author | Jan Vrany <jan.vrany@fit.cvut.cz> |
Wed, 06 Sep 2017 09:47:50 +0200 | |
branch | jv |
changeset 8179 | ced410b68993 |
parent 7608 | 0f8d92a9c1e7 |
child 7946 | 6ed11ca75246 |
permissions | -rw-r--r-- |
2547 | 1 |
" |
2 |
COPYRIGHT (c) 1999 by eXept Software AG |
|
3 |
All Rights Reserved |
|
4 |
||
5 |
This software is furnished under a license and may be used |
|
6 |
only in accordance with the terms of that license and with the |
|
7 |
inclusion of the above copyright notice. This software may not |
|
8 |
be provided or otherwise made available to, or used by, any |
|
9 |
other person. No title to or ownership of the software is |
|
10 |
hereby transferred. |
|
11 |
||
12 |
This is a demo example: |
|
13 |
||
14 |
THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTOR ``AS IS'' AND |
|
15 |
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
16 |
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
17 |
ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTOR BE LIABLE |
|
18 |
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|
19 |
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
|
20 |
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
|
21 |
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
22 |
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
|
23 |
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
|
24 |
SUCH DAMAGE. |
|
25 |
" |
|
7608 | 26 |
"{ Package: 'stx:libview' }" |
2547 | 27 |
|
7608 | 28 |
"{ NameSpace: Smalltalk }" |
3659 | 29 |
|
2546 | 30 |
FontDescription subclass:#CompoundFont |
3663 | 31 |
instanceVariableNames:'baseFont characterToFontMapping maxAscent maxDescent maxHeight |
32 |
device' |
|
33 |
classVariableNames:'' |
|
34 |
poolDictionaries:'' |
|
35 |
category:'Graphics-Support' |
|
2546 | 36 |
! |
37 |
||
38 |
!CompoundFont class methodsFor:'documentation'! |
|
39 |
||
2547 | 40 |
copyright |
41 |
" |
|
42 |
COPYRIGHT (c) 1999 by eXept Software AG |
|
43 |
All Rights Reserved |
|
44 |
||
45 |
This software is furnished under a license and may be used |
|
46 |
only in accordance with the terms of that license and with the |
|
47 |
inclusion of the above copyright notice. This software may not |
|
48 |
be provided or otherwise made available to, or used by, any |
|
49 |
other person. No title to or ownership of the software is |
|
50 |
hereby transferred. |
|
51 |
||
52 |
This is a demo example: |
|
53 |
||
54 |
THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTOR ``AS IS'' AND |
|
55 |
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
56 |
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
57 |
ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTOR BE LIABLE |
|
58 |
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|
59 |
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
|
60 |
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
|
61 |
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
62 |
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
|
63 |
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
|
64 |
SUCH DAMAGE. |
|
65 |
" |
|
66 |
||
67 |
! |
|
68 |
||
2546 | 69 |
documentation |
70 |
" |
|
71 |
a CompountFont is a font which consists of character glyphs from multiple |
|
72 |
other (base-)fonts; for each character code, an individual font may be given. |
|
73 |
||
74 |
This has been mostly added to allow for non-EURO fonts to be used with ST/X, |
|
75 |
by defining a mixedFont, which has an EURO-glyph at the desired character |
|
76 |
position. |
|
77 |
Do not hardCode usage of MixedFonts into your application, since they |
|
78 |
might disappear in the future (when Unicode support has been fully |
|
79 |
implemented in ST/X, and Unicode fonts are generally available under X). |
|
80 |
I.e. to use these fonts, add appropriate setup to the styleSheet, |
|
81 |
or private.rc and use those fonts transparently. |
|
82 |
||
83 |
[Instance variables:] |
|
84 |
||
85 |
baseFont <Font> fallback (default-) font |
|
86 |
characterToFontMapping <Dictionary> maps characters to a fonts |
|
87 |
||
88 |
[class variables:] |
|
89 |
||
90 |
[see also:] |
|
91 |
Font BitmapFont |
|
92 |
DeviceDrawable GraphicsContext |
|
93 |
||
94 |
[author:] |
|
95 |
Claus Gittinger |
|
96 |
" |
|
97 |
||
98 |
||
99 |
! |
|
100 |
||
101 |
examples |
|
102 |
" |
|
103 |
a mixed font; all vowels are displayed in times; |
|
104 |
the rest in helvetica. |
|
105 |
[exBegin] |
|
106 |
|font top list| |
|
107 |
||
3659 | 108 |
font := CompoundFont basedOn:(Font family:'courier' size:18). |
2546 | 109 |
#($a $e $i $o $u) do:[:char | |
3659 | 110 |
font glyphAt:char putFont:(Font family:'times' size:18). |
2546 | 111 |
]. |
112 |
top := ScrollableView forView:(list := EditTextView new). |
|
113 |
list font:font. |
|
114 |
list list:#('a' 'z' 'aaa' 'zzz' 'azaz' 'zaza' 'aa' 'az' 'za' 'hello' 'abcdef' 'xyz'). |
|
115 |
top extent:200@200. |
|
116 |
top open. |
|
117 |
[exEnd] |
|
118 |
||
3671 | 119 |
[exBegin] |
120 |
|font font2 top list| |
|
121 |
||
122 |
font := CompoundFont basedOn:(Font family:'courier' size:18). |
|
123 |
font2 := Font family:'times' size:24. |
|
124 |
||
125 |
#($a $e $i $o $u $j) do:[:char | |
|
126 |
font glyphAt:char putFont:font2. |
|
127 |
font glyphAt:char asUppercase putFont:font2. |
|
128 |
]. |
|
129 |
top := ScrollableView forView:(list := EditTextView new). |
|
130 |
list font:font. |
|
131 |
list list:#('hello' 'abcdefghijklmnopqrstuvwxyz' 'xyz' |
|
132 |
'HELLO' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'XYZ'). |
|
133 |
top extent:200@200. |
|
134 |
top open. |
|
135 |
[exEnd] |
|
2546 | 136 |
|
137 |
a mixed font; the dollar character is replaced by the european |
|
138 |
EURO symbol; the rest is helvetica |
|
139 |
(this is a hack - we really need a resizable font for this): |
|
140 |
||
141 |
[exBegin] |
|
142 |
|font baseFont euroGlyph glyphs euroFont top list| |
|
143 |
||
144 |
baseFont := Font family:'helvetica' size:12. |
|
145 |
baseFont := baseFont onDevice:Display. |
|
146 |
glyphs := Array new:256. |
|
147 |
euroGlyph := Form |
|
3659 | 148 |
width:12 |
2546 | 149 |
height:16 |
150 |
fromArray:#( |
|
151 |
2r00000000 2r00000000 |
|
152 |
2r00000000 2r00000000 |
|
153 |
2r00000000 2r00000000 |
|
154 |
2r00000111 2r11000000 |
|
155 |
2r00001000 2r00100000 |
|
156 |
2r00010000 2r00000000 |
|
157 |
2r01111111 2r10000000 |
|
158 |
2r00010000 2r00000000 |
|
159 |
2r01111111 2r10000000 |
|
160 |
2r00010000 2r00000000 |
|
161 |
2r00001000 2r00100000 |
|
162 |
2r00000111 2r11000000 |
|
163 |
2r00000000 2r00000000 |
|
164 |
2r00000000 2r00000000 |
|
3659 | 165 |
2r00000000 2r00000000 |
166 |
2r00000000 2r00000000 |
|
2546 | 167 |
). |
168 |
glyphs at:($$ asciiValue+1) put:euroGlyph. |
|
169 |
||
170 |
euroFont := BitmapFont new glyphs:glyphs. |
|
171 |
euroFont setAscent:(baseFont ascent). |
|
172 |
euroFont setDescent:(baseFont descent). |
|
173 |
||
174 |
font := CompoundFont basedOn:baseFont. |
|
175 |
font glyphAt:$$ putFont:euroFont. |
|
176 |
||
177 |
top := ScrollableView forView:(list := EditTextView new). |
|
178 |
list font:font. |
|
179 |
list list:#('100 $' '193 DM'). |
|
180 |
top extent:200@200. |
|
181 |
top open. |
|
182 |
[exEnd] |
|
183 |
" |
|
184 |
! ! |
|
185 |
||
186 |
!CompoundFont class methodsFor:'instance creation'! |
|
187 |
||
188 |
basedOn:aRealFont |
|
189 |
^ self new baseFont:aRealFont |
|
190 |
! ! |
|
191 |
||
192 |
!CompoundFont methodsFor:'accessing'! |
|
193 |
||
194 |
baseFont |
|
195 |
"return the value of the instance variable 'baseFont' (automatically generated)" |
|
196 |
||
3659 | 197 |
^ baseFont |
198 |
! |
|
2546 | 199 |
|
200 |
baseFont:something |
|
201 |
"set the value of the instance variable 'baseFont' (automatically generated)" |
|
202 |
||
203 |
baseFont := something. |
|
204 |
maxAscent := maxDescent := nil. |
|
205 |
! |
|
206 |
||
207 |
glyphAt:char putFont:aFont |
|
208 |
characterToFontMapping isNil ifTrue:[ |
|
209 |
characterToFontMapping := Dictionary new. |
|
210 |
]. |
|
211 |
||
212 |
characterToFontMapping at:char put:aFont. |
|
3673 | 213 |
maxAscent := maxDescent := maxHeight := nil. |
3660 | 214 |
! |
215 |
||
216 |
graphicsDevice |
|
217 |
"return the device I am on" |
|
218 |
||
219 |
^ device |
|
2546 | 220 |
! ! |
221 |
||
222 |
!CompoundFont methodsFor:'displaying'! |
|
223 |
||
3663 | 224 |
displayString:aString from:index1 to:index2 x:x0 y:y0 in:aGC opaque:opaque |
2546 | 225 |
"this is only called for fonts which have a nil fontId, |
226 |
and therefore use the replacementFont. Should never be called |
|
227 |
for non-replacement fonts." |
|
228 |
||
229 |
|x y| |
|
230 |
||
231 |
x := x0. |
|
232 |
y := y0. |
|
233 |
||
234 |
self |
|
235 |
substringPartsOf:aString from:index1 to:index2 |
|
236 |
do:[:s :i1 :i2 :font | |
|
3671 | 237 |
|wString| |
238 |
||
239 |
wString := font widthOf:aString from:i1 to:i2. |
|
240 |
opaque ifTrue:[ |
|
3673 | 241 |
"/ (font ascent < maxAscent |
242 |
"/ or:[font descent < maxDescent]) |
|
243 |
"/ ifTrue:[ |
|
3671 | 244 |
aGC |
245 |
fillRectangleX:x |
|
3673 | 246 |
y:y-maxAscent |
3671 | 247 |
width:wString |
248 |
height:maxAscent+maxDescent |
|
249 |
color:aGC backgroundPaint. |
|
3673 | 250 |
"/ ]. |
3671 | 251 |
]. |
3663 | 252 |
font displayString:s from:i1 to:i2 x:x y:y in:aGC opaque:opaque. |
3671 | 253 |
x := x + wString. |
2546 | 254 |
]. |
255 |
! ! |
|
256 |
||
4525
30fa1d24ca43
fix #userFriendlyName and #printOn:
Stefan Vogel <sv@exept.de>
parents:
3673
diff
changeset
|
257 |
!CompoundFont methodsFor:'printing'! |
30fa1d24ca43
fix #userFriendlyName and #printOn:
Stefan Vogel <sv@exept.de>
parents:
3673
diff
changeset
|
258 |
|
30fa1d24ca43
fix #userFriendlyName and #printOn:
Stefan Vogel <sv@exept.de>
parents:
3673
diff
changeset
|
259 |
userFriendlyName |
30fa1d24ca43
fix #userFriendlyName and #printOn:
Stefan Vogel <sv@exept.de>
parents:
3673
diff
changeset
|
260 |
^ 'CompoundFont(baseFont: ', baseFont userFriendlyName, ')' |
30fa1d24ca43
fix #userFriendlyName and #printOn:
Stefan Vogel <sv@exept.de>
parents:
3673
diff
changeset
|
261 |
! ! |
30fa1d24ca43
fix #userFriendlyName and #printOn:
Stefan Vogel <sv@exept.de>
parents:
3673
diff
changeset
|
262 |
|
2546 | 263 |
!CompoundFont methodsFor:'private'! |
264 |
||
265 |
computeMaxBounds |
|
3671 | 266 |
maxAscent := baseFont maxAscent. |
267 |
maxDescent := baseFont maxDescent. |
|
268 |
maxHeight := baseFont maxHeight. |
|
2546 | 269 |
characterToFontMapping notNil ifTrue:[ |
270 |
characterToFontMapping keysAndValuesDo:[:char :aFont | |
|
3671 | 271 |
maxAscent := maxAscent max:aFont maxAscent. |
272 |
maxDescent := maxDescent max:aFont maxDescent. |
|
273 |
maxHeight := maxHeight max:aFont maxHeight. |
|
2546 | 274 |
] |
275 |
]. |
|
276 |
! |
|
277 |
||
278 |
substringPartsOf:aString from:index1 to:index2 do:aBlock |
|
279 |
"helper - evaluate aBlock for parts of a string, which use the same font. |
|
280 |
aBlock is invoked for consecutive substrings, passing the string, |
|
281 |
the startIndex, endIndex and the font as arguments." |
|
282 |
||
283 |
|i1 i2 fn char currentFont| |
|
284 |
||
285 |
index2 < index1 ifTrue:[^ self]. |
|
286 |
||
287 |
i1 := index1. |
|
288 |
currentFont := characterToFontMapping at:(aString at:i1) ifAbsent:baseFont. |
|
289 |
i2 := i1 + 1. |
|
290 |
||
291 |
[i2 <= index2] whileTrue:[ |
|
292 |
char := aString at:i2. |
|
293 |
fn := characterToFontMapping at:char ifAbsent:baseFont. |
|
294 |
fn ~~ currentFont ifTrue:[ |
|
295 |
aBlock value:aString value:i1 value:(i2-1) value:currentFont. |
|
296 |
currentFont := fn. |
|
297 |
i1 := i2. |
|
298 |
]. |
|
299 |
i2 := i2 + 1. |
|
300 |
]. |
|
301 |
||
302 |
i1 < i2 ifTrue:[ |
|
303 |
aBlock value:aString value:i1 value:(i2-1) value:currentFont. |
|
304 |
]. |
|
305 |
||
306 |
" |
|
307 |
|f| |
|
308 |
||
309 |
f := self new. |
|
310 |
f baseFont:#baseFont. |
|
311 |
f fontAt:$$ put:#font2. |
|
312 |
f substringPartsOf:'ae$a' from:1 to:8 |
|
313 |
do:[:s :i1 :i2 :f | |
|
314 |
Transcript |
|
315 |
show:i1; space; |
|
316 |
show:i2; space; |
|
317 |
showCR:f |
|
318 |
] |
|
319 |
" |
|
320 |
! ! |
|
321 |
||
322 |
!CompoundFont methodsFor:'queries'! |
|
323 |
||
324 |
ascent |
|
3671 | 325 |
^ self maxAscent |
2546 | 326 |
! |
327 |
||
328 |
descent |
|
3671 | 329 |
^ self maxDescent |
2546 | 330 |
! |
331 |
||
3660 | 332 |
height |
333 |
maxHeight isNil ifTrue:[ |
|
334 |
self computeMaxBounds |
|
335 |
]. |
|
336 |
^ maxHeight. |
|
337 |
! |
|
338 |
||
2546 | 339 |
isFixedWidth |
7608 | 340 |
"return true, if this is a fixed pitch font |
341 |
(i.e. all characters are of the same width)" |
|
2546 | 342 |
|
3664 | 343 |
|w| |
344 |
||
2546 | 345 |
baseFont isFixedWidth ifFalse:[^ false]. |
3664 | 346 |
w := baseFont width. |
347 |
||
2546 | 348 |
characterToFontMapping keysAndValuesDo:[:char :font | |
3664 | 349 |
font isFixedWidth ifFalse:[^ false]. |
350 |
font width ~~ w ifTrue:[^ false]. |
|
2546 | 351 |
]. |
352 |
^ true |
|
353 |
! |
|
354 |
||
355 |
maxAscent |
|
3671 | 356 |
maxAscent isNil ifTrue:[ |
357 |
self computeMaxBounds |
|
358 |
]. |
|
359 |
^ maxAscent |
|
2546 | 360 |
! |
361 |
||
362 |
maxDescent |
|
3671 | 363 |
maxDescent isNil ifTrue:[ |
364 |
self computeMaxBounds |
|
365 |
]. |
|
366 |
^ maxDescent |
|
2546 | 367 |
! |
368 |
||
3659 | 369 |
onDevice:aDevice |
2546 | 370 |
"return a device representation of the receiver. |
371 |
Since I am device independent, return the receiver." |
|
372 |
||
3660 | 373 |
|newFonts lastFont lastDeviceFont newFont| |
374 |
||
375 |
aDevice == device ifTrue:[ ^ self ]. |
|
2546 | 376 |
|
377 |
baseFont := baseFont onDevice:aDevice. |
|
378 |
newFonts := Dictionary new. |
|
379 |
characterToFontMapping keysAndValuesDo:[:char :font | |
|
3660 | 380 |
font == lastFont ifTrue:[ |
381 |
newFont := lastDeviceFont |
|
382 |
] ifFalse:[ |
|
383 |
newFont := font onDevice:aDevice. |
|
384 |
lastFont := font. |
|
385 |
lastDeviceFont := newFont. |
|
386 |
]. |
|
387 |
newFonts at:char put:newFont |
|
2546 | 388 |
]. |
3660 | 389 |
characterToFontMapping := newFonts. |
390 |
device := aDevice. |
|
2546 | 391 |
! |
392 |
||
393 |
widthOf:aString from:index1 to:index2 |
|
394 |
|w| |
|
395 |
||
396 |
w := 0. |
|
397 |
self |
|
398 |
substringPartsOf:aString from:index1 to:index2 |
|
399 |
do:[:s :i1 :i2 :f | |
|
400 |
w := w + (f widthOf:s from:i1 to:i2) |
|
401 |
]. |
|
402 |
^ w |
|
403 |
||
404 |
! ! |
|
405 |
||
406 |
!CompoundFont class methodsFor:'documentation'! |
|
407 |
||
408 |
version |
|
7608 | 409 |
^ '$Header$' |
2546 | 410 |
! ! |
7608 | 411 |