[squeak-dev] The Trunk: TrueType-mt.81.mcz

commits at source.squeak.org commits at source.squeak.org
Thu Mar 3 13:15:49 UTC 2022


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].'!



More information about the Squeak-dev mailing list