[ENH] Displaying undefined glyphs
Andreas Raab
andreas.raab at gmx.de
Sun Apr 10 10:42:05 UTC 2005
Folks -
It has annoyed me for a long time that MultiCharacters are often only
displayed as question marks which makes it very simple to confuse them
with a real question mark. The attached changes fix this so that e.g.,
"Character value: 500" is printed as \u1F4. The attached images
illustrate the difference. How the undefined character is displayed can
be changed in Character>>asUndefinedGlyph (so if you prefer to prefer
<Character value: 500> instead you are free to do this ;-)
Cheers,
- Andreas
-------------- next part --------------
'From Squeak3.8gamma of ''24 November 2004'' [latest update: #6643] on 10 April 2005 at 3:34:54 am'!
"Change Set: DisplayUndefined
Date: 10 April 2005
Author: Andreas Raab
Change the display of undefined characters from a question mark to a \uXYZ format. E.g., instead of
Character value: 500 -> $?
Character value: 500 -> $\u1F4
"!
!AbstractFont methodsFor: 'measuring' stamp: 'ar 4/10/2005 03:14'!
widthOf: aCharacter
"Answer the width of the argument as a character in the receiver."
^self widthOf: aCharacter ifAbsent:[self widthOfString: aCharacter asUndefinedGlyph].! !
!AbstractFont methodsFor: 'measuring' stamp: 'ar 4/10/2005 03:02'!
widthOf: aCharacter ifAbsent: aBlock
"Return the width of the given character if defined in the font.
If absent evaluate aBlock."
^self subclassResponsibility! !
!Character methodsFor: 'printing' stamp: 'ar 4/10/2005 03:00'!
asUndefinedGlyph
^'\u', (value printStringBase: 16)! !
!FixedFaceFont methodsFor: 'measuring' stamp: 'ar 4/10/2005 03:03'!
widthOf: aCharacter ifAbsent: aBlock
"Characters are always defined in a fixed face font"
^ baseFont widthOf: substitutionCharacter! !
!StrikeFont methodsFor: 'accessing' stamp: 'ar 4/10/2005 03:04'!
widthOf: aCharacter ifAbsent: aBlock
"Characters are always defined in a fixed face font"
| code |
code := aCharacter class == Character
ifTrue: [aCharacter asciiValue]
ifFalse: [aCharacter charCode].
((code < minAscii or: [maxAscii < code]) or: [(xTable at: code + 1) < 0])
ifTrue: [^aBlock value].
^(xTable at: code + 2) - (xTable at: code + 1)! !
!StrikeFont methodsFor: 'displaying' stamp: 'ar 4/10/2005 03:20'!
displayMultiString: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta baselineY: baselineY
| destPoint leftX rightX glyphInfo char destY str |
destPoint _ aPoint.
charIndex _ startIndex.
glyphInfo _ Array new: 5.
[charIndex <= stopIndex] whileTrue: [
char _ aString at: charIndex.
(self hasGlyphOf: char) not ifTrue: [
str := char asUndefinedGlyph.
destPoint := self displayString: str on: aBitBlt from: 1 to: str size at: destPoint kern: kernDelta baselineY: baselineY.
charIndex _ charIndex + 1.
] ifFalse: [
self glyphInfoOf: char into: glyphInfo.
leftX _ glyphInfo second.
rightX _ glyphInfo third.
(glyphInfo fifth ~= aBitBlt lastFont) ifTrue: [
glyphInfo fifth installOn: aBitBlt.
].
aBitBlt sourceForm: glyphInfo first.
destY _ baselineY - glyphInfo fourth.
aBitBlt destX: destPoint x.
aBitBlt destY: destY.
aBitBlt sourceOrigin: leftX @ 0.
aBitBlt width: rightX - leftX.
aBitBlt height: self height.
aBitBlt copyBits.
destPoint _ destPoint + (rightX - leftX + kernDelta @ 0).
charIndex _ charIndex + 1.
].
].
^destPoint.
! !
!StrikeFontSet methodsFor: 'accessing' stamp: 'ar 4/10/2005 03:09'!
widthOf: aCharacter ifAbsent: aBlock
"Answer the width of the argument as a character in the receiver."
"1: optimizing"
| encoding f |
aCharacter class == Character
ifTrue: [^ (fontArray at: 1) widthOf: aCharacter].
"2: other case"
encoding := aCharacter leadingChar + 1.
f := ((((aCharacter isMemberOf: Character) not
and: [encoding > 1])
and: [encoding <= fontArray size])
and: [(fontArray at: encoding) notNil])
ifTrue: [fontArray at: encoding]
ifFalse: [^aBlock value].
^ f widthOf: aCharacter ifAbsent: aBlock! !
!StrikeFontSet methodsFor: 'displaying' stamp: 'ar 4/10/2005 03:27'!
displayString: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta baselineY: baselineY
| destPoint leftX rightX glyphInfo g destY ch str |
destPoint _ aPoint.
glyphInfo _ Array new: 5.
startIndex to: stopIndex do: [:charIndex |
ch _ aString at: charIndex.
(self hasGlyphOf: ch) ifTrue:[
self glyphInfoOf: ch into: glyphInfo.
g _ glyphInfo first.
leftX _ glyphInfo second.
rightX _ glyphInfo third.
(glyphInfo fifth ~= aBitBlt lastFont) ifTrue: [
glyphInfo fifth installOn: aBitBlt.
].
aBitBlt sourceForm: g.
destY _ baselineY - glyphInfo fourth.
aBitBlt destX: destPoint x.
aBitBlt destY: destY.
aBitBlt sourceOrigin: leftX @ 0.
aBitBlt width: rightX - leftX.
aBitBlt height: self height.
aBitBlt copyBits.
destPoint _ destPoint + (rightX - leftX + kernDelta @ 0).
] ifFalse:[
str _ ch asUndefinedGlyph.
destPoint _ self displayString: str on: aBitBlt from: 1 to: str size at: destPoint kern: kernDelta baselineY: baselineY.
].
].
^ destPoint.
! !
!StrikeFontSet methodsFor: 'private' stamp: 'ar 4/10/2005 03:26'!
hasGlyphOf: aCharacter
| index f code leftX |
index _ aCharacter leadingChar + 1.
fontArray size < index ifTrue: [^false].
(f _ fontArray at: index) ifNil: [^false].
code _ aCharacter charCode.
((code between: f minAscii and: f maxAscii) not) ifTrue: [^false].
leftX _ f xTable at: code + 1.
leftX < 0 ifTrue: [^ false].
^true! !
!TTCFont methodsFor: 'friend' stamp: 'ar 4/10/2005 03:28'!
displayString: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta baselineY: baselineY
| destPoint form glyphInfo destY ch str |
destPoint _ aPoint.
glyphInfo _ Array new: 5.
startIndex to: stopIndex do: [:charIndex |
ch _ aString at: charIndex.
(self hasGlyphOf: ch) ifTrue:[
self glyphInfoOf: ch into: glyphInfo.
form _ glyphInfo first.
(glyphInfo fifth ~= aBitBlt lastFont) ifTrue: [
glyphInfo fifth installOn: aBitBlt.
].
destY _ baselineY - glyphInfo fourth.
aBitBlt sourceForm: form.
aBitBlt destX: destPoint x.
aBitBlt destY: destY.
aBitBlt sourceOrigin: (glyphInfo second) @ 0.
aBitBlt width: glyphInfo third - glyphInfo second.
aBitBlt height: form height.
aBitBlt copyBits.
destPoint _ destPoint + ((glyphInfo third - glyphInfo second) + kernDelta @ 0).
] ifFalse:[
str _ ch asUndefinedGlyph.
destPoint _ self displayString: str on: aBitBlt from: 1 to: str size at: destPoint kern: kernDelta baselineY: baselineY.
].
].
^ destPoint.
! !
!TTCFont methodsFor: 'public' stamp: 'ar 4/10/2005 03:11'!
widthOf: aCharacter ifAbsent: aBlock
"This method cannot use #formOf: because formOf: discriminates the color and causes unnecessary bitmap creation."
| f assoc |
aCharacter charCode > 255 ifTrue: [^aBlock value].
assoc _ self cache at: (aCharacter charCode + 1).
assoc ifNotNil: [
^ assoc value width
].
f _ self computeForm: aCharacter.
self at: aCharacter charCode put: f.
^ f width.
! !
!MultiTTCFont methodsFor: 'as yet unclassified' stamp: 'ar 4/10/2005 03:13'!
widthOf: aCharacter ifAbsent: aBlock
"ar 4/10/2005: This is odd - it looks like this assumes that all MultiTTCFonts define glyphs for all characters (which is rather unlikely...)"
"This method cannot use #formOf: because formOf: discriminates the color and causes unnecessary bitmap creation."
| newForm |
self hasCached: aCharacter ifTrue: [:form :index |
self access: aCharacter at: index.
^ form width.
].
newForm _ self computeForm: aCharacter.
self at: aCharacter put: newForm.
^ newForm width.
! !
!TTCFontSet methodsFor: 'as yet unclassified' stamp: 'ar 4/10/2005 03:30'!
displayString: aString on: aBitBlt from: startIndex to: stopIndex at: aPoint kern: kernDelta baselineY: baselineY
| destPoint font form encoding glyphInfo char charCode destY str |
destPoint _ aPoint.
glyphInfo _ Array new: 5.
startIndex to: stopIndex do: [:charIndex |
char _ aString at: charIndex.
encoding _ char leadingChar + 1.
charCode _ char charCode.
font _ fontArray at: encoding.
((charCode between: font minAscii and: font maxAscii) not)
ifTrue: [charCode _ nil].
charCode ifNil:[
str _ char asUndefinedGlyph.
destPoint _ self displayString: str on: aBitBlt from: 1 to: str size at: destPoint kern: kernDelta baselineY: baselineY.
] ifNotNil:[
self glyphInfoOf: char into: glyphInfo.
form _ glyphInfo first.
(glyphInfo fifth ~= aBitBlt lastFont) ifTrue: [
glyphInfo fifth installOn: aBitBlt.
].
destY _ baselineY - glyphInfo fourth.
aBitBlt sourceForm: form.
aBitBlt destX: destPoint x.
aBitBlt destY: destY.
aBitBlt sourceOrigin: 0 @ 0.
aBitBlt width: form width.
aBitBlt height: form height.
aBitBlt copyBits.
destPoint _ destPoint + (form width + kernDelta @ 0).
].
].
^ destPoint.
! !
!TTCFontSet methodsFor: 'as yet unclassified' stamp: 'ar 4/10/2005 03:14'!
widthOf: aCharacter ifAbsent: aBlock
| encoding |
encoding _ aCharacter leadingChar.
^ (fontArray at: encoding + 1) widthOf: aCharacter ifAbsent: aBlock! !
TTCFontSet removeSelector: #widthOf:!
MultiTTCFont removeSelector: #widthOf:!
TTCFont removeSelector: #widthOf:!
StrikeFontSet removeSelector: #widthOf:!
StrikeFont removeSelector: #widthOf:!
FixedFaceFont removeSelector: #widthOf:!
-------------- next part --------------
A non-text attachment was scrubbed...
Name: UndefinedCharsOLD.gif
Type: image/gif
Size: 2924 bytes
Desc: not available
Url : http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20050410/4e3a9736/UndefinedCharsOLD.gif
-------------- next part --------------
A non-text attachment was scrubbed...
Name: UndefinedCharsNEW.gif
Type: image/gif
Size: 5563 bytes
Desc: not available
Url : http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20050410/4e3a9736/UndefinedCharsNEW.gif
More information about the Squeak-dev
mailing list
|