Ticket #126: libview_fix_1_of_1_rev_e703c1122501_Removing_hack__correctly_calculating_masDisplayBuffer_and_having_fallback_maxDisplayBuffer_is_set_to_107_characters_.patch
File libview_fix_1_of_1_rev_e703c1122501_Removing_hack__correctly_calculating_masDisplayBuffer_and_having_fallback_maxDisplayBuffer_is_set_to_107_characters_.patch, 14.0 KB (added by , 5 years ago) |
---|
-
Depth16Image.st
# HG changeset patch # User Patrik Svestka <patrik.svestka@gmail.com> # Date 1523348885 -7200 # Tue Apr 10 10:28:05 2018 +0200 # Branch jv # Node ID e703c1122501de5caa16dc5e69a10e09af1467cb # Parent cc53a404d32d213dae19840d3876cecaa2560b27 Removing hack, correctly calculating masDisplayBuffer and having fallback maxDisplayBuffer is set to 107 characters. On windows (7 and up) there is undocumented, you can't find this information anywhere, limit for raster size when using TextOutA or TextOutW. Experimentally, I have come to the conclusion that the limit is most likely set to 16384 points of the raster. To correctly calculate the maximum display buffer (maxDisplayBuffer) I have come to a formula: maxDisplayBuffer = 16384 / (maxWidth + tmet.tmOverhang); maxWidth is the maximum selected font width tmet.tmOverhang is the "extra width per string that may be added to some synthesized fonts." -> If you want to get the actual width you have to add it to maxWidth. You will get the whole extent then. (For most fonts tmOverhang will be 0.) The whole definition of tmOverhang from MSND - https://msdn.microsoft.com/en-us/library/windows/desktop/dd145132(v=vs.85).aspx diff -r cc53a404d32d -r e703c1122501 Depth16Image.st
a b 204 204 "return the number of bytes in one scanline of the image" 205 205 206 206 ^ width * 2. 207 ! 208 209 isDepth16Image 210 "return true if the image is instance of Depth16Image" 211 (self bitsPerPixel == 16) ifTrue:[^ true]. 212 ^ false 213 214 "Created: / 16-04-2018 / 16:59:55 / svestkap" 207 215 ! ! 208 216 209 217 !Depth16Image class methodsFor:'documentation'! … … 214 222 215 223 version_CVS 216 224 ^ '$Header$' 225 ! 226 227 version_HG 228 229 ^ '$Changeset: <not expanded> $' 217 230 ! ! 218 231 -
Depth1Image.st
diff -r cc53a404d32d -r e703c1122501 Depth1Image.st
a b 683 683 ^ super colorFromValue:pixelValue. 684 684 ! 685 685 686 isDepth1Image 687 "return true if the image is instance of Depth1Image" 688 (self bitsPerPixel == 1) ifTrue:[^ true]. 689 ^ false 690 691 "Created: / 16-04-2018 / 17:02:34 / svestkap" 692 ! 693 686 694 rgbFromValue:pixelValue 687 695 "given a pixel value, return the corresponding 24bit rgbValue (rrggbb, red is MSB). 688 696 Pixel values start with 0." -
Depth24Image.st
diff -r cc53a404d32d -r e703c1122501 Depth24Image.st
a b 1 "{ Encoding: utf8 }"2 3 1 " 4 2 COPYRIGHT (c) 1993 by Claus Gittinger 5 3 All Rights Reserved … … 3352 3350 ^ -8 3353 3351 ! 3354 3352 3353 isDepth24Image 3354 "return true if the image is instance of Depth24Image" 3355 (self bitsPerPixel == 24) ifTrue:[^ true]. 3356 ^ false 3357 3358 "Created: / 16-04-2018 / 16:53:00 / svestkap" 3359 ! 3360 3355 3361 redBitsOf:pixel 3356 3362 "given a pixel-value, return the red component as byteValue (0..255)" 3357 3363 -
Depth2Image.st
diff -r cc53a404d32d -r e703c1122501 Depth2Image.st
a b 968 968 ^ super colorFromValue:colorValue. 969 969 ! 970 970 971 isDepth2Image 972 "return true if the image is instance of Depth2Image" 973 (self bitsPerPixel == 2) ifTrue:[^ true]. 974 ^ false 975 976 "Created: / 16-04-2018 / 17:02:16 / svestkap" 977 ! 978 971 979 usedColors 972 980 "return a collection of colors used in the receiver. 973 981 For depth2 images, we return the colorMap here, assuming all -
Depth32Image.st
diff -r cc53a404d32d -r e703c1122501 Depth32Image.st
a b 1078 1078 ^ true 1079 1079 ! 1080 1080 1081 isDepth32Image 1082 "return true if the image is instance of Depth32Image" 1083 (self bitsPerPixel == 32) ifTrue:[^ true]. 1084 ^ false 1085 1086 "Created: / 16-04-2018 / 17:00:39 / svestkap" 1087 ! 1088 1081 1089 redBitsOf:pixel 1082 1090 "given a pixel-value, return the red component as byteValue (0..255)" 1083 1091 -
Depth48Image.st
diff -r cc53a404d32d -r e703c1122501 Depth48Image.st
a b 134 134 "return the number of bytes in one scanline of the image" 135 135 136 136 ^ width * 6. 137 ! 138 139 isDepth48Image 140 "return true if the image is instance of Depth48Image" 141 (self bitsPerPixel == 48) ifTrue:[^ true]. 142 ^ false 143 144 "Created: / 16-04-2018 / 17:02:03 / svestkap" 137 145 ! ! 138 146 139 147 !Depth48Image class methodsFor:'documentation'! 140 148 141 149 version 142 150 ^ '$Header$' 151 ! 152 153 version_HG 154 155 ^ '$Changeset: <not expanded> $' 143 156 ! ! 144 157 -
Depth4Image.st
diff -r cc53a404d32d -r e703c1122501 Depth4Image.st
a b 1024 1024 ^ super colorFromValue:pixelValue 1025 1025 ! 1026 1026 1027 isDepth4Image 1028 "return true if the image is instance of Depth4Image" 1029 (self bitsPerPixel == 4) ifTrue:[^ true]. 1030 ^ false 1031 1032 "Created: / 16-04-2018 / 17:01:45 / svestkap" 1033 ! 1034 1027 1035 usedValues 1028 1036 "return a collection of color values used in the receiver." 1029 1037 -
Depth64Image.st
diff -r cc53a404d32d -r e703c1122501 Depth64Image.st
a b 140 140 141 141 hasAlphaChannel 142 142 ^ true 143 ! 144 145 isDepth64Image 146 "return true if the image is instance of Depth64Image" 147 (self bitsPerPixel == 64) ifTrue:[^ true]. 148 ^ false 149 150 "Created: / 16-04-2018 / 17:01:31 / svestkap" 143 151 ! ! 144 152 145 153 !Depth64Image class methodsFor:'documentation'! -
Depth8Image.st
diff -r cc53a404d32d -r e703c1122501 Depth8Image.st
a b 1 "{ Encoding: utf8 }"2 3 1 " 4 2 COPYRIGHT (c) 1993 by Claus Gittinger 5 3 All Rights Reserved … … 2586 2584 ^ super colorFromValue:pixelValue 2587 2585 ! 2588 2586 2587 isDepth8Image 2588 "return true if the image is instance of Depth8Image" 2589 (self bitsPerPixel == 8) ifTrue:[^ true]. 2590 ^ false 2591 2592 "Created: / 16-04-2018 / 17:01:10 / svestkap" 2593 ! 2594 2589 2595 nColorsUsed 2590 2596 ^ colorMap size 2591 2597 ! -
WinWorkstation.st
diff -r cc53a404d32d -r e703c1122501 WinWorkstation.st
a b 10777 10777 SIZE size; 10778 10778 TEXTMETRICW tmet; 10779 10779 short maxDisplayBuffer; 10780 int i1, i2, n, l, getMetricsResult, maxWidth, toDisplay; 10780 int i1, i2, n, l; 10781 int maxWidth, toDisplay; 10781 10782 int nInstBytes; 10782 10783 10783 10784 if (__isExternalAddress(aGCId) … … 10814 10815 } 10815 10816 } 10816 10817 10817 /* Windows (as in 7 or newer) limits the string size for TextOut* changes 10818 according to the font size! There is apparently an undocumented limit to 10819 the overall raster size. The maximum value for the raster size is 16384. */ 10820 10821 10822 // GetTextMetricsW gives all needed font metrics 10823 // If for any reason it does not work there is a fallback 10818 /* The Windows (as in 7 or newer) limits the string size for TextOut*. There is apparently 10819 * an undocumented limit to the overall raster size. It changes according to the font size (width)! 10820 * The maximum value for the raster size is apparently 16384 (experimentally tested on Windows 7). 10821 */ 10822 10823 10824 /* GetTextMetricsW gives all needed font metrics (has a fallback when fails) 10825 * - a maxWidth parameter takes in account the worst case scenario - user prints 10826 * with the widest possible characters from the selected font. 10827 * - a overHang is a parameter which allows the font to grow outside the maxWidth size 10828 */ 10829 10824 10830 if (GetTextMetricsW(hDC, &tmet)) { 10825 10831 maxWidth = tmet.tmMaxCharWidth; 10832 // Dynamically calculate the maximum buffer size for the selected font and its size 10833 maxDisplayBuffer = 16384 / (maxWidth + tmet.tmOverhang); 10826 10834 } else { 10827 static char *s = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzコーヒーアイスクリームケーキビールすしかき";10828 static int len;10829 10830 if (len == 0) {10831 len = strlen(s);10832 }10833 assert(GetTextExtentPoint32(hDC, s, len, &size) != 0 && "GetTextExtentPoint32 != 0, fix me");10834 max Width = size.cx / (len / 2) + 1;10835 /* A fallback when GetTextMetricsW fails. Should not normally happen! 10836 * The works case scenario, experimentally tested from 1170 fonts, is Microsoft Uighur-build-italic-288 10837 * with maxWidth = 2179. That would mean only 7 characters at the maxDisplayBuffer (16384 / 2179). 10838 * Such a buffer would be rediculously slow!. A compromise is needed (speed vs. functionality) 10839 * Taking an avgWidth from all 1170 with fonts size 96pt -> avgWidth = 152, 10840 * which should suffice 99.9% of time. The buffer would then be int(16384/152) = 107, which is reasonable. 10841 */ 10842 maxDisplayBuffer = 107; 10835 10843 } 10836 10844 10837 // Calculate the maximum buffer size for the selected font size10838 maxDisplayBuffer = 16384 / (maxWidth + tmet.tmOverhang);10839 10840 // Debug messages10841 // PRINTF(("MaxDisplayBuffer:%d\n", maxDisplayBuffer));10842 //PRINTF(("MaxWidth:%d; overHang:%d\n", maxWidth, tmet.tmOverhang));10843 10844 10845 #if 0 10845 10846 /* leftover code from tries to make TextOut honor the gc-mode, 10846 10847 * until I googled, that TextOut does not (by purpose, or backward-bug compatibility) -
new file tests/FontTests.st
diff -r cc53a404d32d -r e703c1122501 tests/FontTests.st
- + 1 "{ Encoding: utf8 }" 2 3 "{ Package: 'stx:libview/tests' }" 4 5 "{ NameSpace: Smalltalk }" 6 7 TestCase subclass:#FontTests 8 instanceVariableNames:'testFontSize fontList testString startTimer topView textView' 9 classVariableNames:'' 10 poolDictionaries:'' 11 category:'TestCases' 12 ! 13 14 !FontTests class methodsFor:'documentation'! 15 16 documentation 17 " 18 documentation to be added. 19 20 [author:] 21 svestkap 22 23 [instance variables:] 24 25 [class variables:] 26 27 [see also:] 28 29 " 30 ! ! 31 32 !FontTests methodsFor:'initialize / release'! 33 34 setUp 35 36 | numberOfTestedFonts windowWidthX windowHightY | 37 self skipIf: Screen current isNil description: 'No display connection'. 38 39 "/init 40 startTimer := Time now. 41 numberOfTestedFonts := 100. 42 43 "/random font size to circumvent ascanding or descending font size bugs 44 testFontSize := #(6 12 24 48 96 288) shuffled. 45 46 "/pick random fonts available at system 47 fontList := (Display listOfAvailableFonts) shuffled. 48 fontList := ((fontList size) > numberOfTestedFonts) ifTrue: [fontList copyFrom:1 to: numberOfTestedFonts]. 49 50 "/Japanese characters for UTF-16 testing 51 testString := Unicode16String new. 52 testString := 'コーヒーアイスクリームケーキビールすしかき空'. 53 54 "/creating a long string to be displayed at textView 55 10 timesRepeat:[testString := testString,testString]. 56 57 "/set testing window size -> large for large font testing (will probably fail for smaller) 58 windowWidthX := 640. 59 windowHightY := 400. 60 61 topView := StandardSystemView new. 62 topView extent:windowWidthX @ windowHightY. 63 topView label:'TextOut Raster testing with different font sizes and large strings'. 64 textView := EditTextView origin:0.0 @ 0.0 extent:1.0 @ 1.0 in:topView. 65 "/if styles are present, make sure we have correct setup 66 textView backgroundColor: Color white; 67 foregroundColor: Color black. 68 69 topView open. 70 topView waitUntilVisible. 71 72 "Modified: / 06-04-2018 / 14:44:17 / svestkap" 73 "Modified (comment): / 25-04-2018 / 12:09:18 / svestkap" 74 ! 75 76 tearDown 77 "common cleanup - invoked after testing." 78 | endTimer message | 79 endTimer := Time now. 80 81 "/left here for user overview when run manually 82 "/Transcript showCR: 'FontTests time duration: '; showCR:(endTimer - startTimer) asString. 83 84 message := 'FontTests time duration: ', (endTimer - startTimer) asString. 85 Logger log: message severity: #info. 86 87 topView isOpen ifTrue:[ topView close ]. 88 89 "Modified (format): / 25-04-2018 / 12:05:24 / svestkap" 90 ! ! 91 92 !FontTests methodsFor:'tests'! 93 94 test_issue_126_TextOut_raster_size_24bit 95 " Testing long strings display. 96 The test takes shown textView and tries to find out non-white pixels. 97 98 For more visit: https://swing.fit.cvut.cz/projects/stx-jv/ticket/126" 99 | font imageSnapshot | 100 101 self skipIf: Screen current depth ~~ 24 description: 'Different than 24bit resulution'. 102 103 font := fontList atRandom. 104 105 fontList do:[:font | 106 testFontSize do:[:preselectedFontSize | | setFontSize fontAtSize bits | 107 [ textView contents: testString. 108 (font size = 0.0) ifTrue:[setFontSize := preselectedFontSize] "/TrueType font 109 ifFalse:[setFontSize := font size]. "/Raster font 110 fontAtSize := (font copy asSize:setFontSize) onDevice:textView device. 111 textView font:fontAtSize. 112 113 imageSnapshot := Image fromView:textView grab:false. 114 self assert:(imageSnapshot photometric == #rgb). 115 self assert:(imageSnapshot isDepth24Image). 116 117 bits := imageSnapshot bits. 118 self assert:(bits contains:[:bit | bit ~~ 255 ]). 119 ] ensure:[textView contents:nil]. 120 ] 121 ]. 122 123 " 124 FontTests run: #test_issue_126_TextOut_raster_size_24bit 125 FontTests debug: #test_issue_126_TextOut_raster_size_24bit 126 " 127 128 "Created: / 05-04-2018 / 12:16:57 / svestkap" 129 "Modified: / 25-04-2018 / 10:19:35 / svestkap" 130 "Modified (format): / 25-04-2018 / 11:45:40 / svestkap" 131 ! ! 132 133 !FontTests class methodsFor:'documentation'! 134 135 version_HG 136 137 ^ '$Changeset: <not expanded> $' 138 ! ! 139 -
tests/stx_libview_tests.st
diff -r cc53a404d32d -r e703c1122501 tests/stx_libview_tests.st
a b 75 75 ^ #( 76 76 "<className> or (<className> attributes...) in load order" 77 77 FcPatternTests 78 FontTests 78 79 FormTests 79 80 ImageTests 80 81 ResourcePackTests