5
5
#name : ' FreeTypeCache' ,
6
6
#superclass : ' Object' ,
7
7
#instVars : [
8
+ ' mutex' ,
8
9
' maximumSize' ,
9
10
' used' ,
10
11
' fontTable' ,
@@ -96,7 +97,7 @@ FreeTypeCache >> atFont: aFreeTypeFont charCode: charCodeInteger type: typeFlag
96
97
97
98
| charCodeTable typeTable scaleTable entry v vSize |
98
99
99
- aFreeTypeFont mutex criticalReleasingOnError: [
100
+ mutex criticalReleasingOnError: [
100
101
charCodeTable := fontTable at: aFreeTypeFont ifAbsentPut: [self dictionaryClass new : 60 ].
101
102
typeTable := charCodeTable at: charCodeInteger ifAbsentPut: [self dictionaryClass new : 10 ].
102
103
scaleTable := typeTable at: typeFlag ifAbsentPut: [self dictionaryClass new : 1 ].
@@ -105,10 +106,16 @@ FreeTypeCache >> atFont: aFreeTypeFont charCode: charCodeInteger type: typeFlag
105
106
ifNotNil: [
106
107
fifo moveDown: entry.
107
108
^ entry object].
108
- v := aBlock value.
109
+ v := aBlock on: Error do: [ :error |
110
+ self removeIfEmptyScaleTable: scaleTable type: typeFlag typeTable: typeTable
111
+ charCode: charCodeInteger charCodeTable: charCodeTable font: aFreeTypeFont.
112
+ error pass].
109
113
vSize := self sizeOf: v.
110
114
(maximumSize isNotNil and :[vSize > maximumSize])
111
- ifTrue: [^ v].
115
+ ifTrue: [
116
+ self removeIfEmptyScaleTable: scaleTable type: typeFlag typeTable: typeTable
117
+ charCode: charCodeInteger charCodeTable: charCodeTable font: aFreeTypeFont.
118
+ ^ v].
112
119
used := used + vSize.
113
120
entry := (self fifoEntryClass new
114
121
font: aFreeTypeFont;
@@ -128,7 +135,7 @@ FreeTypeCache >> atFont: aFreeTypeFont charCode: charCodeInteger type: typeFlag
128
135
129
136
| charCodeTable typeTable scaleTable anObjectSize oldEntry oldEntrySize entry |
130
137
131
- aFreeTypeFont mutex criticalReleasingOnError: [
138
+ mutex criticalReleasingOnError: [
132
139
anObjectSize := self sizeOf: anObject.
133
140
(maximumSize isNotNil and :[anObjectSize > maximumSize])
134
141
ifTrue: [^ anObject].
@@ -156,6 +163,14 @@ FreeTypeCache >> atFont: aFreeTypeFont charCode: charCodeInteger type: typeFlag
156
163
^ anObject ]
157
164
]
158
165
166
+ { #category : ' private - sizing' }
167
+ FreeTypeCache >> basicRemoveAll [
168
+
169
+ fontTable := self dictionaryClass new : self fontTableInitialMinimumCapacity.
170
+ fifo := self fifoClass new .
171
+ used := 0
172
+ ]
173
+
159
174
{ #category : ' public' }
160
175
FreeTypeCache >> cacheSize [
161
176
@@ -186,12 +201,19 @@ FreeTypeCache >> fifoEntryClass [
186
201
^ FreeTypeCacheEntry
187
202
]
188
203
204
+ { #category : ' private - sizing' }
205
+ FreeTypeCache >> fontTableInitialMinimumCapacity [
206
+
207
+ ^ 100
208
+ ]
209
+
189
210
{ #category : ' initialization' }
190
211
FreeTypeCache >> initialize [
191
212
192
213
super initialize.
214
+ mutex := Semaphore forMutualExclusion.
193
215
maximumSize := self class defaultMaximumSize.
194
- fontTable := self dictionaryClass new : 100 .
216
+ fontTable := self dictionaryClass new : self fontTableInitialMinimumCapacity .
195
217
used := 0 .
196
218
fifo := self fifoClass new
197
219
]
@@ -205,68 +227,97 @@ FreeTypeCache >> maximumSize [
205
227
{ #category : ' public' }
206
228
FreeTypeCache >> maximumSize: anIntegerOrNil [
207
229
208
- maximumSize := anIntegerOrNil.
209
- maximumSize ifNotNil: [
210
- used > maximumSize
211
- ifTrue: [" shrink"
212
- self shrinkTo: maximumSize]]
230
+ mutex criticalReleasingOnError: [
231
+ maximumSize := anIntegerOrNil.
232
+ maximumSize ifNotNil: [
233
+ used > maximumSize
234
+ ifTrue: [" shrink"
235
+ self shrinkTo: maximumSize]]]
213
236
]
214
237
215
238
{ #category : ' add-remove' }
216
239
FreeTypeCache >> removeAll [
217
240
218
- fontTable := self dictionaryClass new : 100 .
219
- fifo := self fifoClass new .
220
- used := 0
241
+ mutex criticalReleasingOnError: [
242
+ self basicRemoveAll ]
221
243
]
222
244
223
245
{ #category : ' add-remove' }
224
246
FreeTypeCache >> removeAllForFont: aFreeTypeFont [
225
247
226
- | toRemove |
227
- (fontTable includesKey: aFreeTypeFont) ifFalse: [ ^ self ].
228
- toRemove := IdentitySet new .
229
- fifo do: [ :entry |
230
- entry font = aFreeTypeFont ifTrue: [ toRemove add: entry ] ].
231
- toRemove do: [ :entry |
232
- | d |
233
- fifo remove: entry.
234
- d := ((fontTable at: entry font) at: entry charCode) at: entry type.
235
- d removeKey: entry scale.
236
- used := used - (self sizeOf: entry object) ]
248
+ mutex criticalReleasingOnError: [
249
+ | toRemove |
250
+ (fontTable includesKey: aFreeTypeFont) ifFalse: [ ^ self ].
251
+ toRemove := IdentitySet new .
252
+ fifo do: [ :entry |
253
+ entry font = aFreeTypeFont ifTrue: [ toRemove add: entry ] ].
254
+ toRemove do: [ :entry | self removeEntry: entry ] ]
237
255
]
238
256
239
257
{ #category : ' add-remove' }
240
258
FreeTypeCache >> removeAllForType: typeFlag [
241
259
242
- | toRemove |
243
- toRemove := IdentitySet new .
244
- fifo do: [ :entry |
245
- entry type = typeFlag ifTrue: [ toRemove add: entry ] ].
246
- toRemove do: [ :entry |
247
- | d |
248
- fifo remove: entry.
249
- d := ((fontTable at: entry font) at: entry charCode) at: entry type.
250
- d removeKey: entry scale.
251
- used := used - (self sizeOf: entry object) ]
260
+ mutex criticalReleasingOnError: [
261
+ | toRemove |
262
+ toRemove := IdentitySet new .
263
+ fifo do: [ :entry |
264
+ entry type = typeFlag ifTrue: [ toRemove add: entry ] ].
265
+ toRemove do: [ :entry | self removeEntry: entry ] ]
266
+ ]
267
+
268
+ { #category : ' private - sizing' }
269
+ FreeTypeCache >> removeEntry: entry [
270
+
271
+ fifo remove: entry.
272
+ self removeFont: entry font charCode: entry charCode type: entry type scale: entry scale.
273
+ used := used - (self sizeOf: entry object)
274
+ ]
275
+
276
+ { #category : ' private - sizing' }
277
+ FreeTypeCache >> removeFont: font charCode: charCode type: type scale: scale [
278
+
279
+ | charCodeTable typeTable scaleTable |
280
+
281
+ charCodeTable := fontTable at: font.
282
+ typeTable := charCodeTable at: charCode.
283
+ scaleTable := typeTable at: type.
284
+
285
+ scaleTable removeKey: scale.
286
+ self removeIfEmptyScaleTable: scaleTable type: type typeTable: typeTable
287
+ charCode: charCode charCodeTable: charCodeTable font: font
288
+ ]
289
+
290
+ { #category : ' private - sizing' }
291
+ FreeTypeCache >> removeIfEmptyScaleTable: scaleTable type: type typeTable: typeTable charCode: charCode charCodeTable: charCodeTable font: font [
292
+
293
+ scaleTable ifNotEmpty: [ ^ self ].
294
+ typeTable removeKey: type.
295
+ typeTable ifNotEmpty: [ ^ self ].
296
+ charCodeTable removeKey: charCode.
297
+ charCodeTable ifNotEmpty: [ ^ self ].
298
+ fontTable removeKey: font.
299
+ (fontTable capacity // 2 > self fontTableInitialMinimumCapacity
300
+ and : [ fontTable capacity // 4 > fontTable size ]) ifFalse: [ ^ self ].
301
+ fontTable compact
252
302
]
253
303
254
304
{ #category : ' reporting' }
255
305
FreeTypeCache >> reportCacheState [
256
306
" Answer a description of the current state of the cache"
257
307
258
- | usedPercent |
259
- usedPercent := maximumSize
260
- ifNil: [0 ]
261
- ifNotNil: [(used * 100 / maximumSize) asFloat rounded].
262
- ^ usedPercent asString,' % Full (maximumSize: ' , maximumSize asString, ' , used: ' , used asString,' )'
308
+ ^ mutex criticalReleasingOnError: [
309
+ | usedPercent |
310
+ usedPercent := maximumSize
311
+ ifNil: [0 ]
312
+ ifNotNil: [(used * 100 / maximumSize) asFloat rounded].
313
+ usedPercent asString,' % Full (maximumSize: ' , maximumSize asString, ' , used: ' , used asString,' )' ]
263
314
]
264
315
265
316
{ #category : ' private - sizing' }
266
317
FreeTypeCache >> shrinkTo: newSize [
267
- " if the used size is greater than newSize, then remove all the receiver's entries "
318
+ " while the used size is greater than newSize, remove the receiver's first entry "
268
319
269
- used > newSize ifTrue: [ self removeAll ]
320
+ [ used > newSize ] whileTrue: [ self removeEntry: fifo firstLink ]
270
321
]
271
322
272
323
{ #category : ' private - accessing' }
0 commit comments