Andreas Raab uploaded a new version of Monticello to project The Trunk:
http://source.squeak.org/trunk/Monticello-ar.321.mcz
==================== Summary ====================
Name: Monticello-ar.321
Author: ar
Time: 30 August 2009, 8:35:22 am
UUID: dedee780-04ae-e84a-8e6c-0947f7a24780
Ancestors: Monticello-tfel.320
Adds a workaround for the broken 'atomic' loading behavior in MCPackageLoader>>basicLoad.
=============== Diff against Monticello-tfel.320 ===============
Item was changed:
----- Method: MCPackageLoader>>basicLoad (in category 'private') -----
basicLoad
errorDefinitions := OrderedCollection new.
+ [[
+
+ "FIXME. Do a separate pass on loading class definitions as the very first thing.
+ This is a workaround for a problem with the so-called 'atomic' loading (you wish!!)
+ which isn't atomic at all but mixes compilation of methods with reshapes of classes.
+
+ Since the method is not installed until later, any class reshape in the middle *will*
+ affect methods in subclasses that have been compiled before. There is probably
+ a better way of dealing with this by ensuring that the sort order of the definition lists
+ superclass definitions before methods for subclasses but I need this NOW, and adding
+ an extra pass ensures that methods are compiled against their new class definitions."
+
+ additions do: [:ea | self loadClassDefinition: ea] displayingProgress: 'Loading classes...'.
+
+ additions do: [:ea | self tryToLoad: ea] displayingProgress: 'Compiling methods...'.
- [[additions do: [:ea | self tryToLoad: ea] displayingProgress: 'Loading...'.
removals do: [:ea | ea unload] displayingProgress: 'Cleaning up...'.
self shouldWarnAboutErrors ifTrue: [self warnAboutErrors].
errorDefinitions do: [:ea | ea addMethodAdditionTo: methodAdditions] displayingProgress: 'Reloading...'.
methodAdditions do: [:each | each installMethod].
methodAdditions do: [:each | each notifyObservers].
additions do: [:ea | ea postloadOver: (self obsoletionFor: ea)] displayingProgress: 'Initializing...']
on: InMidstOfFileinNotification
do: [:n | n resume: true]]
ensure: [self flushChangesFile]!
Item was added:
+ ----- Method: MCPackageLoader>>loadClassDefinition: (in category 'private') -----
+ loadClassDefinition: aDefinition
+ [aDefinition isClassDefinition ifTrue:[aDefinition load]] on: Error do: [errorDefinitions add: aDefinition].!
Andreas Raab uploaded a new version of ToolBuilder-Morphic to project The Trunk:
http://source.squeak.org/trunk/ToolBuilder-Morphic-ar.35.mcz
==================== Summary ====================
Name: ToolBuilder-Morphic-ar.35
Author: ar
Time: 30 August 2009, 5:28:43 am
UUID: 0d095223-7722-7b4f-a18b-1e2ef334b6da
Ancestors: ToolBuilder-Morphic-ar.34
Implement font-chooser interface for Morphic.
=============== Diff against ToolBuilder-Morphic-ar.34 ===============
Item was added:
+ ----- Method: MorphicUIManager>>chooseFont:for:setSelector:getSelector: (in category 'ui requests') -----
+ chooseFont: titleString for: aModel setSelector: setSelector getSelector: getSelector
+ "Open a font-chooser for the given model"
+ ^FontChooserTool default
+ openWithWindowTitle: titleString
+ for: aModel
+ setSelector: setSelector
+ getSelector: getSelector!
Andreas Raab uploaded a new version of ToolBuilder-MVC to project The Trunk:
http://source.squeak.org/trunk/ToolBuilder-MVC-ar.15.mcz
==================== Summary ====================
Name: ToolBuilder-MVC-ar.15
Author: ar
Time: 30 August 2009, 5:28:07 am
UUID: 26f9ab5c-5cb3-424e-ae1f-81bbb7c57af6
Ancestors: ToolBuilder-MVC-bp.14
Implement font-chooser interface for MVC.
=============== Diff against ToolBuilder-MVC-bp.14 ===============
Item was added:
+ ----- Method: MVCUIManager>>chooseFont:for:setSelector:getSelector: (in category 'ui requests') -----
+ chooseFont: titleString for: aModel setSelector: setSelector getSelector: getSelector
+ "Open a font-chooser for the given model"
+ ^TextStyle mvcPromptForFont: titleString andSendTo: aModel withSelector: setSelector!
Andreas Raab uploaded a new version of ToolBuilder-Kernel to project The Trunk:
http://source.squeak.org/trunk/ToolBuilder-Kernel-ar.20.mcz
==================== Summary ====================
Name: ToolBuilder-Kernel-ar.20
Author: ar
Time: 30 August 2009, 5:27:11 am
UUID: e874090d-db4c-d34e-ac06-a760b7466c8d
Ancestors: ToolBuilder-Kernel-ar.19
Add UIManager support for a font-chooser dialog, based on the FreeTypePlus FontChooser interface.
=============== Diff against ToolBuilder-Kernel-ar.19 ===============
Item was added:
+ ----- Method: UIManager>>chooseFont:for:setSelector:getSelector: (in category 'ui requests') -----
+ chooseFont: titleString for: aModel setSelector: setSelector getSelector: getSelector
+ "Open a font-chooser for the given model"!
Andreas Raab uploaded a new version of MorphicExtras to project The Trunk:
http://source.squeak.org/trunk/MorphicExtras-ar.44.mcz
==================== Summary ====================
Name: MorphicExtras-ar.44
Author: ar
Time: 30 August 2009, 5:18:50 am
UUID: 77556604-c907-714e-8d84-aacd322ed0ec
Ancestors: MorphicExtras-eem.43
FreeTypePlus integration. Fold extensions and overrides in CanvasCharacterScanner.
=============== Diff against MorphicExtras-eem.43 ===============
Item was changed:
----- Method: CanvasCharacterScanner>>tab (in category 'stop conditions') -----
tab
+ destX _ (alignment == Justified and: [self leadingTab not])
- destX := (alignment == Justified and: [self leadingTab not])
ifTrue: "imbedded tabs in justified text are weird"
[destX + (textStyle tabWidth - (line justifiedTabDeltaFor: spaceCount)) max: destX]
ifFalse:
[textStyle nextTabXFrom: destX
leftMargin: leftMargin
rightMargin: rightMargin].
+ lastIndex _ lastIndex + 1.
+ pendingKernX := 0.
-
- lastIndex := lastIndex + 1.
^ false!
Item was changed:
----- Method: CanvasCharacterScanner>>cr (in category 'stop conditions') -----
cr
"When a carriage return is encountered, simply increment the pointer
into the paragraph."
+ lastIndex_ lastIndex + 1.
+ pendingKernX := 0.
- lastIndex:= lastIndex + 1.
^false!
Item was changed:
----- Method: CanvasCharacterScanner>>paddedSpace (in category 'stop conditions') -----
paddedSpace
"Each space is a stop condition when the alignment is right justified.
Padding must be added to the base width of the space according to
which space in the line this space is and according to the amount of
space that remained at the end of the line when it was composed."
+ destX _ destX + spaceWidth + (line justifiedPadFor: spaceCount font: font).
+ lastIndex _ lastIndex + 1.
+ pendingKernX := 0.
- destX := destX + spaceWidth + (line justifiedPadFor: spaceCount).
-
- lastIndex := lastIndex + 1.
^ false!
Andreas Raab uploaded a new version of Graphics to project The Trunk:
http://source.squeak.org/trunk/Graphics-ar.71.mcz
==================== Summary ====================
Name: Graphics-ar.71
Author: ar
Time: 30 August 2009, 5:11:12 am
UUID: 4fc068c9-df6c-8249-b8ee-5c9ab469a2dc
Ancestors: Graphics-ar.70
First pass on FreeTypePlus integration. Deal with all of the overrides and add kerning support to CharacterScanner. This gets rid of all of the FTP extensions on Graphics package and the fumbling with CharacterScanner ivar list.
=============== Diff against Graphics-ar.70 ===============
Item was added:
+ ----- Method: AbstractFont>>linearWidthOf: (in category 'measuring') -----
+ linearWidthOf: aCharacter
+ "This is the scaled, unrounded advance width."
+ ^self widthOf: aCharacter!
Item was added:
+ ----- Method: AbstractFont>>kerningLeft:right: (in category 'kerning') -----
+ kerningLeft: leftChar right: rightChar
+ ^0!
Item was changed:
----- Method: CompositionScanner>>space (in category 'stop conditions') -----
space
"Record left x and character index of the space character just encounted.
Used for wrap-around. Answer whether the character has crossed the
right edge of the composition rectangle of the paragraph."
+ pendingKernX := 0.
spaceX := destX.
destX := spaceX + spaceWidth.
spaceIndex := lastIndex.
lineHeightAtSpace := lineHeight.
baselineAtSpace := baseline.
lastIndex := lastIndex + 1.
spaceCount := spaceCount + 1.
destX > rightMargin ifTrue: [^self crossedX].
^false
!
Item was added:
+ ----- Method: AbstractFont class>>forceNonSubPixelCount (in category 'utilities') -----
+ forceNonSubPixelCount
+ "Answer the force non-subpixel count"
+ ^ForceNonSubPixelCount ifNil:[ForceNonSubPixelCount := 0]!
Item was changed:
----- Method: CompositionScanner>>crossedX (in category 'stop conditions') -----
crossedX
"There is a word that has fallen across the right edge of the composition
rectangle. This signals the need for wrapping which is done to the last
space that was encountered, as recorded by the space stop condition."
+ pendingKernX := 0.
spaceCount >= 1 ifTrue:
["The common case. First back off to the space at which we wrap."
line stop: spaceIndex.
lineHeight := lineHeightAtSpace.
baseline := baselineAtSpace.
spaceCount := spaceCount - 1.
spaceIndex := spaceIndex - 1.
"Check to see if any spaces preceding the one at which we wrap.
Double space after punctuation, most likely."
[(spaceCount > 1 and: [(text at: spaceIndex) = Space])]
whileTrue:
[spaceCount := spaceCount - 1.
"Account for backing over a run which might
change width of space."
font := text fontAt: spaceIndex withStyle: textStyle.
spaceIndex := spaceIndex - 1.
spaceX := spaceX - (font widthOf: Space)].
line paddingWidth: rightMargin - spaceX.
line internalSpaces: spaceCount]
ifFalse:
["Neither internal nor trailing spaces -- almost never happens."
lastIndex := lastIndex - 1.
[destX <= rightMargin]
whileFalse:
[destX := destX - (font widthOf: (text at: lastIndex)).
lastIndex := lastIndex - 1].
spaceX := destX.
line paddingWidth: rightMargin - destX.
line stop: (lastIndex max: line first)].
^true!
Item was added:
+ ----- Method: AbstractFont>>emphasisStringFor: (in category 'accessing') -----
+ emphasisStringFor: emphasisCode
+ "Answer a translated string that represents the attributes given in emphasisCode."
+
+ ^self class emphasisStringFor: emphasisCode!
Item was added:
+ ----- Method: BitBlt>>combinationRule (in category 'accessing') -----
+ combinationRule
+ "Answer the receiver's combinationRule"
+
+ ^combinationRule!
Item was added:
+ ----- Method: AbstractFont>>widthAndKernedWidthOfLeft:right:into: (in category 'kerning') -----
+ widthAndKernedWidthOfLeft: leftCharacter right: rightCharacterOrNil into: aTwoElementArray
+ "Set the first element of aTwoElementArray to the width of leftCharacter and
+ the second element to the width of left character when kerned with
+ rightCharacterOrNil. Answer aTwoElementArray"
+ | w k |
+ w := self widthOf: leftCharacter.
+ rightCharacterOrNil isNil
+ ifTrue:[
+ aTwoElementArray
+ at: 1 put: w;
+ at: 2 put: w]
+ ifFalse:[
+ k := self kerningLeft: leftCharacter right: rightCharacterOrNil.
+ aTwoElementArray
+ at: 1 put: w;
+ at: 2 put: w+k].
+ ^aTwoElementArray
+ !
Item was added:
+ ----- Method: AbstractFont>>displayUnderlineOn:from:to: (in category 'displaying') -----
+ displayUnderlineOn: aDisplayContext from: baselineStartPoint to: baselineEndPoint
+ "display the underline if appropriate for the receiver"!
Item was changed:
----- Method: CharacterBlockScanner>>paddedSpace (in category 'stop conditions') -----
paddedSpace
"When the line is justified, the spaces will not be the same as the font's
space character. A padding of extra space must be considered in trying
to find which character the cursor is pointing at. Answer whether the
scanning has crossed the cursor."
| pad |
pad := 0.
spaceCount := spaceCount + 1.
+ pad := line justifiedPadFor: spaceCount font: font.
- pad := line justifiedPadFor: spaceCount.
lastSpaceOrTabExtent := lastCharacterExtent copy.
self lastSpaceOrTabExtentSetX: spaceWidth + pad.
(destX + lastSpaceOrTabExtent x) >= characterPoint x
ifTrue: [lastCharacterExtent := lastSpaceOrTabExtent copy.
^self crossedX].
lastIndex := lastIndex + 1.
destX := destX + lastSpaceOrTabExtent x.
^ false
!
Item was changed:
----- Method: CompositionScanner>>tab (in category 'stop conditions') -----
tab
"Advance destination x according to tab settings in the paragraph's
textStyle. Answer whether the character has crossed the right edge of
the composition rectangle of the paragraph."
+ pendingKernX := 0.
destX := textStyle
nextTabXFrom: destX leftMargin: leftMargin rightMargin: rightMargin.
destX > rightMargin ifTrue: [^self crossedX].
lastIndex := lastIndex + 1.
^false
!
Item was changed:
----- Method: CompositionScanner>>columnBreak (in category 'stop conditions') -----
columnBreak
"Answer true. Set up values for the text line interval currently being
composed."
+ pendingKernX := 0.
line stop: lastIndex.
spaceX := destX.
line paddingWidth: rightMargin - spaceX.
^true!
Item was changed:
----- Method: CompositionScanner>>cr (in category 'stop conditions') -----
cr
"Answer true. Set up values for the text line interval currently being
composed."
+ pendingKernX := 0.
line stop: lastIndex.
spaceX := destX.
line paddingWidth: rightMargin - spaceX.
^true!
Item was changed:
----- Method: CharacterBlockScanner>>crossedX (in category 'stop conditions') -----
crossedX
"Text display has wrapping. The scanner just found a character past the x
location of the cursor. We know that the cursor is pointing at a character
or before one."
| leadingTab currentX |
characterIndex == nil ifFalse: [
"If the last character of the last line is a space,
and it crosses the right margin, then locating
the character block after it is impossible without this hack."
characterIndex > text size ifTrue: [
lastIndex := characterIndex.
characterPoint := (nextLeftMargin ifNil: [leftMargin]) @ (destY + line lineHeight).
^true]].
characterPoint x <= (destX + (lastCharacterExtent x // 2))
ifTrue: [lastCharacter := (text at: lastIndex).
characterPoint := destX @ destY.
^true].
lastIndex >= line last
ifTrue: [lastCharacter := (text at: line last).
characterPoint := destX @ destY.
^true].
"Pointing past middle of a character, return the next character."
lastIndex := lastIndex + 1.
lastCharacter := text at: lastIndex.
currentX := destX + lastCharacterExtent x + kern.
self lastCharacterExtentSetX: (font widthOf: lastCharacter).
characterPoint := currentX @ destY.
lastCharacter = Space ifFalse: [^ true].
"Yukky if next character is space or tab."
alignment = Justified ifTrue:
[self lastCharacterExtentSetX:
+ (lastCharacterExtent x + (line justifiedPadFor: (spaceCount + 1) font: font)).
- (lastCharacterExtent x + (line justifiedPadFor: (spaceCount + 1))).
^ true].
true ifTrue: [^ true].
"NOTE: I find no value to the following code, and so have defeated it - DI"
"See tabForDisplay for illumination on the following awfulness."
leadingTab := true.
line first to: lastIndex - 1 do:
[:index | (text at: index) ~= Tab ifTrue: [leadingTab := false]].
(alignment ~= Justified or: [leadingTab])
ifTrue: [self lastCharacterExtentSetX: (textStyle nextTabXFrom: currentX
leftMargin: leftMargin rightMargin: rightMargin) -
currentX]
ifFalse: [self lastCharacterExtentSetX: (((currentX + (textStyle tabWidth -
(line justifiedTabDeltaFor: spaceCount))) -
currentX) max: 0)].
^ true!
Item was changed:
Object subclass: #AbstractFont
instanceVariableNames: ''
+ classVariableNames: 'ForceNonSubPixelCount'
- classVariableNames: ''
poolDictionaries: ''
category: 'Graphics-Fonts'!
!AbstractFont commentStamp: '<historical>' prior: 0!
AbstractFont defines the generic interface that all fonts need to implement.!
Item was changed:
Object subclass: #CharacterScanner
+ instanceVariableNames: 'destX lastIndex xTable destY stopConditions text textStyle alignment leftMargin rightMargin font line runStopIndex spaceCount spaceWidth emphasisCode kern indentationLevel wantsColumnBreaks pendingKernX'
- instanceVariableNames: 'destX lastIndex xTable destY stopConditions text textStyle alignment leftMargin rightMargin font line runStopIndex spaceCount spaceWidth emphasisCode kern indentationLevel wantsColumnBreaks'
classVariableNames: 'DefaultStopConditions NilCondition PaddedSpaceCondition SpaceCondition'
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: DisplayScanner>>paddedSpace (in category 'stop conditions') -----
paddedSpace
"Each space is a stop condition when the alignment is right justified.
Padding must be added to the base width of the space according to
which space in the line this space is and according to the amount of
space that remained at the end of the line when it was composed."
spaceCount := spaceCount + 1.
+ destX := destX + spaceWidth + (line justifiedPadFor: spaceCount font: font).
- destX := destX + spaceWidth + (line justifiedPadFor: spaceCount).
lastIndex := lastIndex + 1.
^ false!
Item was changed:
----- Method: CharacterScanner>>setFont (in category 'private') -----
setFont
| priorFont |
"Set the font and other emphasis."
priorFont := font.
text == nil ifFalse:[
emphasisCode := 0.
kern := 0.
indentationLevel := 0.
alignment := textStyle alignment.
font := nil.
(text attributesAt: lastIndex forStyle: textStyle)
do: [:att | att emphasizeScanner: self]].
font == nil ifTrue:
[self setFont: textStyle defaultFontIndex].
font := font emphasized: emphasisCode.
+ priorFont
+ ifNotNil: [
+ font = priorFont
+ ifTrue:[
+ "font is the same, perhaps the color has changed?
+ We still want kerning between chars of the same
+ font, but of different color. So add any pending kern to destX"
+ destX := destX + (pendingKernX ifNil:[0])].
+ destX := destX + priorFont descentKern].
+ pendingKernX := 0. "clear any pending kern so there is no danger of it being added twice"
- priorFont ifNotNil: [destX := destX + priorFont descentKern].
destX := destX - font descentKern.
"NOTE: next statement should be removed when clipping works"
leftMargin ifNotNil: [destX := destX max: leftMargin].
kern := kern - font baseKern.
"Install various parameters from the font."
spaceWidth := font widthOf: Space.
xTable := font xTable.
stopConditions := DefaultStopConditions.!
Item was changed:
----- Method: TextStyle class>>emphasisMenuForFont:target:selector:highlight: (in category 'user interface') -----
emphasisMenuForFont: font target: target selector: selector highlight: currentEmphasis
"Offer a font emphasis menu for the given style. If one is selected, pass that font to target with a call to selector. The fonts will be displayed in that font.
Answer nil if no derivatives exist.
"
| aMenu derivs |
derivs := font derivativeFonts.
derivs isEmpty ifTrue: [ ^nil ].
aMenu := MenuMorph entitled: 'emphasis' translated.
derivs := derivs asOrderedCollection.
derivs addFirst: font.
derivs do: [ :df |
aMenu
+ add: df emphasisString
- add: (AbstractFont emphasisStringFor: df emphasis)
target: target
selector: selector
argument: df.
aMenu lastItem font: df.
df emphasis == currentEmphasis ifTrue: [aMenu lastItem color: Color blue darker]].
^ aMenu!
Item was changed:
----- Method: TextStyle class>>fontMenuForStyle:target:selector:highlight: (in category 'user interface') -----
fontMenuForStyle: styleName target: target selector: selector highlight: currentFont
"Offer a font menu for the given style. If one is selected, pass
that font to target with a
call to selector. The fonts will be displayed in that font."
+ | aMenu displayFont |
- | aMenu |
aMenu := MenuMorph entitled: styleName.
(TextStyle named: styleName)
ifNotNilDo: [:s | s isTTCStyle
ifTrue: [aMenu
add: 'New Size'
target: self
selector: #chooseTTCFontSize:
argument: {styleName. target. selector}]].
(self pointSizesFor: styleName)
do: [:pointSize |
| font subMenu |
font := (self named: styleName)
fontOfPointSize: pointSize.
subMenu := self
emphasisMenuForFont: font
target: target
selector: selector
highlight: (currentFont
ifNotNilDo: [:cf | (cf familyName = styleName
and: [cf pointSize = font pointSize])
ifTrue: [currentFont emphasis]]).
subMenu
ifNil: [aMenu
add: pointSize asString , ' Point'
target: target
selector: selector
argument: font]
ifNotNil: [aMenu add: pointSize asString , ' Point' subMenu: subMenu].
+ displayFont := font.
+ (font isSymbolFont or:[(font hasDistinctGlyphsForAll: pointSize asString , ' Point') not])
+ ifTrue:[
+ "don't use a symbol font to display its own name!!!!"
+ displayFont := self default fontOfPointSize: pointSize].
+ aMenu lastItem font: displayFont.
- aMenu lastItem font: font.
currentFont
ifNotNilDo: [:cf | (cf familyName = styleName
and: [cf pointSize = font pointSize])
ifTrue: [aMenu lastItem color: Color blue darker]]].
^ aMenu!
Item was changed:
----- Method: CharacterScanner>>basicScanCharactersFrom:to:in:rightX:stopConditions:kern: (in category 'scanning') -----
basicScanCharactersFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops kern: kernDelta
"Primitive. This is the inner loop of text display--but see
scanCharactersFrom: to:rightX: which would get the string,
stopConditions and displaying from the instance. March through source
String from startIndex to stopIndex. If any character is flagged with a
non-nil entry in stops, then return the corresponding value. Determine
width of each character from xTable, indexed by map.
If dextX would exceed rightX, then return stops at: 258.
Advance destX by the width of the character. If stopIndex has been
reached, then return stops at: 257. Optional.
See Object documentation whatIsAPrimitive."
+ | ascii nextDestX char floatDestX widthAndKernedWidth nextChar atEndOfRun |
- | ascii nextDestX char |
<primitive: 103>
lastIndex := startIndex.
+ floatDestX := destX.
+ widthAndKernedWidth := Array new: 2.
+ atEndOfRun := false.
[lastIndex <= stopIndex]
whileTrue:
[char := (sourceString at: lastIndex).
ascii := char asciiValue + 1.
(stops at: ascii) == nil ifFalse: [^stops at: ascii].
"Note: The following is querying the font about the width
since the primitive may have failed due to a non-trivial
mapping of characters to glyphs or a non-existing xTable."
+ nextChar := (lastIndex + 1 <= stopIndex)
+ ifTrue:[sourceString at: lastIndex + 1]
+ ifFalse:[
+ atEndOfRun := true.
+ "if there is a next char in sourceString, then get the kern
+ and store it in pendingKernX"
+ lastIndex + 1 <= sourceString size
+ ifTrue:[sourceString at: lastIndex + 1]
+ ifFalse:[ nil]].
+ font
+ widthAndKernedWidthOfLeft: char
+ right: nextChar
+ into: widthAndKernedWidth.
+ nextDestX := floatDestX + (widthAndKernedWidth at: 1).
- nextDestX := destX + (font widthOf: char).
nextDestX > rightX ifTrue: [^stops at: CrossedX].
+ floatDestX := floatDestX + kernDelta + (widthAndKernedWidth at: 2).
+ atEndOfRun
+ ifTrue:[
+ pendingKernX := (widthAndKernedWidth at: 2) - (widthAndKernedWidth at: 1).
+ floatDestX := floatDestX - pendingKernX].
+ destX := floatDestX.
- destX := nextDestX + kernDelta.
lastIndex := lastIndex + 1].
lastIndex := stopIndex.
^stops at: EndOfRun!
Item was added:
+ ----- Method: AbstractFont class>>forceNonSubPixelDuring: (in category 'utilities') -----
+ forceNonSubPixelDuring: aBlock
+ "Forces all font rendering to suppress subpixel anti-aliasing during the execution of aBlock"
+ ForceNonSubPixelCount ifNil:[ForceNonSubPixelCount := 0].
+ ForceNonSubPixelCount := ForceNonSubPixelCount + 1.
+ aBlock ensure:[ForceNonSubPixelCount := ForceNonSubPixelCount - 1]!
Item was added:
+ ----- Method: TextLineInterval>>justifiedPadFor:font: (in category 'scanning') -----
+ justifiedPadFor: spaceIndex font: aFont
+ "Compute the width of pad for a given space in a line of justified text."
+
+ | pad |
+ internalSpaces = 0 ifTrue: [^0].
+ ^(aFont notNil and:[aFont isSubPixelPositioned])
+ ifTrue:[paddingWidth * 1.0 / internalSpaces]
+ ifFalse:[
+ pad := paddingWidth // internalSpaces.
+ spaceIndex <= (paddingWidth \\ internalSpaces)
+ ifTrue: [pad + 1]
+ ifFalse: [pad]]!
Item was added:
+ ----- Method: AbstractFont>>hasGlyphsForAll: (in category 'testing') -----
+ hasGlyphsForAll: asciiString
+ "Answer true if the receiver has glyphs for all the characters
+ in asciiString, false otherwise.
+ The default behaviour is to answer true, but subclasses may reimplement"
+
+ ^true!
Item was changed:
----- Method: TextStyle>>addNewFontSize: (in category 'fonts and font indexes') -----
addNewFontSize: pointSize
"Add a font in specified size to the array of fonts."
+ | f d newArray t isSet |
- | f d newArray t isSet fallbackStyle |
fontArray first emphasis ~= 0 ifTrue: [
t := TextConstants at: self fontArray first familyName asSymbol.
t fonts first emphasis = 0 ifTrue: [
^ t addNewFontSize: pointSize.
].
].
pointSize <= 0 ifTrue: [^ nil].
fontArray do: [:s |
s pointSize = pointSize ifTrue: [^ s].
].
(isSet := fontArray first isKindOf: TTCFontSet)
ifTrue:[
| fonts |
fonts := fontArray first fontArray collect: [ :font |
| newFont |
(font isNil)
ifTrue: [newFont := nil]
ifFalse: [
newFont := (font ttcDescription size > 256)
ifTrue: [MultiTTCFont new initialize]
ifFalse: [TTCFont new initialize].
newFont ttcDescription: font ttcDescription.
newFont pixelSize: pointSize * 96 // 72.
font derivativeFonts notEmpty ifTrue: [font derivativeFonts do: [ :proto |
proto ifNotNil: [
d := proto class new initialize.
d ttcDescription: proto ttcDescription.
d pixelSize: newFont pixelSize.
newFont derivativeFont: d]]].
].
newFont].
f := TTCFontSet newFontArray: fonts]
ifFalse: [
+ f := fontArray first class new initialize: fontArray first.
- f := TTCFont new initialize.
- f ttcDescription: fontArray first ttcDescription.
f pointSize: pointSize.
fontArray first derivativeFonts do: [:proto |
proto ifNotNil: [
+ d := proto class new initialize: proto.
- d := TTCFont new initialize.
- d ttcDescription: proto ttcDescription.
d pointSize: f pointSize.
+ f derivativeFont: d mainFont: proto.
- f derivativeFont: d.
].
].
- ].
- isSet ifFalse: [
- fallbackStyle := TextStyle named: (fontArray first fallbackFont textStyleName).
].
newArray := ((fontArray copyWith: f) asSortedCollection: [:a :b | a pointSize <= b pointSize]) asArray.
self newFontArray: newArray.
isSet ifTrue: [
TTCFontSet register: newArray at: newArray first familyName asSymbol.
].
- isSet ifFalse: [
- f setupDefaultFallbackFontTo: fallbackStyle.
- f derivativeFonts do: [:g | g setupDefaultFallbackFontTo: fallbackStyle].
- ].
^ self fontOfPointSize: pointSize
!
Item was added:
+ ----- Method: AbstractFont>>isSubPixelPositioned (in category 'testing') -----
+ isSubPixelPositioned
+ "Answer true if the receiver is currently using subpixel positioned
+ glyphs, false otherwise. This affects how padded space sizes are calculated
+ when composing text.
+ Currently, only FreeTypeFonts are subPixelPositioned, and only when not
+ Hinted"
+
+ ^false !
Item was added:
+ ----- Method: AbstractFont>>isSymbolFont (in category 'testing') -----
+ isSymbolFont
+ "Answer true if the receiver is a Symbol font, false otherwise.
+ The default is to answer false, subclasses can reimplement"
+
+ ^false!
Item was added:
+ ----- Method: AbstractFont>>displayStrikeoutOn:from:to: (in category 'displaying') -----
+ displayStrikeoutOn: aDisplayContext from: baselineStartPoint to: baselineEndPoint
+ "display the strikeout if appropriate for the receiver"!
Item was added:
+ ----- Method: AbstractFont>>hasDistinctGlyphsForAll: (in category 'testing') -----
+ hasDistinctGlyphsForAll: asciiString
+ "Answer true if the receiver has glyphs for all the characters
+ in asciiString and no single glyph is shared by more than one character, false otherwise.
+ The default behaviour is to answer true, but subclasses may reimplement"
+
+ ^true!
Item was changed:
+ ----- Method: AbstractFont class>>emphasisStringFor: (in category 'utilities') -----
- ----- Method: AbstractFont class>>emphasisStringFor: (in category 'as yet unclassified') -----
emphasisStringFor: emphasisCode
"Answer a translated string that represents the attributes given in emphasisCode."
| emphases bit |
emphasisCode = 0 ifTrue: [ ^'Normal' translated ].
emphases := (IdentityDictionary new)
at: 1 put: 'Bold' translated;
at: 2 put: 'Italic' translated;
at: 4 put: 'Underlined' translated;
at: 8 put: 'Narrow' translated;
at: 16 put: 'StruckOut' translated;
yourself.
bit := 1.
^String streamContents: [ :s |
[ bit < 32 ] whileTrue: [ | code |
code := emphasisCode bitAnd: bit.
code isZero ifFalse: [ s nextPutAll: (emphases at: code); space ].
bit := bit bitShift: 1 ].
s position isZero ifFalse: [ s skip: -1 ].
]!
Item was changed:
----- Method: CharacterScanner>>columnBreak (in category 'scanning') -----
columnBreak
+ pendingKernX := 0.
^true!
Item was added:
+ ----- Method: AbstractFont>>emphasisString (in category 'accessing') -----
+ emphasisString
+ "Answer a translated string that represents the receiver's emphasis."
+
+ ^self emphasisStringFor: self emphasis!
Alexander Lazarević uploaded a new version of KernelTests to project The Trunk:
http://source.squeak.org/trunk/KernelTests-laza.87.mcz
==================== Summary ====================
Name: KernelTests-laza.87
Author: laza
Time: 31 August 2009, 1:24:44 am
UUID: 7bbafac0-f203-f94c-95de-ce3b9a575c4a
Ancestors: KernelTests-laza.86
Remove obsolete BlockContext tests
=============== Diff against KernelTests-laza.86 ===============
Item was removed:
- ----- Method: BlockContextTest>>testSupplyAnswerUsingTraditionalMatchOfQuestion (in category 'tests') -----
- testSupplyAnswerUsingTraditionalMatchOfQuestion
-
- self should: [true = ([self confirm: 'You like Smalltalk?']
- valueSupplyingAnswer: #('*Smalltalk#' true))]!
Item was removed:
- ----- Method: BlockContextTest>>testDecompile (in category 'tests - printing') -----
- testDecompile
- self assert: ([3 + 4] decompile printString = '{[3 + 4]}').!
Item was removed:
- ----- Method: BlockContextTest>>testSupplyAnswerUsingRegexMatchOfQuestion (in category 'tests') -----
- testSupplyAnswerUsingRegexMatchOfQuestion
-
- (String includesSelector: #matchesRegex:) ifFalse: [^ self].
-
- self should: [true = ([self confirm: 'You like Smalltalk?']
- valueSupplyingAnswer: #('.*Smalltalk\?' true))]!
Item was removed:
- ----- Method: BlockContextTest>>testSetUp (in category 'tests') -----
- testSetUp
- "Note: In addition to verifying that the setUp worked the way it was expected to, testSetUp is used to illustrate the meaning of the simple access methods, methods that are not normally otherwise 'tested'"
- self deny: aBlockContext isClosure.
- self deny: aBlockContext isMethodContext.
- self deny: aBlockContext isPseudoContext.
- self deny: aBlockContext isDead.
- self assert: aBlockContext home = contextOfaBlockContext.
- self assert: aBlockContext blockHome = contextOfaBlockContext.
- self assert: aBlockContext receiver = self.
- self assert: (aBlockContext method isKindOf: CompiledMethod).
- self assert: aBlockContext methodNode selector = 'setUp'.
- self assert: (aBlockContext methodNodeFormattedAndDecorated: true) selector = 'setUp'.!
Item was removed:
- ----- Method: BlockContextTest>>testCopyStack (in category 'tests') -----
- testCopyStack
- self assert: aBlockContext copyStack printString = aBlockContext printString.!
Item was removed:
- ----- Method: BlockContextTest>>testValueWithPossibleArgument (in category 'tests - evaluating') -----
- testValueWithPossibleArgument
- | block blockWithArg blockWith2Arg |
-
- block := [1].
- blockWithArg := [:arg | arg].
- blockWith2Arg := [:arg1 :arg2 | {arg1. arg2}].
-
- self assert: (block valueWithPossibleArgument: 1) = 1.
-
- self assert: (blockWithArg valueWithPossibleArgument: 1) = 1.
-
- self assert: (blockWith2Arg valueWithPossibleArgument: 1) = {1 . nil}.
-
-
- !
Item was removed:
- ----- Method: BlockContextTest>>testNew (in category 'tests') -----
- testNew
- self should: [ContextPart new: 5] raise: Error.
- [ContextPart new: 5]
- ifError: [:error :receiver | error = 'Error: Contexts must only be created with newForMethod:'].
- [ContextPart new]
- ifError: [:error :receiver | error = 'Error: Contexts must only be created with newForMethod:'].
- [ContextPart basicNew]
- ifError: [:error :receiver | error = 'Error: Contexts must only be created with newForMethod:'].
-
- !
Item was removed:
- ----- Method: BlockContextTest>>testOneArgument (in category 'tests') -----
- testOneArgument
- | c |
- c := OrderedCollection new.
- c add: 'hello'.
- [c
- do: [1 + 2]]
- ifError: [:err :rcvr | self deny: err = 'This block requires 0 arguments.'].
- [c
- do: [:arg1 :arg2 | 1 + 2]]
- ifError: [:err :rcvr | self deny: err = 'This block requires 2 arguments.'] !
Item was removed:
- ----- Method: BlockContextTest>>testSupplyAnswerThroughNestedBlocks (in category 'tests') -----
- testSupplyAnswerThroughNestedBlocks
-
- self should: [true = ([[self confirm: 'You like Smalltalk?']
- valueSupplyingAnswer: #('Blub' false)] valueSupplyingAnswer: #('Smalltalk' true))]!
Item was removed:
- ----- Method: BlockContextTest>>testSupplyAnswerOfFillInTheBlank (in category 'testing') -----
- testSupplyAnswerOfFillInTheBlank
-
- self should: ['blue' = ([UIManager default request: 'Your favorite color?']
- valueSupplyingAnswer: #('Your favorite color?' 'blue'))]!
Item was removed:
- ----- Method: BlockContextTest>>testTallyInstructions (in category 'tests') -----
- testTallyInstructions
- self assert: (ContextPart tallyInstructions: aBlockContext) size = 15.!
Item was removed:
- ----- Method: BlockContextTest>>testRunSimulated (in category 'tests') -----
- testRunSimulated
- self assert: (ContextPart runSimulated: aBlockContext) class = Rectangle.!
Item was removed:
- ----- Method: BlockContextTest>>testSupplyAnswerOfFillInTheBlankUsingDefaultAnswer (in category 'testing') -----
- testSupplyAnswerOfFillInTheBlankUsingDefaultAnswer
-
- self should: ['red' = ([UIManager default request: 'Your favorite color?' initialAnswer: 'red']
- valueSupplyingAnswer: #('Your favorite color?' #default))]!
Item was removed:
- ----- Method: BlockContextTest>>testSupplySameAnswerToAllQuestions (in category 'tests') -----
- testSupplySameAnswerToAllQuestions
-
- self should: [true = ([self confirm: 'You like Smalltalk?'] valueSupplyingAnswer: true)].
-
- self should: [#(true true) = ([{self confirm: 'One'. self confirm: 'Two'}] valueSupplyingAnswer: true)].!
Item was removed:
- ----- Method: BlockContextTest>>testSuppressInformUsingStringMatchOptions (in category 'tests') -----
- testSuppressInformUsingStringMatchOptions
-
- self should: [([nil inform: 'Should not see this message or this test failed!!'] valueSuppressingMessages: #('Should not see this message or this test failed!!')) isNil].
-
- self should: [([nil inform: 'Should not see this message or this test failed!!'] valueSuppressingMessages: #('not see this message')) isNil].
-
- self should: [([nil inform: 'Should not see this message or this test failed!!'] valueSuppressingMessages: #('*message*failed#')) isNil].
- !
Item was removed:
- TestCase subclass: #BlockContextTest
- instanceVariableNames: 'aBlockContext contextOfaBlockContext'
- classVariableNames: ''
- poolDictionaries: ''
- category: 'KernelTests-Methods'!
-
- !BlockContextTest commentStamp: 'jrp 10/17/2004 12:22' prior: 0!
- I am an SUnit Test of BlockContext and its supertype ContextPart. See also MethodContextTest.
-
- My fixtures are:
- aBlockContext - just some trivial block, i.e., [100@100 corner: 200@200].
-
- NOTES ABOUT AUTOMATING USER INPUTS
-
- When executing non-interactive programs you will inevitably run into programs (like SqueakMap or Monticello installation packages -- and other programs, to be fair) that require user input during their execution and these sort of problems shoot the whole non-interactiveness of your enclosing program.
-
- BlockContext helper methods have been made available and tests of these helpers are provided in this class to demonstrate that it can intercept PopUpMenu and FillInTheBlankMorph requests for user interaction. Of course, PopUpMenu and FillInTheBlankMorph were modified to first signal a ProvideAnswerNotification and if someone handles that (e.g. the enclosing block) then the user interaction will be circumvented and the provided answer of the enclosing block will be used. The basic syntax looks like:
-
- [self confirm: 'Install spyware?'] valueSupplyingAnswer: #('Install spyware?' false)
-
- There a few variants on this theme making it easy to provide a literal list of answers for the block so that you can handle a bunch of questions in a block with appropriate answers.
-
- Additionally, it is possible to suppress Object>>inform: modal dialog boxes as these get in the way of automating anything. After applying this changeset you should be able to tryout the following code snippets to see the variants on this theme that are available.
-
- Examples:
-
- So you don't need any introduction here -- this one works like usual.
- [self inform: 'hello'. #done] value.
-
- Now let's suppress all inform: messages.
- [self inform: 'hello'; inform: 'there'. #done] valueSuppressingAllMessages.
-
- Here we can just suppress a single inform: message.
- [self inform: 'hi'; inform: 'there'. #done] valueSuppressingMessages: #('there')
-
- Here you see how you can suppress a list of messages.
- [self inform: 'hi'; inform: 'there'; inform: 'bill'. #done] valueSuppressingMessages: #('hi' 'there')
-
- Enough about inform:, let's look at confirm:. As you see this one works as expected.
- [self confirm: 'You like Squeak?'] value
-
- Let's supply answers to one of the questions -- check out the return value.
- [{self confirm: 'You like Smalltalk?'. self confirm: 'You like Squeak?'}]
- valueSupplyingAnswer: #('You like Smalltalk?' true)
-
- Here we supply answers using only substrings of the questions (for simplicity).
- [{self confirm: 'You like Squeak?'. self confirm: 'You like MVC?'}]
- valueSupplyingAnswers: #( ('Squeak' true) ('MVC' false) )
-
- This time let's answer all questions exactly the same way.
- [{self confirm: 'You like Squeak?'. self confirm: 'You like Morphic?'}]
- valueSupplyingAnswer: true
-
- And, of course, we can answer FillInTheBlank questions in the same manner.
- [FillInTheBlank request: 'What day is it?']
- valueSupplyingAnswer: 'the first day of the rest of your life'
-
- We can also return whatever the initialAnswer of the FillInTheBlank was by using the #default answer.
- [FillInTheBlank request: 'What day is it?' initialAnswer: DateAndTime now dayOfWeekName]
- valueSupplyingAnswer: #default
-
- Finally, you can also do regex matches on any of the question text (or inform text) (should you have VB-Regex enhancements in your image).
- [FillInTheBlank request: 'What day is it?']
- valueSupplyingAnswers: { {'What day.*\?'. DateAndTime now dayOfWeekName} }!
Item was removed:
- ----- Method: BlockContextTest>>testSuppressInform (in category 'tests') -----
- testSuppressInform
-
- self should: [[nil inform: 'Should not see this message or this test failed!!'] valueSuppressingAllMessages isNil]!
Item was removed:
- ----- Method: BlockContextTest>>setUp (in category 'setup') -----
- setUp
- super setUp.
- aBlockContext := [100@100 corner: 200@200].
- contextOfaBlockContext := thisContext.!
Item was removed:
- ----- Method: BlockContextTest>>testTallyMethods (in category 'tests') -----
- testTallyMethods
- self assert: (ContextPart tallyMethods: aBlockContext) size = 3.!
Item was removed:
- ----- Method: BlockContextTest>>testValueWithPossibleArgs (in category 'tests - evaluating') -----
- testValueWithPossibleArgs
- | block blockWithArg blockWith2Arg |
-
- block := [1].
- blockWithArg := [:arg | arg].
- blockWith2Arg := [:arg1 :arg2 | {arg1. arg2}].
-
- self assert: (block valueWithPossibleArgs: #()) = 1.
- self assert: (block valueWithPossibleArgs: #(1)) = 1.
-
- self assert: (blockWithArg valueWithPossibleArgs: #()) = nil.
- self assert: (blockWithArg valueWithPossibleArgs: #(1)) = 1.
- self assert: (blockWithArg valueWithPossibleArgs: #(1 2)) = 1.
-
- self assert: (blockWith2Arg valueWithPossibleArgs: #()) = {nil .nil}.
- self assert: (blockWith2Arg valueWithPossibleArgs: #(1)) = {1 . nil}.
- self assert: (blockWith2Arg valueWithPossibleArgs: #(1 2)) = #(1 2).
- self assert: (blockWith2Arg valueWithPossibleArgs: #(1 2 3)) = #(1 2).
-
-
- !
Item was removed:
- ----- Method: BlockContextTest>>testValueWithExitContinue (in category 'tests - evaluating') -----
- testValueWithExitContinue
-
- | val last |
- val := 0.
-
- 1 to: 10 do: [ :i |
- [ :continue |
- i = 4 ifTrue: [continue value].
- val := val + 1.
- last := i
- ] valueWithExit.
- ].
-
- self assert: val = 9.
- self assert: last = 10. !
Item was removed:
- ----- Method: BlockContextTest>>testSupplySeveralAnswersToSeveralQuestions (in category 'tests') -----
- testSupplySeveralAnswersToSeveralQuestions
-
- self should: [#(false true) = ([{self confirm: 'One'. self confirm: 'Two'}]
- valueSupplyingAnswers: #( ('One' false) ('Two' true) ))].
-
- self should: [#(true false) = ([{self confirm: 'One'. self confirm: 'Two'}]
- valueSupplyingAnswers: #( ('One' true) ('Two' false) ))]!
Item was removed:
- ----- Method: BlockContextTest>>testTrace (in category 'tests') -----
- testTrace
- self assert: (ContextPart trace: aBlockContext) class = Rectangle.!
Item was removed:
- ----- Method: BlockContextTest>>testValueWithExitBreak (in category 'tests - evaluating') -----
- testValueWithExitBreak
-
- | val |
-
- [ :break |
- 1 to: 10 do: [ :i |
- val := i.
- i = 4 ifTrue: [break value].
- ]
- ] valueWithExit.
-
- self assert: val = 4.!
Item was removed:
- ----- Method: BlockContextTest>>testSupplyAnswerUsingOnlySubstringOfQuestion (in category 'tests') -----
- testSupplyAnswerUsingOnlySubstringOfQuestion
-
- self should: [false = ([self confirm: 'You like Smalltalk?']
- valueSupplyingAnswer: #('like' false))]!
Item was removed:
- ----- Method: BlockContextTest>>testSupplySpecificAnswerToQuestion (in category 'tests') -----
- testSupplySpecificAnswerToQuestion
-
- self should: [false = ([self confirm: 'You like Smalltalk?']
- valueSupplyingAnswer: #('You like Smalltalk?' false))]!
Item was removed:
- ----- Method: BlockContextTest>>testFindContextSuchThat (in category 'tests') -----
- testFindContextSuchThat
- self assert: (aBlockContext findContextSuchThat: [:each| true]) printString = aBlockContext printString.
- self assert: (aBlockContext hasContext: aBlockContext). !
Item was removed:
- ----- Method: BlockContextTest>>testNoArguments (in category 'tests') -----
- testNoArguments
- [10
- timesRepeat: [:arg | 1 + 2]]
- ifError: [:err :rcvr | self deny: err = 'This block requires 1 arguments.'].
- [10
- timesRepeat: [:arg1 :arg2 | 1 + 2]]
- ifError: [:err :rcvr | self deny: err = 'This block requires 2 arguments.'] !
Item was removed:
- ----- Method: BlockContextTest>>testBlockIsBottomContext (in category 'tests') -----
- testBlockIsBottomContext
- self should: [aBlockContext client ] raise: Error. "block's sender is nil, a block has no client"
- self assert: aBlockContext bottomContext = aBlockContext.
- self assert: aBlockContext secondFromBottom isNil.!
Item was removed:
- ----- Method: BlockContextTest>>testValueWithArguments (in category 'tests - evaluating') -----
- testValueWithArguments
- self
- should: [aBlockContext
- valueWithArguments: #(1 )]
- raise: Error.
- self
- shouldnt: [aBlockContext
- valueWithArguments: #()]
- raise: Error.
- [aBlockContext
- valueWithArguments: #(1 )]
- ifError: [:err :rcvr | self assert: err = 'Error: This block accepts 0 arguments, but was called with 1.'].
- [[:i | 3 + 4]
- valueWithArguments: #(1 2)]
- ifError: [:err :rcvr | self assert: err = 'Error: This block accepts 1 argument, but was called with 2.']!