<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"><<a href="mailto:commits@source.squeak.org" target="_blank">commits@source.squeak.org</a>></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>>isPairKerningCapable (in category 'testing') -----<br>
+ isPairKerningCapable<br>
+ "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"<br>
+ ^false!<br>
<br>
Item was removed:<br>
- ----- Method: AbstractFont>>widthAndKernedWidthOfLeft:right:into: (in category 'kerning') -----<br>
- widthAndKernedWidthOfLeft: leftCharacter right: rightCharacterOrNil into: aTwoElementArray<br>
- "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"<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>>basicScanCharactersFrom:to:in:rightX:stopConditions:kern: (in category 'scanning') -----<br>
+ basicScanCharactersFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops kern: kernDelta<br>
+ "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'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"<br>
+ | ascii nextDestX char |<br>
- basicScanCharactersFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops kern: kernDelta<br>
- "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>
- | ascii nextDestX char floatDestX widthAndKernedWidth nextChar atEndOfRun |<br>
- <primitive: 103><br>
lastIndex := startIndex.<br>
- floatDestX := destX.<br>
- widthAndKernedWidth := Array new: 2.<br>
- atEndOfRun := false.<br>
[lastIndex <= stopIndex]<br>
+ whileTrue: [<br>
+ "get the character value"<br>
+ char := sourceString at: lastIndex.<br>
- whileTrue:<br>
- [char := (sourceString at: lastIndex).<br>
ascii := char asciiValue + 1.<br>
+ "if there is an entry in 'stops' for this value, return it"<br>
+ (stops at: ascii)<br>
+ ifNotNil: [^ stops at: ascii].<br>
+ "bump nextDestX by the width of the current character"<br>
+ nextDestX := destX + (font widthOf: char).<br>
+ "if the next x is past the right edge, return crossedX"<br>
+ nextDestX > rightX<br>
+ ifTrue: [^ stops crossedX].<br>
+ "update destX and incorporate thr kernDelta"<br>
+ destX := nextDestX + kernDelta.<br>
- (stops at: ascii) == nil ifFalse: [^stops at: ascii].<br>
- "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."<br>
- nextChar := (lastIndex + 1 <= stopIndex)<br>
- ifTrue:[sourceString at: lastIndex + 1]<br>
- ifFalse:[<br>
- atEndOfRun := true.<br>
- "if there is a next char in sourceString, then get the kern<br>
- and store it in pendingKernX"<br>
- lastIndex + 1 <= 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 > 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>>basicScanKernableCharactersFrom:to:in:rightX:stopConditions:kern: (in category 'scanning') -----<br>
+ basicScanKernableCharactersFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops kern: kernDelta<br>
+ "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'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"<br>
+ | ascii nextDestX char floatDestX widthAndKernedWidth nextCharOrNil atEndOfRun |<br>
+ lastIndex := startIndex.<br>
+ floatDestX := destX.<br>
+ widthAndKernedWidth := Array new: 2.<br>
+ atEndOfRun := false.<br>
+ [lastIndex <= stopIndex]<br>
+ whileTrue: [<br>
+ "get the character value"<br>
+ char := sourceString at: lastIndex.<br>
+ ascii := char asciiValue + 1.<br>
+ "if there is an entry in 'stops' for this value, return it"<br>
+ (stops at: ascii)<br>
+ ifNotNil: [^ stops at: ascii].<br>
+ "get the next character..."<br>
+ nextCharOrNil := lastIndex + 1 <= stopIndex<br>
+ ifTrue: [sourceString at: lastIndex + 1]<br>
+ ifFalse: ["if we're at or past the stopIndex, see if there is anything in the full string"<br>
+ atEndOfRun := true.<br>
+ lastIndex + 1 <= sourceString size<br>
+ ifTrue: [sourceString at: lastIndex + 1]].<br>
+ "get the font's kerning info for the pair of current character and next character"<br>
+ "for almost all fonts in common use this is a waste of time since they don't support pair kerning and both values are #widthOf: char"<br>
+ font<br>
+ widthAndKernedWidthOfLeft: char<br>
+ right: nextCharOrNil<br>
+ into: widthAndKernedWidth.<br>
+ "bump nextDestX by the width of the current character"<br>
+ nextDestX := floatDestX<br>
+ + (widthAndKernedWidth at: 1).<br>
+ "if the next x is past the right edge, return crossedX"<br>
+ nextDestX > rightX<br>
+ ifTrue: [^ stops crossedX].<br>
+ "bump floatDestX by the *kerned* width of the current<br>
+ character, which is where the *next* char will go"<br>
+ floatDestX := floatDestX + kernDelta<br>
+ + (widthAndKernedWidth at: 2).<br>
+ "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"<br>
+ atEndOfRun<br>
+ ifTrue: [pendingKernX := (widthAndKernedWidth at: 2)<br>
+ - (widthAndKernedWidth at: 1).<br>
+ floatDestX := floatDestX - pendingKernX].<br>
+ "save the next x for next time around the loop"<br>
+ destX := floatDestX.<br>
+ lastIndex := lastIndex + 1].<br>
+ lastIndex := stopIndex.<br>
+ ^ stops endOfRun!<br>
<br>
Item was added:<br>
+ ----- Method: CharacterScanner>>historicalScanCharactersFrom:to:in:rightX:stopConditions:kern: (in category 'scanning') -----<br>
+ historicalScanCharactersFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops kern: kernDelta<br>
+ "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"<br>
+ | ascii nextDestX char |<br>
+ <primitive: 103><br>
+ lastIndex _ startIndex.<br>
+ [lastIndex <= stopIndex]<br>
+ whileTrue:<br>
+ [char _ (sourceString at: lastIndex).<br>
+ ascii _ char asciiValue + 1.<br>
+ (stops at: ascii) == nil ifFalse: [^stops at: ascii].<br>
+ "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."<br>
+ nextDestX _ destX + (font widthOf: char).<br>
+ nextDestX > 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>>isBreakableAtIndex: (in category 'scanner methods') -----<br>
isBreakableAtIndex: index<br>
+ "appears t obe unused - cf MultiCharacterScanner>isBreakableAt:in:in"<br>
-<br>
^ (EncodedCharSet at: ((text at: index) leadingChar + 1)) isBreakableAt: index in: text.<br>
!<br>
<br>
Item was changed:<br>
----- Method: CharacterScanner>>scanCharactersFrom:to:in:rightX:stopConditions:kern: (in category 'scanning') -----<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 > 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 > 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>>scanMultiCharactersCombiningFrom:to:in:rightX:stopConditions:kern: (in category 'scanner methods') -----<br>
- scanMultiCharactersCombiningFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops kern: kernDelta<br>
- "Implement a workaround for unicode composing.<br>
- a MultiCharacterScanner should better be used to handle combination."<br>
-<br>
- ^self scanMultiCharactersFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops kern: kernDelta!<br>
<br>
<br>
</blockquote></div><br></div>