<div dir="ltr">Please tim, := assignments would be much appreciated :)<br></div><div class="gmail_extra"><br><br><div class="gmail_quote">2013/9/23  <span dir="ltr">&lt;<a href="mailto:commits@source.squeak.org" target="_blank">commits@source.squeak.org</a>&gt;</span><br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">tim Rowledge uploaded a new version of Graphics to project The Trunk:<br>
<a href="http://source.squeak.org/trunk/Graphics-tpr.226.mcz" target="_blank">http://source.squeak.org/trunk/Graphics-tpr.226.mcz</a><br>
<br>
==================== Summary ====================<br>
<br>
Name: Graphics-tpr.226<br>
Author: tpr<br>
Time: 23 September 2013, 12:42:11.34 pm<br>
UUID: 842c37b1-aab4-41a7-b8ff-1411a96c4590<br>
Ancestors: Graphics-tpr.225<br>
<br>
A first step in improvingthe characterscanner tree(s);<br>
mostly split out kerning and non-kerning scanning. Also add some guide comments for later parts of the work, so some methods are only changed in comment.<br>
<br>
=============== Diff against Graphics-tpr.225 ===============<br>
<br>
Item was added:<br>
+ ----- Method: AbstractFont&gt;&gt;isPairKerningCapable (in category &#39;testing&#39;) -----<br>
+ isPairKerningCapable<br>
+ &quot;a hopefully temporary test method; better factoring of scan/measure/display should remove the need for it.<br>
+ Only FreeType fonts would currently add this to return true&quot;<br>
+       ^false!<br>
<br>
Item was removed:<br>
- ----- Method: AbstractFont&gt;&gt;widthAndKernedWidthOfLeft:right:into: (in category &#39;kerning&#39;) -----<br>
- widthAndKernedWidthOfLeft: leftCharacter right: rightCharacterOrNil into: aTwoElementArray<br>
-       &quot;Set the first element of aTwoElementArray to the width of leftCharacter and<br>
-       the second element to the width of left character when kerned with<br>
-       rightCharacterOrNil. Answer aTwoElementArray&quot;<br>
-       | w k |<br>
-       w := self widthOf: leftCharacter.<br>
-       rightCharacterOrNil isNil<br>
-               ifTrue:[<br>
-                       aTwoElementArray<br>
-                               at: 1 put: w;<br>
-                               at: 2 put: w]<br>
-               ifFalse:[<br>
-                       k := self kerningLeft: leftCharacter right: rightCharacterOrNil.<br>
-                       aTwoElementArray<br>
-                               at: 1 put: w;<br>
-                               at: 2 put: w+k].<br>
-       ^aTwoElementArray<br>
-       !<br>
<br>
Item was changed:<br>
  ----- Method: CharacterScanner&gt;&gt;basicScanCharactersFrom:to:in:rightX:stopConditions:kern: (in category &#39;scanning&#39;) -----<br>
+ basicScanCharactersFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops kern: kernDelta<br>
+       &quot;In ancient days this would have called primitive 103 to scan a string with StrikeFont, but time moves on. See historicalScanCharactersFrom:to:in:rightX:stopConditions:kern: if you&#39;re curious. This code handles the newer shape of CharacterScanner but does *no* pair kerning.<br>

+       There is a pretty deep assumption of simple ASCII strings and characters - beware&quot;<br>
+       | ascii nextDestX char |<br>
- basicScanCharactersFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops kern: kernDelta<br>
-       &quot;Primitive. This is the inner loop of text display--but see<br>
-       scanCharactersFrom: to:rightX: which would get the string,<br>
-       stopConditions and displaying from the instance. March through source<br>
-       String from startIndex to stopIndex. If any character is flagged with a<br>
-       non-nil entry in stops, then return the corresponding value. Determine<br>
-       width of each character from xTable, indexed by map.<br>
-       If dextX would exceed rightX, then return stops at: 258.<br>
-       Advance destX by the width of the character. If stopIndex has been<br>
-       reached, then return stops at: 257. Optional.<br>
-       See Object documentation whatIsAPrimitive.&quot;<br>
-       | ascii nextDestX char  floatDestX widthAndKernedWidth nextChar atEndOfRun |<br>
-       &lt;primitive: 103&gt;<br>
        lastIndex := startIndex.<br>
-       floatDestX := destX.<br>
-       widthAndKernedWidth := Array new: 2.<br>
-       atEndOfRun := false.<br>
        [lastIndex &lt;= stopIndex]<br>
+               whileTrue: [<br>
+                       &quot;get the character value&quot;<br>
+                       char := sourceString at: lastIndex.<br>
-               whileTrue:<br>
-                       [char := (sourceString at: lastIndex).<br>
                        ascii := char asciiValue + 1.<br>
+                       &quot;if there is an entry in &#39;stops&#39; for this value, return it&quot;<br>
+                       (stops at: ascii)<br>
+                               ifNotNil: [^ stops at: ascii].<br>
+                       &quot;bump nextDestX by the width of the current character&quot;<br>
+                       nextDestX := destX + (font widthOf: char).<br>
+                       &quot;if the next x is past the right edge, return crossedX&quot;<br>
+                       nextDestX &gt; rightX<br>
+                               ifTrue: [^ stops crossedX].<br>
+                       &quot;update destX and incorporate thr kernDelta&quot;<br>
+                       destX := nextDestX + kernDelta.<br>
-                       (stops at: ascii) == nil ifFalse: [^stops at: ascii].<br>
-                       &quot;Note: The following is querying the font about the width<br>
-                       since the primitive may have failed due to a non-trivial<br>
-                       mapping of characters to glyphs or a non-existing xTable.&quot;<br>
-                       nextChar := (lastIndex + 1 &lt;= stopIndex)<br>
-                               ifTrue:[sourceString at: lastIndex + 1]<br>
-                               ifFalse:[<br>
-                                       atEndOfRun := true.<br>
-                                       &quot;if there is a next char in sourceString, then get the kern<br>
-                                       and store it in pendingKernX&quot;<br>
-                                       lastIndex + 1 &lt;= sourceString size<br>
-                                               ifTrue:[sourceString at: lastIndex + 1]<br>
-                                               ifFalse:[       nil]].<br>
-                       font<br>
-                               widthAndKernedWidthOfLeft: char<br>
-                               right: nextChar<br>
-                               into: widthAndKernedWidth.<br>
-                       nextDestX := floatDestX + (widthAndKernedWidth at: 1).<br>
-                       nextDestX &gt; rightX ifTrue: [^stops crossedX].<br>
-                       floatDestX := floatDestX + kernDelta + (widthAndKernedWidth at: 2).<br>
-                       atEndOfRun<br>
-                               ifTrue:[<br>
-                                       pendingKernX := (widthAndKernedWidth at: 2) - (widthAndKernedWidth at: 1).<br>
-                                       floatDestX := floatDestX - pendingKernX].<br>
-                       destX := floatDestX.<br>
                        lastIndex := lastIndex + 1].<br>
        lastIndex := stopIndex.<br>
+       ^ stops endOfRun!<br>
-       ^stops endOfRun!<br>
<br>
Item was added:<br>
+ ----- Method: CharacterScanner&gt;&gt;basicScanKernableCharactersFrom:to:in:rightX:stopConditions:kern: (in category &#39;scanning&#39;) -----<br>
+ basicScanKernableCharactersFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops kern: kernDelta<br>
+       &quot;In ancient days this would have called primitive 103 to scan a string with StrikeFont, but time moves on. See historicalScanCharactersFrom:to:in:rightX:stopConditions:kern: if you&#39;re curious. This code handles the newer shape of CharacterScanner and provides some support for fonts that have pair-kerning; this may be removable with some better factoring.<br>

+       There is a pretty deep assumption of simple ASCII strings and characters - beware&quot;<br>
+       | ascii nextDestX char floatDestX widthAndKernedWidth nextCharOrNil atEndOfRun |<br>
+       lastIndex := startIndex.<br>
+       floatDestX := destX.<br>
+       widthAndKernedWidth := Array new: 2.<br>
+       atEndOfRun := false.<br>
+       [lastIndex &lt;= stopIndex]<br>
+               whileTrue: [<br>
+                       &quot;get the character value&quot;<br>
+                       char := sourceString at: lastIndex.<br>
+                       ascii := char asciiValue + 1.<br>
+                       &quot;if there is an entry in &#39;stops&#39; for this value, return it&quot;<br>
+                       (stops at: ascii)<br>
+                               ifNotNil: [^ stops at: ascii].<br>
+                       &quot;get the next character...&quot;<br>
+                       nextCharOrNil := lastIndex + 1 &lt;= stopIndex<br>
+                                               ifTrue: [sourceString at: lastIndex + 1]<br>
+                                               ifFalse: [&quot;if we&#39;re at or past the stopIndex, see if there is anything in the full string&quot;<br>
+                                                       atEndOfRun := true.<br>
+                                                       lastIndex + 1 &lt;= sourceString size<br>
+                                                               ifTrue: [sourceString at: lastIndex + 1]].<br>
+                       &quot;get the font&#39;s kerning info for the pair of current character and next character&quot;<br>
+                       &quot;for almost all fonts in common use this is a waste of time since they don&#39;t support pair kerning and both values are #widthOf: char&quot;<br>
+                       font<br>
+                               widthAndKernedWidthOfLeft: char<br>
+                               right: nextCharOrNil<br>
+                               into: widthAndKernedWidth.<br>
+                       &quot;bump nextDestX by the width of the current character&quot;<br>
+                       nextDestX := floatDestX<br>
+                                               + (widthAndKernedWidth at: 1).<br>
+                       &quot;if the next x is past the right edge, return crossedX&quot;<br>
+                       nextDestX &gt; rightX<br>
+                               ifTrue: [^ stops crossedX].<br>
+                       &quot;bump floatDestX by the *kerned* width of the current<br>
+                       character, which is where the *next* char will go&quot;<br>
+                       floatDestX := floatDestX + kernDelta<br>
+                                               + (widthAndKernedWidth at: 2).<br>
+                       &quot;if we are at the end of this run we keep track of the<br>
+                       character-kern-delta for possible later use and then rather<br>
+                       insanely remove that character-kern-delta from floatDestX,<br>
+                       making it equivalent to (old floatDestX) + kernDelta +<br>
+                       width-of-character - no idea why&quot;<br>
+                       atEndOfRun<br>
+                               ifTrue: [pendingKernX := (widthAndKernedWidth at: 2)<br>
+                                                               - (widthAndKernedWidth at: 1).<br>
+                                       floatDestX := floatDestX - pendingKernX].<br>
+                       &quot;save the next x for next time around the loop&quot;<br>
+                       destX := floatDestX.<br>
+                       lastIndex := lastIndex + 1].<br>
+       lastIndex := stopIndex.<br>
+       ^ stops endOfRun!<br>
<br>
Item was added:<br>
+ ----- Method: CharacterScanner&gt;&gt;historicalScanCharactersFrom:to:in:rightX:stopConditions:kern: (in category &#39;scanning&#39;) -----<br>
+ historicalScanCharactersFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops kern: kernDelta<br>
+       &quot;Primitive. This is the inner loop of text display--but see<br>
+       scanCharactersFrom: to:rightX: which would get the string,<br>
+       stopConditions and displaying from the instance. March through source<br>
+       String from startIndex to stopIndex. If any character is flagged with a<br>
+       non-nil entry in stops, then return the corresponding value. Determine<br>
+       width of each character from xTable, indexed by map.<br>
+       If dextX would exceed rightX, then return stops at: 258.<br>
+       Advance destX by the width of the character. If stopIndex has been<br>
+       reached, then return stops at: 257. Optional.<br>
+       See Object documentation whatIsAPrimitive.<br>
+       Historical note: this primitive has been unusable since about Squeak 2.8 when the shape of the CharracterScanner class changed. It is left here as a reminder that the actual primitive still needs supporting in the VM to keep old images such as Scratch1.4 alive - tpr&quot;<br>

+       | ascii nextDestX char |<br>
+       &lt;primitive: 103&gt;<br>
+       lastIndex _ startIndex.<br>
+       [lastIndex &lt;= stopIndex]<br>
+               whileTrue:<br>
+                       [char _ (sourceString at: lastIndex).<br>
+                       ascii _ char asciiValue + 1.<br>
+                       (stops at: ascii) == nil ifFalse: [^stops at: ascii].<br>
+                       &quot;Note: The following is querying the font about the width<br>
+                       since the primitive may have failed due to a non-trivial<br>
+                       mapping of characters to glyphs or a non-existing xTable.&quot;<br>
+                       nextDestX _ destX + (font widthOf: char).<br>
+                       nextDestX &gt; rightX ifTrue: [^stops at: CrossedX].<br>
+                       destX _ nextDestX + kernDelta.<br>
+                       lastIndex _ lastIndex + 1].<br>
+       lastIndex _ stopIndex.<br>
+       ^stops at: EndOfRun<br>
+ !<br>
<br>
Item was changed:<br>
  ----- Method: CharacterScanner&gt;&gt;isBreakableAtIndex: (in category &#39;scanner methods&#39;) -----<br>
  isBreakableAtIndex: index<br>
+ &quot;appears t obe unused - cf MultiCharacterScanner&gt;isBreakableAt:in:in&quot;<br>
-<br>
        ^ (EncodedCharSet at: ((text at: index) leadingChar + 1)) isBreakableAt: index in: text.<br>
  !<br>
<br>
Item was changed:<br>
  ----- Method: CharacterScanner&gt;&gt;scanCharactersFrom:to:in:rightX:stopConditions:kern: (in category &#39;scanning&#39;) -----<br>
+ scanCharactersFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops kern: kernDelta<br>
- scanCharactersFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops kern: kernDelta<br>
-<br>
        | startEncoding selector |<br>
+       sourceString isByteString<br>
+               ifTrue: [font isPairKerningCapable<br>
+                               ifTrue: [^ self<br>
+                                               basicScanKernableCharactersFrom: startIndex<br>
+                                               to: (stopIndex min: sourceString size)<br>
+                                               in: sourceString<br>
+                                               rightX: rightX<br>
+                                               stopConditions: stops<br>
+                                               kern: kernDelta]<br>
+                               ifFalse: [^ self<br>
+                                               basicScanCharactersFrom: startIndex<br>
+                                               to: (stopIndex min: sourceString size)<br>
+                                               in: sourceString<br>
+                                               rightX: rightX<br>
+                                               stopConditions: stops<br>
+                                               kern: kernDelta]].<br>
+       sourceString isWideString<br>
+               ifTrue: [startIndex &gt; stopIndex<br>
+                               ifTrue: [lastIndex := stopIndex.<br>
+                                       ^ stops endOfRun].<br>
+                       startEncoding := (sourceString at: startIndex) leadingChar.<br>
+                       selector := EncodedCharSet scanSelectorAt: startEncoding.<br>
+                       ^ self<br>
+                               perform: selector<br>
+                               withArguments: (Array<br>
+                                               with: startIndex<br>
+                                               with: stopIndex<br>
+                                               with: sourceString<br>
+                                               with: rightX<br>
+                                               with: stops<br>
+                                               with: kernDelta)].<br>
+       ^ stops endOfRun!<br>
-       (sourceString isByteString) ifTrue: [^ self basicScanCharactersFrom: startIndex to: (stopIndex min: sourceString size) in: sourceString rightX: rightX stopConditions: stops kern: kernDelta.].<br>
-<br>
-       (sourceString isWideString) ifTrue: [<br>
-               startIndex &gt; stopIndex ifTrue: [lastIndex := stopIndex. ^ stops endOfRun].<br>
-               startEncoding :=  (sourceString at: startIndex) leadingChar.<br>
-               selector := EncodedCharSet scanSelectorAt: startEncoding.<br>
-               ^ self perform: selector withArguments: (Array with: startIndex with: stopIndex with: sourceString with: rightX with: stops with: kernDelta).<br>
-       ].<br>
-<br>
-       ^ stops endOfRun<br>
- !<br>
<br>
Item was removed:<br>
- ----- Method: CharacterScanner&gt;&gt;scanMultiCharactersCombiningFrom:to:in:rightX:stopConditions:kern: (in category &#39;scanner methods&#39;) -----<br>
- scanMultiCharactersCombiningFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops kern: kernDelta<br>
-       &quot;Implement a workaround for unicode composing.<br>
-       a MultiCharacterScanner should better be used to handle combination.&quot;<br>
-<br>
-       ^self scanMultiCharactersFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops kern: kernDelta!<br>
<br>
<br>
</blockquote></div><br></div>