Nicolas Cellier uploaded a new version of Graphics to project The Trunk:
http://source.squeak.org/trunk/Graphics-nice.238.mcz
==================== Summary ====================
Name: Graphics-nice.238
Author: nice
Time: 29 September 2013, 7:06:35.509 pm
UUID: f7a0533e-2b32-4908-8666-d26204334a6e
Ancestors: Graphics-nice.237
Take font baseKern into account when measuring a String (a small diff with defunct Multi*).
Create a specially crafted MeasuringStopConditions and use it when measuringString.
This way, initializeStringMeasurer is no longer required and deprecated.
=============== Diff against Graphics-nice.237 ===============
Item was changed:
Object subclass: #CharacterScanner
instanceVariableNames: 'destX lastIndex destY stopConditions text textStyle alignment leftMargin rightMargin font line runStopIndex spaceCount spaceWidth emphasisCode kern indentationLevel wantsColumnBreaks pendingKernX'
+ classVariableNames: 'ColumnBreakStopConditions DefaultStopConditions MeasuringStopConditions PaddedSpaceCondition'
- classVariableNames: 'ColumnBreakStopConditions DefaultStopConditions PaddedSpaceCondition'
poolDictionaries: 'TextConstants'
category: 'Graphics-Text'!
!CharacterScanner commentStamp: '<historical>' prior: 0!
My instances hold the state associated with scanning text. My subclasses scan characters for specified purposes, such as computing a CharacterBlock or placing characters into Forms.!
Item was changed:
----- Method: CharacterScanner class>>initialize (in category 'class initialization') -----
initialize
"
CharacterScanner initialize
"
| a |
a := TextStopConditions new.
a at: 1 + 1 put: #embeddedObject.
a at: Space asciiValue + 1 put: #space.
a at: Tab asciiValue + 1 put: #tab.
a at: CR asciiValue + 1 put: #cr.
a at: Character lf asciiValue + 1 put: #cr.
DefaultStopConditions := a copy.
ColumnBreakStopConditions := a copy.
ColumnBreakStopConditions at: TextComposer characterForColumnBreak asciiValue + 1 put: #columnBreak.
PaddedSpaceCondition := a copy.
PaddedSpaceCondition at: Space asciiValue + 1 put: #paddedSpace.
+
+ MeasuringStopConditions := TextStopConditions new!
- !
Item was removed:
- ----- Method: CharacterScanner>>initializeStringMeasurer (in category 'initialize') -----
- initializeStringMeasurer
-
- stopConditions := TextStopConditions new
- !
Item was changed:
----- Method: CharacterScanner>>measureString:inFont:from:to: (in category 'scanning') -----
measureString: aString inFont: aFont from: startIndex to: stopIndex
+ "Measure aString width in given font aFont.
+ The string shall not include line breaking, tab or other control character."
- "WARNING: In order to use this method the receiver has to be set up using #initializeStringMeasurer"
destX := destY := lastIndex := 0.
pendingKernX := 0.
font := aFont.
kern := 0 - font baseKern.
spaceWidth := font widthOf: Space.
+ stopConditions := MeasuringStopConditions.
+ self scanCharactersFrom: startIndex to: stopIndex in: aString rightX: 999999 stopConditions: stopConditions kern: kern.
- self scanCharactersFrom: startIndex to: stopIndex in: aString rightX: 999999 stopConditions: stopConditions kern: 0.
^destX!
Nicolas Cellier uploaded a new version of ST80 to project The Trunk:
http://source.squeak.org/trunk/ST80-nice.151.mcz
==================== Summary ====================
Name: ST80-nice.151
Author: nice
Time: 29 September 2013, 4:35:30.085 pm
UUID: bdd314c3-0f95-4519-82f0-dfc85b76d4a7
Ancestors: ST80-nice.150
Start using the CharacterScanner hierarchy instead of the Multi one.
=============== Diff against ST80-nice.150 ===============
Item was changed:
----- Method: Paragraph>>composeAll (in category 'composition') -----
composeAll
"Compose a collection of characters into a collection of lines."
| startIndex stopIndex lineIndex maximumRightX compositionScanner |
lines := Array new: 32.
lastLine := 0.
maximumRightX := 0.
text size = 0
ifTrue:
[compositionRectangle := compositionRectangle withHeight: 0.
^maximumRightX].
startIndex := lineIndex := 1.
stopIndex := text size.
+ compositionScanner := CompositionScanner new forParagraph: self.
- compositionScanner := MultiCompositionScanner new forParagraph: self.
[startIndex > stopIndex] whileFalse:
[self lineAt: lineIndex
put: (compositionScanner composeLine: lineIndex
fromCharacterIndex: startIndex
inParagraph: self).
maximumRightX := compositionScanner rightX max: maximumRightX.
startIndex := (lines at: lineIndex) last + 1.
lineIndex := lineIndex + 1].
self updateCompositionHeight.
self trimLinesTo: lineIndex - 1.
^ maximumRightX!
Item was changed:
----- Method: Paragraph>>displayLines:affectedRectangle: (in category 'private') -----
displayLines: linesInterval affectedRectangle: affectedRectangle
"This is the first level workhorse in the display portion of the TextForm routines.
It checks to see which lines in the interval are actually visible, has the
CharacterScanner display only those, clears out the areas in which display will
occur, and clears any space remaining in the visibleRectangle following the space
occupied by lastLine."
+ | topY firstLineIndex lastLineIndex lastLineIndexBottom |
- | lineGrid topY firstLineIndex lastLineIndex lastLineIndexBottom |
"Save some time by only displaying visible lines"
firstLineIndex := self lineIndexOfTop: affectedRectangle top.
firstLineIndex < linesInterval first ifTrue: [firstLineIndex := linesInterval first].
lastLineIndex := self lineIndexOfTop: affectedRectangle bottom - 1.
lastLineIndex > linesInterval last ifTrue:
[linesInterval last > lastLine
ifTrue: [lastLineIndex := lastLine]
ifFalse: [lastLineIndex := linesInterval last]].
lastLineIndexBottom := (self bottomAtLineIndex: lastLineIndex).
((Rectangle
origin: affectedRectangle left @ (topY := self topAtLineIndex: firstLineIndex)
corner: affectedRectangle right @ lastLineIndexBottom)
intersects: affectedRectangle)
ifTrue: [ " . . . (skip to clear-below if no lines displayed)"
+ DisplayScanner new
- MultiDisplayScanner new
displayLines: (firstLineIndex to: lastLineIndex)
in: self clippedBy: affectedRectangle].
lastLineIndex = lastLine ifTrue:
[destinationForm "Clear out white space below last line"
fill: (affectedRectangle left @ (lastLineIndexBottom max: affectedRectangle top)
corner: affectedRectangle bottomRight)
rule: rule fillColor: self backgroundColor]!
Nicolas Cellier uploaded a new version of ST80 to project The Trunk:
http://source.squeak.org/trunk/ST80-nice.151.mcz
==================== Summary ====================
Name: ST80-nice.151
Author: nice
Time: 29 September 2013, 4:35:30.085 pm
UUID: bdd314c3-0f95-4519-82f0-dfc85b76d4a7
Ancestors: ST80-nice.150
Start using the CharacterScanner hierarchy instead of the Multi one.
=============== Diff against ST80-nice.150 ===============
Item was changed:
----- Method: Paragraph>>composeAll (in category 'composition') -----
composeAll
"Compose a collection of characters into a collection of lines."
| startIndex stopIndex lineIndex maximumRightX compositionScanner |
lines := Array new: 32.
lastLine := 0.
maximumRightX := 0.
text size = 0
ifTrue:
[compositionRectangle := compositionRectangle withHeight: 0.
^maximumRightX].
startIndex := lineIndex := 1.
stopIndex := text size.
+ compositionScanner := CompositionScanner new forParagraph: self.
- compositionScanner := MultiCompositionScanner new forParagraph: self.
[startIndex > stopIndex] whileFalse:
[self lineAt: lineIndex
put: (compositionScanner composeLine: lineIndex
fromCharacterIndex: startIndex
inParagraph: self).
maximumRightX := compositionScanner rightX max: maximumRightX.
startIndex := (lines at: lineIndex) last + 1.
lineIndex := lineIndex + 1].
self updateCompositionHeight.
self trimLinesTo: lineIndex - 1.
^ maximumRightX!
Item was changed:
----- Method: Paragraph>>displayLines:affectedRectangle: (in category 'private') -----
displayLines: linesInterval affectedRectangle: affectedRectangle
"This is the first level workhorse in the display portion of the TextForm routines.
It checks to see which lines in the interval are actually visible, has the
CharacterScanner display only those, clears out the areas in which display will
occur, and clears any space remaining in the visibleRectangle following the space
occupied by lastLine."
+ | topY firstLineIndex lastLineIndex lastLineIndexBottom |
- | lineGrid topY firstLineIndex lastLineIndex lastLineIndexBottom |
"Save some time by only displaying visible lines"
firstLineIndex := self lineIndexOfTop: affectedRectangle top.
firstLineIndex < linesInterval first ifTrue: [firstLineIndex := linesInterval first].
lastLineIndex := self lineIndexOfTop: affectedRectangle bottom - 1.
lastLineIndex > linesInterval last ifTrue:
[linesInterval last > lastLine
ifTrue: [lastLineIndex := lastLine]
ifFalse: [lastLineIndex := linesInterval last]].
lastLineIndexBottom := (self bottomAtLineIndex: lastLineIndex).
((Rectangle
origin: affectedRectangle left @ (topY := self topAtLineIndex: firstLineIndex)
corner: affectedRectangle right @ lastLineIndexBottom)
intersects: affectedRectangle)
ifTrue: [ " . . . (skip to clear-below if no lines displayed)"
+ DisplayScanner new
- MultiDisplayScanner new
displayLines: (firstLineIndex to: lastLineIndex)
in: self clippedBy: affectedRectangle].
lastLineIndex = lastLine ifTrue:
[destinationForm "Clear out white space below last line"
fill: (affectedRectangle left @ (lastLineIndexBottom max: affectedRectangle top)
corner: affectedRectangle bottomRight)
rule: rule fillColor: self backgroundColor]!
Nicolas Cellier uploaded a new version of ST80 to project The Trunk:
http://source.squeak.org/trunk/ST80-nice.151.mcz
==================== Summary ====================
Name: ST80-nice.151
Author: nice
Time: 29 September 2013, 4:35:30.085 pm
UUID: bdd314c3-0f95-4519-82f0-dfc85b76d4a7
Ancestors: ST80-nice.150
Start using the CharacterScanner hierarchy instead of the Multi one.
=============== Diff against ST80-nice.150 ===============
Item was changed:
----- Method: Paragraph>>composeAll (in category 'composition') -----
composeAll
"Compose a collection of characters into a collection of lines."
| startIndex stopIndex lineIndex maximumRightX compositionScanner |
lines := Array new: 32.
lastLine := 0.
maximumRightX := 0.
text size = 0
ifTrue:
[compositionRectangle := compositionRectangle withHeight: 0.
^maximumRightX].
startIndex := lineIndex := 1.
stopIndex := text size.
+ compositionScanner := CompositionScanner new forParagraph: self.
- compositionScanner := MultiCompositionScanner new forParagraph: self.
[startIndex > stopIndex] whileFalse:
[self lineAt: lineIndex
put: (compositionScanner composeLine: lineIndex
fromCharacterIndex: startIndex
inParagraph: self).
maximumRightX := compositionScanner rightX max: maximumRightX.
startIndex := (lines at: lineIndex) last + 1.
lineIndex := lineIndex + 1].
self updateCompositionHeight.
self trimLinesTo: lineIndex - 1.
^ maximumRightX!
Item was changed:
----- Method: Paragraph>>displayLines:affectedRectangle: (in category 'private') -----
displayLines: linesInterval affectedRectangle: affectedRectangle
"This is the first level workhorse in the display portion of the TextForm routines.
It checks to see which lines in the interval are actually visible, has the
CharacterScanner display only those, clears out the areas in which display will
occur, and clears any space remaining in the visibleRectangle following the space
occupied by lastLine."
+ | topY firstLineIndex lastLineIndex lastLineIndexBottom |
- | lineGrid topY firstLineIndex lastLineIndex lastLineIndexBottom |
"Save some time by only displaying visible lines"
firstLineIndex := self lineIndexOfTop: affectedRectangle top.
firstLineIndex < linesInterval first ifTrue: [firstLineIndex := linesInterval first].
lastLineIndex := self lineIndexOfTop: affectedRectangle bottom - 1.
lastLineIndex > linesInterval last ifTrue:
[linesInterval last > lastLine
ifTrue: [lastLineIndex := lastLine]
ifFalse: [lastLineIndex := linesInterval last]].
lastLineIndexBottom := (self bottomAtLineIndex: lastLineIndex).
((Rectangle
origin: affectedRectangle left @ (topY := self topAtLineIndex: firstLineIndex)
corner: affectedRectangle right @ lastLineIndexBottom)
intersects: affectedRectangle)
ifTrue: [ " . . . (skip to clear-below if no lines displayed)"
+ DisplayScanner new
- MultiDisplayScanner new
displayLines: (firstLineIndex to: lastLineIndex)
in: self clippedBy: affectedRectangle].
lastLineIndex = lastLine ifTrue:
[destinationForm "Clear out white space below last line"
fill: (affectedRectangle left @ (lastLineIndexBottom max: affectedRectangle top)
corner: affectedRectangle bottomRight)
rule: rule fillColor: self backgroundColor]!
Nicolas Cellier uploaded a new version of Morphic to project The Trunk:
http://source.squeak.org/trunk/Morphic-nice.693.mcz
==================== Summary ====================
Name: Morphic-nice.693
Author: nice
Time: 29 September 2013, 4:31:07.575 pm
UUID: 7c0b3c16-a967-457e-8fcf-0bdcec39d18a
Ancestors: Morphic-tpr.692
Start using the CharacterScanner hierarchy instead of the Multi one.
=============== Diff against Morphic-tpr.692 ===============
Item was changed:
----- Method: GrafPort>>displayScannerFor:foreground:background:ignoreColorChanges: (in category 'accessing') -----
displayScannerFor: para foreground: foreColor background: backColor ignoreColorChanges: shadowMode
-
- ((para isMemberOf: NewParagraph) or: [para text string isByteString]) ifTrue: [
- ^ (MultiDisplayScanner new text: para text textStyle: para textStyle
- foreground: foreColor background: backColor fillBlt: self
- ignoreColorChanges: shadowMode)
- setPort: self clone
- ].
^ (DisplayScanner new text: para text textStyle: para textStyle
foreground: foreColor background: backColor fillBlt: self
ignoreColorChanges: shadowMode)
setPort: self clone
!
Item was changed:
----- Method: NewParagraph>>characterBlockAtPoint: (in category 'selection') -----
characterBlockAtPoint: aPoint
"Answer a CharacterBlock for the character in the text at aPoint."
| line |
line := lines at: (self lineIndexForPoint: aPoint).
+ ^(CharacterBlockScanner new text: text textStyle: textStyle)
- ^ ((text string isWideString) ifTrue: [
- MultiCharacterBlockScanner new text: text textStyle: textStyle
- ] ifFalse: [CharacterBlockScanner new text: text textStyle: textStyle])
characterBlockAtPoint: aPoint index: nil
in: line!
Item was changed:
----- Method: NewParagraph>>characterBlockForIndex: (in category 'selection') -----
characterBlockForIndex: index
"Answer a CharacterBlock for the character in text at index."
| line |
line := lines at: (self lineIndexOfCharacterIndex: index).
+ ^ (CharacterBlockScanner new text: text textStyle: textStyle)
- ^ ((text string isWideString) ifTrue: [
- MultiCharacterBlockScanner new text: text textStyle: textStyle
- ] ifFalse: [
- CharacterBlockScanner new text: text textStyle: textStyle
- ])
characterBlockAtPoint: nil index: ((index max: line first) min: text size+1)
in: line!
Nicolas Cellier uploaded a new version of Morphic to project The Trunk:
http://source.squeak.org/trunk/Morphic-nice.693.mcz
==================== Summary ====================
Name: Morphic-nice.693
Author: nice
Time: 29 September 2013, 4:31:07.575 pm
UUID: 7c0b3c16-a967-457e-8fcf-0bdcec39d18a
Ancestors: Morphic-tpr.692
Start using the CharacterScanner hierarchy instead of the Multi one.
=============== Diff against Morphic-tpr.692 ===============
Item was changed:
----- Method: GrafPort>>displayScannerFor:foreground:background:ignoreColorChanges: (in category 'accessing') -----
displayScannerFor: para foreground: foreColor background: backColor ignoreColorChanges: shadowMode
-
- ((para isMemberOf: NewParagraph) or: [para text string isByteString]) ifTrue: [
- ^ (MultiDisplayScanner new text: para text textStyle: para textStyle
- foreground: foreColor background: backColor fillBlt: self
- ignoreColorChanges: shadowMode)
- setPort: self clone
- ].
^ (DisplayScanner new text: para text textStyle: para textStyle
foreground: foreColor background: backColor fillBlt: self
ignoreColorChanges: shadowMode)
setPort: self clone
!
Item was changed:
----- Method: NewParagraph>>characterBlockAtPoint: (in category 'selection') -----
characterBlockAtPoint: aPoint
"Answer a CharacterBlock for the character in the text at aPoint."
| line |
line := lines at: (self lineIndexForPoint: aPoint).
+ ^(CharacterBlockScanner new text: text textStyle: textStyle)
- ^ ((text string isWideString) ifTrue: [
- MultiCharacterBlockScanner new text: text textStyle: textStyle
- ] ifFalse: [CharacterBlockScanner new text: text textStyle: textStyle])
characterBlockAtPoint: aPoint index: nil
in: line!
Item was changed:
----- Method: NewParagraph>>characterBlockForIndex: (in category 'selection') -----
characterBlockForIndex: index
"Answer a CharacterBlock for the character in text at index."
| line |
line := lines at: (self lineIndexOfCharacterIndex: index).
+ ^ (CharacterBlockScanner new text: text textStyle: textStyle)
- ^ ((text string isWideString) ifTrue: [
- MultiCharacterBlockScanner new text: text textStyle: textStyle
- ] ifFalse: [
- CharacterBlockScanner new text: text textStyle: textStyle
- ])
characterBlockAtPoint: nil index: ((index max: line first) min: text size+1)
in: line!
Nicolas Cellier uploaded a new version of Morphic to project The Trunk:
http://source.squeak.org/trunk/Morphic-nice.693.mcz
==================== Summary ====================
Name: Morphic-nice.693
Author: nice
Time: 29 September 2013, 4:31:07.575 pm
UUID: 7c0b3c16-a967-457e-8fcf-0bdcec39d18a
Ancestors: Morphic-tpr.692
Start using the CharacterScanner hierarchy instead of the Multi one.
=============== Diff against Morphic-tpr.692 ===============
Item was changed:
----- Method: GrafPort>>displayScannerFor:foreground:background:ignoreColorChanges: (in category 'accessing') -----
displayScannerFor: para foreground: foreColor background: backColor ignoreColorChanges: shadowMode
-
- ((para isMemberOf: NewParagraph) or: [para text string isByteString]) ifTrue: [
- ^ (MultiDisplayScanner new text: para text textStyle: para textStyle
- foreground: foreColor background: backColor fillBlt: self
- ignoreColorChanges: shadowMode)
- setPort: self clone
- ].
^ (DisplayScanner new text: para text textStyle: para textStyle
foreground: foreColor background: backColor fillBlt: self
ignoreColorChanges: shadowMode)
setPort: self clone
!
Item was changed:
----- Method: NewParagraph>>characterBlockAtPoint: (in category 'selection') -----
characterBlockAtPoint: aPoint
"Answer a CharacterBlock for the character in the text at aPoint."
| line |
line := lines at: (self lineIndexForPoint: aPoint).
+ ^(CharacterBlockScanner new text: text textStyle: textStyle)
- ^ ((text string isWideString) ifTrue: [
- MultiCharacterBlockScanner new text: text textStyle: textStyle
- ] ifFalse: [CharacterBlockScanner new text: text textStyle: textStyle])
characterBlockAtPoint: aPoint index: nil
in: line!
Item was changed:
----- Method: NewParagraph>>characterBlockForIndex: (in category 'selection') -----
characterBlockForIndex: index
"Answer a CharacterBlock for the character in text at index."
| line |
line := lines at: (self lineIndexOfCharacterIndex: index).
+ ^ (CharacterBlockScanner new text: text textStyle: textStyle)
- ^ ((text string isWideString) ifTrue: [
- MultiCharacterBlockScanner new text: text textStyle: textStyle
- ] ifFalse: [
- CharacterBlockScanner new text: text textStyle: textStyle
- ])
characterBlockAtPoint: nil index: ((index max: line first) min: text size+1)
in: line!