Marcel Taeumel uploaded a new version of TrueType to project The Trunk: http://source.squeak.org/trunk/TrueType-mt.81.mcz
==================== Summary ====================
Name: TrueType-mt.81 Author: mt Time: 3 March 2022, 2:15:48.031142 pm UUID: 46619d54-c342-e240-8224-44cee41f77ad Ancestors: TrueType-dtl.80
Bugfixes: - "Install & Load" will now configure the glyphTable with the correct fallback glyph; does not affect remote fonts - kernPairs must keep their glyph indexes bc. multiple code points can map to the same glyph
Enhancements: - Install "Unicode BMP" character mapping for our Bitstream Vera fonts bc. we have all the glyphs; limit #maxCodePoint to 255 until we have a better strategy for our glyph-form cache in TTCFont - Increase robustness in TTFontFileHandle against whitespace-typos in family name; e.g., merge "OpenDyslexic 3" and "OpenDyslexic3" to bundle regular and bold face - create a #cmapTable on-the-fly for TTFontDescription using glyphTable - Adds a compression protocol to TTCharacterMappingTable
=============== Diff against TrueType-dtl.80 ===============
Item was added: + ----- Method: TTCharacterMappingTable class>>fromCompressedBytes:perElement: (in category 'instance creation') ----- + fromCompressedBytes: bytes perElement: bytesPerElement + + | cmap | + cmap := self new platformID: -1; "Squeak" yourself. + cmap setCharacterMapFromCompressedBytes: bytes perElement: bytesPerElement. + cmap encodingID: (cmap size caseOf: { + [256] -> [0 "Latin1"]. + [65536] -> [2 "Unicode BMP"]. + } otherwise: [3 "Unicode full -- wild guess"]). + ^ cmap!
Item was added: + ----- Method: TTCharacterMappingTable>>characterMapAsCompressedBytes (in category 'compressing') ----- + characterMapAsCompressedBytes + + | max | + ^ (max := characterMap max) > 16rFFFF + ifTrue: [self characterMapAsCompressedBytes: 4] + ifFalse: [max > 16rFF + ifTrue: [self characterMapAsCompressedBytes: 2] + ifFalse: [self characterMapAsCompressedBytes: 1]]!
Item was added: + ----- Method: TTCharacterMappingTable>>characterMapAsCompressedBytes: (in category 'compressing') ----- + characterMapAsCompressedBytes: bytesPerElement + + | bitmap | + bytesPerElement = 4 ifTrue: [ + "Bitmap is a variable-word subclass, which means 4 bytes per element." + ^ (characterMap as: Bitmap) compressToByteArray]. + + bitmap := Bitmap new: (characterMap size asFloat / bytesPerElement) ceiling. + 1 to: bitmap size do: [:i | + | elements x | + elements := (1 to: 4 // bytesPerElement) + collect: [:j | characterMap at: ((i-1)*bytesPerElement)+j ifAbsent: [0 "bc. #ceiling"]]. + x := 0. + 1 to: elements size do: [:e | + x := (x bitShift: bytesPerElement*8) + (elements at: e)]. + bitmap at: i put: x]. + + ^ bitmap compressToByteArray!
Item was changed: ----- Method: TTCharacterMappingTable>>createGlyphTableFrom: (in category 'mapping') ----- createGlyphTableFrom: allGlyphsInGlyphIndexOrder "Answer a table that can lookup TrueType glyphs by Unicode code point. Note that allGlyphs *must be* in glyphIndex order or otherwise the resulting table will be incorrect."
| mappedGlyphTable fallbackGlyph | self assert: [platformID = -1] description: 'You must call #prepare first!!'. + fallbackGlyph := allGlyphsInGlyphIndexOrder first. - fallbackGlyph := allGlyphsInGlyphIndexOrder. mappedGlyphTable := encodingID = 0 "latin-1" ifTrue: [Array new: 256 withAll: fallbackGlyph] ifFalse: [SparseLargeTable new: characterMap size chunkSize: 256 arrayClass: Array base: 1 defaultValue: fallbackGlyph].
1 to: characterMap size do: [:i | | glyph glyphIndex | glyphIndex := characterMap at: i. glyph := allGlyphsInGlyphIndexOrder at: glyphIndex+1 ifAbsent: [fallbackGlyph]. mappedGlyphTable at: i put: glyph].
encodingID = 0 ifFalse: [mappedGlyphTable zapDefaultOnlyEntries]. self flag: #todo. "Discard unused glyphs such as ligatures etc. We do not support them." ^ mappedGlyphTable!
Item was added: + ----- Method: TTCharacterMappingTable>>setCharacterMapFromCompressedBytes:perElement: (in category 'compressing') ----- + setCharacterMapFromCompressedBytes: bytes perElement: bytesPerElement + + | bitmap numElements | + bitmap := Bitmap decompressFromByteArray: bytes. + numElements := bitmap size * (4 // bytesPerElement). + + numElements = 256 + ifTrue: [characterMap := Array new: numElements] + ifFalse: [characterMap := (SparseLargeTable new: numElements + chunkSize: 256 arrayClass: Array base: 1 + defaultValue: 0)]. + + bytesPerElement = 4 ifTrue: [ + characterMap fillFrom: bitmap with: [:glyphIndex | glyphIndex]. + numElements = 256 ifFalse: [characterMap zapDefaultOnlyEntries]. + ^ self]. + + 1 to: bitmap size do: [:i | + | elements mask x | + x := bitmap at: i. + elements := Array new: 4 // bytesPerElement. + mask := (1 << (bytesPerElement*8)) -1. + elements size to: 1 by: -1 do: [:j | + elements + at: (elements size - j + 1) + put: ((x bitShift: bytesPerElement * 8 * (j-1) * -1) bitAnd: mask)]. + 1 to: elements size do: [:j | + characterMap + at: ((i-1)*bytesPerElement)+j + put: (elements at: j)]]. + + numElements = 256 ifFalse: [characterMap zapDefaultOnlyEntries].!
Item was changed: + ----- Method: TTFontDescription>>allGlyphs (in category 'accessing - debugging') ----- - ----- Method: TTFontDescription>>allGlyphs (in category 'accessing') ----- allGlyphs
^ glyphs!
Item was added: + ----- Method: TTFontDescription>>allKernPairs (in category 'accessing - debugging') ----- + allKernPairs + + ^ kernPairs!
Item was added: + ----- Method: TTFontDescription>>cmapTable (in category 'accessing') ----- + cmapTable + "Construct on-the-fly from glyphTable. Maybe cache later? Maybe there is no need for glyphTable but only cmapTable like in TTRemoteFontDescription?" + + ^ TTCharacterMappingTable new + platformID: -1; "Squeak" + encodingID: (glyphTable size caseOf: { + [256] -> [0 "Latin1"]. + [65536] -> [2 "Unicode BMP"]. + } otherwise: [3 "Unicode full -- wild guess"]); + characterMap: (glyphTable collect: [:glyph | glyph glyphIndex]); + yourself!
Item was changed: + ----- Method: TTFontDescription>>maxGlyphIndex (in category 'accessing - debugging') ----- - ----- Method: TTFontDescription>>maxGlyphIndex (in category 'accessing') ----- maxGlyphIndex
^ glyphs size - 1!
Item was changed: ----- Method: TTFontDescription>>size (in category 'accessing') ----- size
+ ^ maxCodePoint ifNil: [glyphTable size]! - ^ glyphTable size. - !
Item was changed: ----- Method: TTFontFileHandle class>>allHandlesFrom: (in category 'support') ----- allHandlesFrom: specs
| handles | handles := Dictionary new. "Use family name as #key to accumulate families from files."
specs do: [:spec | | familyName subfamilyName fileName fileOffset familyHandle ttc | familyName := spec at: 1. subfamilyName := spec at: 2. fileName := spec at: 3 ifAbsent: nil. "installed but unknown file" fileOffset := spec at: 4 ifAbsent: nil. "installed but unknown file" ttc := spec at: 5 ifAbsent: nil. "already parsed" familyHandle := handles + at: (familyName copyWithout: Character space) "Robustness. Typos are possible" - at: familyName ifAbsentPut: [TTFontFileHandle new fontname: familyName; yourself]. subfamilyName ifNil: [ familyHandle filename: fileName; fileoffset: fileOffset; setFontDescription: ttc] ifNotNil: [ | subfamilyHandle | subfamilyHandle := TTFontFileHandle new fontname: subfamilyName; yourself. subfamilyHandle parent: familyHandle; filename: fileName; fileoffset: fileOffset; setFontDescription: ttc. familyHandle addChild: subfamilyHandle]]. ^ handles!
Item was changed: ----- Method: TTFontReader>>processKerningTable (in category 'reading - tables') ----- processKerningTable
self checkFontOffset. self peekDuring: [ (self skipToTable: 'kern') ifFalse: [^ self "optional"]. (self peekDuring: [self readKerningTable]) ifFalse: [self readKerningTableForMacintosh]]. "Post-processing. Prefer only #kerning values for #horizontal text layout." kernPairs := kernTables detect: [:table | table first includesAllOf: #(horizontal kerning)] ifFound: [:table | table second] + ifNone: [#()].! - ifNone: [#()]. - - "Map glyph index to a character to be used, e.g., in CharacterScanner." - kernPairs do: [:kp | - kp left: ((cmapTable mapIndex: kp left) - ifNotNil: [:codePoint | Character value: codePoint]). - kp right: ((cmapTable mapIndex: kp right) - ifNotNil: [:codePoint | Character value: codePoint])]. - - "Only work with kerning metrics for glyphs that are referenced in the cmap." - kernPairs := kernPairs select: [:kp | kp left notNil and: [kp right notNil]].!
Item was changed: + ----- Method: TTRemoteFontDescription>>maxGlyphIndex (in category 'accessing - debugging') ----- - ----- Method: TTRemoteFontDescription>>maxGlyphIndex (in category 'accessing - glyphs') ----- maxGlyphIndex
^ numGlyphs-1!
Item was changed: + (PackageInfo named: 'TrueType') postscript: '"Repair all kern pairs. We must keep glyph indexes in there. TTFontReader was updated, too." + TTFontDescription allSubInstancesDo: [:ttc | | cmap | + cmap := ttc cmapTable. + ttc allKernPairs do: [:kp | + kp left isCharacter ifTrue: [ + kp left: (cmap mapCode: kp left codePoint)]. + kp right isCharacter ifTrue: [ + kp right: (cmap mapCode: kp right codePoint)]] ]. + + "Install Unicode BMP character mapping for Bitstream Vera font families. But limit to maxCodePoint 255 until we find a better strategy for the glyph cache." + [ | cmap | + cmap := ''/wAAgABBAMMAAwAEAAUABgAHAAgACQAKAAsADAANAA4ADwAQABEAEgATABQAFQAWABcAGAAZ + ABoAGwAcAB0AHgAfACAAIQAiACMAJAAlACYAJwAoACkAKgArACwALQAuAC8AMAAxADIAMwA0 + ADUANgA3ADgAOQA6ADsAPAA9AD4APwBAAEEAQgBDAEQARQBGAEcASABJAEoASwBMAE0ATgBP + AFAAUQBSAFMAVABVAFYAVwBYAFkAWgBbAFwAXQBeAF8AYABhAABBAMMArACjAIQAhQC9AJYA + 5wCGAI4AiwCdAKkApAEAAIoA2QCDAJMA8QDyAI0AlwCIAMMA3QDwAJ4AqgDzAPQA9QCiAK0A + yQDHAK4AYgBjAJAAZADLAGUAyADKAM8AzADNAM4A6ABmANIA0ADRAK8AZwDvAJEA1QDTANQA + aADqAOwAiQBqAGkAawBtAGwAbgCgAG8AcQBwAHIAcwB1AHQAdgB3AOkAeAB6AHkAewB9AHwA + uAChAH8AfgCAAIEA6wDtALoNAAcA+wD8CQAPAP0A/gAAAAAAAAD/GQAHAPYA9yEABwD4ANYd + AAsAAADhAOIAAB0ABwCwALEVAAsA+QD6AOMA5C0AEwC7AAAAAAAAAAAA5QDmAAAlAAcApgAA + 4mUABwDXAOAhAA8A2gDbANwA3wDYAN7hlQAHAAAAny0ABwCbAAD/AAA4oQAvAAAAsgCzAAAA + AAAAALYAtwDEAAAAtAC1AMUAAACCAMIAhwAAAAAAAACrAAARAAcAxgAADQALAAAAvgC/AADg + 4QAHAQIAAODpAAcAjAAA4b0ADwCYAAAAAAAAAKgAAA0AJwAAAJoAAACZAO4AAAAAALwAAAAA + AAABAQClAAAAAAAAAJIAABUABwAAAJw5AAcApwAALQAPAI8AAAAAAAAAlACV5skABwC5AAD/ + AAGqaQALAAAAwADBAADp+QA=''. + cmap := TTCharacterMappingTable + fromCompressedBytes: cmap base64Decoded asByteArray + perElement: 2. + + (#(BitstreamVeraSans BitstreamVeraSansMono BitstreamVeraSerif) + gather: [:family | | font | + font := TTCFont familyName: family. + {font ttcDescription}, (font derivativeFonts + select: [:ea | ea isSynthetic not] thenCollect: [:ea | ea ttcDescription])]) + do: [:ttc | + ttc + setGlyphs: ttc allGlyphs mapping: (cmap createGlyphTableFrom: ttc allGlyphs); + setMinCodePoint: 32 maxCodePoint: 255]. + ] value.'! - (PackageInfo named: 'TrueType') postscript: '#( - BitstreamVeraSans 1.059 24 ''Bitstream Vera Sans For Squeak'' - BitstreamVeraSansMono 1.059 24 ''Bitstream Vera Sans Mono For Squeak'' - ) groupsDo: [:name :scale :gap :customName | - (TextStyle named: name) asHandle - rename: customName; - ttExtraScale: scale; ttExtraGap: gap; - installFont].'!
squeak-dev@lists.squeakfoundation.org