Marcel Taeumel uploaded a new version of Graphics to project The Trunk:
http://source.squeak.org/trunk/Graphics-mt.498.mcz
==================== Summary ====================
Name: Graphics-mt.498
Author: mt
Time: 14 March 2022, 3:46:04.661786 pm
UUID: 83e89fe1-0c23-5345-b0f9-a17ee4008714
Ancestors: Graphics-mt.497
Adds "text composition" protocol to TextStyle to be able to derive a pixel-based composition rectangle using the style's default font and
(a) number of characters per line
(b) factor of the font's type size
See commentary in methods for more information.
=============== Diff against Graphics-mt.497 ===============
Item was changed:
Object subclass: #TextStyle
+ instanceVariableNames: 'fontArray alignment firstIndent restIndent rightIndent tabsArray marginTabsArray defaultFontIndex lineSpacing normalizedCharacterWidth'
- instanceVariableNames: 'fontArray alignment firstIndent restIndent rightIndent tabsArray marginTabsArray defaultFontIndex lineSpacing'
classVariableNames: 'NumSpacesPerTab'
poolDictionaries: 'TextConstants'
category: 'Graphics-Text'!
!TextStyle commentStamp: 'mt 2/21/2022 10:55' prior: 0!
A text style comprises the formatting information for composing and displaying a unit (usually a paragraph) of text. It provides a #defaultFont to use, but text attributes can change that per character (see CompositionScanner and DisplayScanner). It also has a default #alignment that attributes can override. Those defaults make it possible to compose and display (unformatted) strings in paragraphs without having to style them first as texts (i.e., string+attributes).
NOTE THAT for each use you *must* make a copy of a font's master text style (e.g., "TextStyle default copy") or create a fresh one with at least a single font (see TextStyle class >> #fontArray: and AbstractFont >> #asNewTextStyle). That specific instance is typically altered in the process of editing: change default font size, change default alignment, ... and you wouldn't want to change that properties for other applications by accident.
A text style also drives the interpretation of Character tab. Both tabsArray and marginTabsArray are initialized for the #defaultFont(Index:). When you change a style's default font size, those "tab positions" will be recomputed for fast access during composition. See the preference #numSpacesPerTab(:).
While each text style looks like it could handle an arbitrary array of fonts, it is *best practice* to only store fonts of the same font family. A font's master style thus collects all known point sizes at a single place (i.e. "TextStyle named: aFamilyName"). Copies will share that array. The attribute TextFontChange makes it possible to switch to any index in that array, but this is not portable and hence discouraged. TextFontReference adds an explicit reference to font, which is also not good. (February 2022: We plan to add TextFont(Point)Size and TextFontFamily as a portable way to change the font per character.).
There are some legacy information, which should no longer be used:
- #baseline: ... used to prescribe baseline info but is now completely derived from #defaultFont
- #lineGrid: ... same as #baseLine:
- #leading(:) ... is replaced by #lineSpacing(:) and denotes the extra spacing relative to the respective line's height in the composition
The #lineSpacing is noticeable in a paragraph's text selection. Line spacing < 0.0 will appear as overlaps between (translucent) selection rectangles. Lince spacing > 0.0 will appear as gaps between selection rectangles.
Here are some example styles to explore:
- TextStyle default
- TextStyle defaultFixes!
Item was added:
+ ----- Method: TextStyle>>compositionWidthFor: (in category 'text composition') -----
+ compositionWidthFor: aNumber
+ "Answer the width of the composition rectangle in pixels using the receiver's #defaultFont.
+ - Positive numbers are used as number of characters per line
+ - Negative numbers are used as factor of #typoTypeSize
+ - Zero will try to approximate 66 characters per line
+ See commentaries in both #compositionWidthForTypeFactor and #compositionWidthForNumChars."
+
+ aNumber = 0 ifTrue: [^ self compositionWidthForNumChars].
+
+ ^ aNumber > 0
+ ifTrue: [self compositionWidthForNumChars: aNumber]
+ ifFalse: [self compositionWidthForTypeFactor: aNumber negated]!
Item was added:
+ ----- Method: TextStyle>>compositionWidthForNumChars (in category 'text composition') -----
+ compositionWidthForNumChars
+ "Constant is based on the book
+ The Elements of Typographic Style (version 3.0)
+ by Robert Bringhurst
+
+ Excerpts from Section 2.1.2 Choose a comfortable measure, page 26:
+ [...] Anything from 45 to 75 characters is widely regarded as a satisfactory length of a line for a single-column page set in a serifed text face in a text size. The 66-character line (counting both letters and spaces) is widely regarded as ideal. For multiple-column work, a better average is 40 to 50 characters. [...]
+
+ Note that these numbers consider continuous text in English."
+
+ ^ self compositionWidthForNumChars: 66!
Item was added:
+ ----- Method: TextStyle>>compositionWidthForNumChars: (in category 'text composition') -----
+ compositionWidthForNumChars: numChars
+ "Answer the width of the composition rectangle in pixels for numChars
+ using the receiver's #defaultFont.
+
+ You can compare this with other ways to prescribe a 'sheet of paper' for
+ arbitrary content as follows:
+
+ | sample style font |
+ sample := 'the quick brown fox jumps over the lazy dog'.
+ style := TextStyle default.
+ font := style defaultFont.
+ ((1 to: sample size) collect: [:i | {
+ font widthOfString: (sample first: i).
+ style compositionWidthForNumChars: i.
+ (font widthOf: $x) * i.
+ (font widthOf: $m) * i }]) explore
+
+ As you can see, using $x or $m will typically overshoot the values of
+ #widthOfString: and #compositionWidthForNumChars:.
+ "
+
+ ^ (self normalizedCharacterWidth * numChars) truncated!
Item was added:
+ ----- Method: TextStyle>>compositionWidthForTypeFactor (in category 'text composition') -----
+ compositionWidthForTypeFactor
+ "Constant is based on the book
+ The Elements of Typographic Style (version 3.0)
+ by Robert Bringhurst
+
+ Excerpt from Section 2.1.2 Choose a comfortable measure, page 27:
+ [...] On a conventional book page, the measure, or length of line, is usually around 30 times the size of the type, but lines as little as 20 or as much as 40 times the type size fall within the expectable range. [...]
+
+ Note that these numbers consider continuous text in English."
+
+ ^ self compositionWidthForTypeFactor: 30!
Item was added:
+ ----- Method: TextStyle>>compositionWidthForTypeFactor: (in category 'text composition') -----
+ compositionWidthForTypeFactor: typeFactor
+ "Answers a default composition width for the given typeFactor."
+
+ ^ (self typoTypeSize * typeFactor) truncated!
Item was changed:
----- Method: TextStyle>>defaultFontIndex: (in category 'accessing - default font') -----
defaultFontIndex: anIndex
defaultFontIndex := anIndex.
+
+ self initializeTabsArray.
+ self initializeNormalizedCharacterWIdth.!
- self initializeTabsArray.!
Item was removed:
- ----- Method: TextStyle>>flushFonts (in category 'fonts and font indexes') -----
- flushFonts
- "Clean out the fonts, an aid when snapshotting claims too many are
- holding onto Display."
-
- (self confirm:
- 'flushFonts is very dangerous.
- Are you foolish or clever enough to proceed?')
- ifTrue: [1 to: fontArray size do: [:index | fontArray at: index put: nil]]
- ifFalse: [Transcript cr; show: 'flushFonts cancelled']
-
- "TextStyle default flushFonts"!
Item was added:
+ ----- Method: TextStyle>>initializeNormalizedCharacterWIdth (in category 'initialize-release') -----
+ initializeNormalizedCharacterWIdth
+
+ normalizedCharacterWidth := nil.!
Item was added:
+ ----- Method: TextStyle>>normalizedCharacterWidth (in category 'text composition') -----
+ normalizedCharacterWidth
+ "Answer the normalized character width to compute a pixel-based box for text composition that follows what you specify via #compositionWidthForNumChars:. Cached for performance.
+
+ Alphabet-divide constant is based on the book (table on page 29):
+ The Elements of Typographic Style (version 3.0)
+ by Robert Bringhurst"
+
+ ^ normalizedCharacterWidth ifNil: [
+ normalizedCharacterWidth := self defaultFont hasFixedWidth
+ ifTrue: [ self defaultFont widthOf: $M "often ~= #typoTypeSize!!"]
+ ifFalse: [ self typoAlphabetLength asFloat * 0.036 ]]!
Item was added:
+ ----- Method: TextStyle>>typoAlphabetLength (in category 'text composition') -----
+ typoAlphabetLength
+ "
+ TextStyle default typoAlphabetLength.
+ TextStyle defaultFixed typoAlphabetLength.
+ "
+ | font |
+ font := self defaultFont.
+ ^ ($a to: $z) inject: 0 into: [:sum :char | sum + (font widthOf: char)]!
Item was added:
+ ----- Method: TextStyle>>typoTypeSize (in category 'text composition') -----
+ typoTypeSize
+ "
+ TextStyle default typoTypeSize.
+ TextStyle defaultFixed typoTypeSize.
+ "
+ ^ self defaultFont height!
Marcel Taeumel uploaded a new version of Morphic to project The Trunk:
http://source.squeak.org/trunk/Morphic-mt.1932.mcz
==================== Summary ====================
Name: Morphic-mt.1932
Author: mt
Time: 14 March 2022, 10:02:24.651667 am
UUID: c8609f8b-c215-694e-9b4f-179e7791069b
Ancestors: Morphic-mt.1931
Fixes regression in text-morph editing for text morphs that are not inside a cozy scroll container. :-)
=============== Diff against Morphic-mt.1931 ===============
Item was changed:
----- Method: NewParagraph>>recomposeFrom:to:delta: (in category 'composition') -----
recomposeFrom: start to: stop delta: delta
"Recompose this paragraph. The altered portion is between start and stop.
Recomposition may continue to the end of the text, due to a ripple effect.
Delta is the amount by which the current text is longer than it was
when its current lines were composed."
| startLine newLines |
containerUnadjusted ifNotNil: [
+ "Somebody called #adjustRightX. We must recompose everything to
+ avoid strange line breaks and clipping."
+ container := container topLeft extent: containerUnadjusted extent.
+ self composeAll; adjustRightX.
+ ^ self].
- "Somebody called #adjustRightX. We must recompose everything to avoid strange line breaks and clipping."
- container := containerUnadjusted. self composeAll; adjustRightX. ^ self].
"Have to recompose line above in case a word-break was affected."
startLine := (self lineIndexOfCharacterIndex: start) - 1 max: 1.
[startLine > 1 and: [(lines at: startLine-1) top = (lines at: startLine) top]]
whileTrue: [startLine := startLine - 1]. "Find leftmost of line pieces"
newLines := OrderedCollection new: lines size + 1.
1 to: startLine-1 do: [:i | newLines addLast: (lines at: i)].
self composeLinesFrom: (lines at: startLine) first to: stop delta: delta
into: newLines priorLines: lines
atY: (lines at: startLine) top!
Marcel Taeumel uploaded a new version of System to project The Trunk:
http://source.squeak.org/trunk/System-mt.1324.mcz
==================== Summary ====================
Name: System-mt.1324
Author: mt
Time: 13 March 2022, 11:17:15.987963 am
UUID: 9e2ffeff-1a53-2147-af3a-5f907f674683
Ancestors: System-mt.1323
Fixes endless loop on image start-up. Sorry... :/
If you happen do have a stuck image, use DoItFirst or hide your .changes file to then apply this fix manually when the dialog box about not finding the .changes file pops up.
=============== Diff against System-mt.1323 ===============
Item was changed:
----- Method: Locale>>fetchCurrencySymbol (in category 'initialize-release') -----
fetchCurrencySymbol
+ "Note that we MUST NOT use #currentPlatform here bc. we might currently just initialize it here."
+
-
| raw |
raw := self primCurrencySymbol.
+ Smalltalk platformName = 'Win32'
+ ifTrue: [raw := raw convertFromEncoding: 'cp1252'].
- (Smalltalk platformName = 'Win32'
- and: [Locale currentPlatform languageEnvironment isKindOf: Latin1Environment])
- ifTrue: [raw := raw convertFromEncoding: 'cp1252'].
^ raw!
Marcel Taeumel uploaded a new version of System to project The Trunk:
http://source.squeak.org/trunk/System-mt.1322.mcz
==================== Summary ====================
Name: System-mt.1322
Author: mt
Time: 11 March 2022, 10:26:25.956495 am
UUID: 0b5b1557-96a7-3b43-80bc-44e8dae51b2b
Ancestors: System-eem.1321
Fixes locale changes when switching between projects.
=============== Diff against System-eem.1321 ===============
Item was changed:
----- Method: Project class>>localeChanged (in category 'class initialization') -----
localeChanged
+
+ self current localeChanged.!
- self current class == self
- ifTrue: [self current localeChanged].!
Item was changed:
----- Method: Project>>updateLocaleDependents (in category 'language') -----
updateLocaleDependents
"Set the project's natural language as indicated"
+ !
-
- Locale localeChanged.!
Marcel Taeumel uploaded a new version of System to project The Trunk:
http://source.squeak.org/trunk/System-mt.1322.mcz
==================== Summary ====================
Name: System-mt.1322
Author: mt
Time: 11 March 2022, 10:26:25.956495 am
UUID: 0b5b1557-96a7-3b43-80bc-44e8dae51b2b
Ancestors: System-eem.1321
Fixes locale changes when switching between projects.
=============== Diff against System-eem.1321 ===============
Item was changed:
----- Method: Project class>>localeChanged (in category 'class initialization') -----
localeChanged
+
+ self current localeChanged.!
- self current class == self
- ifTrue: [self current localeChanged].!
Item was changed:
----- Method: Project>>updateLocaleDependents (in category 'language') -----
updateLocaleDependents
"Set the project's natural language as indicated"
+ !
-
- Locale localeChanged.!
Marcel Taeumel uploaded a new version of MorphicExtras to project The Trunk:
http://source.squeak.org/trunk/MorphicExtras-lrnp.308.mcz
==================== Summary ====================
Name: MorphicExtras-lrnp.308
Author: lrnp
Time: 2 March 2022, 9:53:05.152048 pm
UUID: aaa42c8a-2ead-42a8-ae9f-e7802c4b176f
Ancestors: MorphicExtras-mt.307
Put the book, not true, in the return position.
Must Do-It:
ScrapBook cleanUp: true.
when updating in-place.
=============== Diff against MorphicExtras-mt.307 ===============
Item was changed:
----- Method: ScrapBook>>scrapBook (in category 'scraps') -----
scrapBook
| header aButton label |
^ book ifNil: [
book := BookMorph new pageSize: 300@300; setNameTo: 'scraps' translated.
book addCornerGrips.
book color: Color yellow muchLighter.
book borderColor: Color darkGray; borderWidth: 2.
book removeEverything; showPageControls; insertPage.
header := AlignmentMorph newRow wrapCentering: #center; cellPositioning: #leftCenter.
header setProperty: #header toValue: true.
header addMorph: (aButton := ThreePhaseButtonMorph labelSymbol: #'Halo-Collapse').
aButton target: book;
actionSelector: #delete;
setBalloonText: 'Close the trashcan.\(to view again later, click on any trashcan).' translated withCRs.
header addMorphBack: AlignmentMorph newVariableTransparentSpacer beSticky.
header addMorphBack: (label := UpdatingStringMorph new target: self) beSticky.
label getSelector: #trashTitle; useStringFormat; step.
header addMorphBack: AlignmentMorph newVariableTransparentSpacer beSticky.
header addMorphBack: (aButton := ThreePhaseButtonMorph labelSymbol: #'Halo-Dismiss').
aButton target: self;
actionSelector: #maybeEmptyTrash;
setBalloonText: 'Click here to empty the trash.' translated.
book currentPage
layoutPolicy: TableLayout new;
addMorph: (TextMorph new
contents: 'Objects you drag into the trash will automatically be saved here, one object per page, in case you need them later. To disable this feature set the "preserveTrash" Preference to false.\\You can individually expunge objects by hitting the "-" control (behind "..."). You can empty out all the objects in the trash can by hitting the "X" button at top right.' translated withCRs;
hResizing: #spaceFill).
book addMorphFront: header.
+ book setProperty: #scraps toValue: true.
+ book].!
- book setProperty: #scraps toValue: true].!
Marcel Taeumel uploaded a new version of MorphicExtras to project The Trunk:
http://source.squeak.org/trunk/MorphicExtras-mt.311.mcz
==================== Summary ====================
Name: MorphicExtras-mt.311
Author: mt
Time: 11 March 2022, 10:23:52.103495 am
UUID: ba283975-c297-4148-a39d-1d4e56c16454
Ancestors: MorphicExtras-mt.310, MorphicExtras-lrnp.308
Merges fix from MorphicExtras-lrnp.308 now that #setProperty:toValue: returns the set property and not the receiver anymore. Let's hope that those incidents are rare.
Thanks to Lauren (lrnp) for spotting this!
=============== Diff against MorphicExtras-mt.310 ===============
Item was changed:
----- Method: ScrapBook>>scrapBook (in category 'scraps') -----
scrapBook
| header aButton label |
^ book ifNil: [
book := BookMorph new pageSize: 300@300; setNameTo: 'scraps' translated.
book addCornerGrips.
book color: Color yellow muchLighter.
book borderColor: Color darkGray; borderWidth: 2.
book removeEverything; showPageControls; insertPage.
header := AlignmentMorph newRow wrapCentering: #center; cellPositioning: #leftCenter.
header setProperty: #header toValue: true.
header addMorph: (aButton := ThreePhaseButtonMorph labelSymbol: #'Halo-Collapse').
aButton target: book;
actionSelector: #delete;
setBalloonText: 'Close the trashcan.\(to view again later, click on any trashcan).' translated withCRs.
header addMorphBack: AlignmentMorph newVariableTransparentSpacer beSticky.
header addMorphBack: (label := UpdatingStringMorph new target: self) beSticky.
label getSelector: #trashTitle; useStringFormat; step.
header addMorphBack: AlignmentMorph newVariableTransparentSpacer beSticky.
header addMorphBack: (aButton := ThreePhaseButtonMorph labelSymbol: #'Halo-Dismiss').
aButton target: self;
actionSelector: #maybeEmptyTrash;
setBalloonText: 'Click here to empty the trash.' translated.
book currentPage
layoutPolicy: TableLayout new;
addMorph: (TextMorph new
contents: 'Objects you drag into the trash will automatically be saved here, one object per page, in case you need them later. To disable this feature set the "preserveTrash" Preference to false.\\You can individually expunge objects by hitting the "-" control (behind "..."). You can empty out all the objects in the trash can by hitting the "X" button at top right.' translated withCRs;
hResizing: #spaceFill).
book addMorphFront: header.
+ book setProperty: #scraps toValue: true.
+ book].!
- book setProperty: #scraps toValue: true].!