~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/ikvm/openjdk/sun/font/StrikeCache.java

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
 
3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 
4
 *
 
5
 * This code is free software; you can redistribute it and/or modify it
 
6
 * under the terms of the GNU General Public License version 2 only, as
 
7
 * published by the Free Software Foundation.  Oracle designates this
 
8
 * particular file as subject to the "Classpath" exception as provided
 
9
 * by Oracle in the LICENSE file that accompanied this code.
 
10
 *
 
11
 * This code is distributed in the hope that it will be useful, but WITHOUT
 
12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 
13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 
14
 * version 2 for more details (a copy is included in the LICENSE file that
 
15
 * accompanied this code).
 
16
 *
 
17
 * You should have received a copy of the GNU General Public License version
 
18
 * 2 along with this work; if not, write to the Free Software Foundation,
 
19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 
20
 *
 
21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 
22
 * or visit www.oracle.com if you need additional information or have any
 
23
 * questions.
 
24
 */
 
25
 
 
26
package sun.font;
 
27
 
 
28
import java.lang.ref.Reference;
 
29
import java.lang.ref.ReferenceQueue;
 
30
import java.lang.ref.SoftReference;
 
31
import java.lang.ref.WeakReference;
 
32
import java.awt.Font;
 
33
import java.awt.FontFormatException;
 
34
import java.util.logging.Level;
 
35
import java.util.logging.Logger;
 
36
 
 
37
import sun.java2d.Disposer;
 
38
import sun.misc.Unsafe;
 
39
import ikvm.internal.NotYetImplementedError;
 
40
 
 
41
/**
 
42
 
 
43
A FontStrike is the keeper of scaled glyph image data which is expensive
 
44
to compute so needs to be cached.
 
45
So long as that data may be being used it cannot be invalidated.
 
46
Yet we also need to limit the amount of native memory and number of
 
47
strike objects in use.
 
48
For scaleability and ease of use, a key goal is multi-threaded read
 
49
access to a strike, so that it may be shared by multiple client objects,
 
50
potentially executing on different threads, with no special reference
 
51
counting or "check-out/check-in" requirements which would pass on the
 
52
burden of keeping track of strike references to the SG2D and other clients.
 
53
 
 
54
A cache of strikes is maintained via Reference objects.
 
55
This helps in two ways :
 
56
1. The VM will free references when memory is low or they have not been
 
57
used in a long time.
 
58
2. Reference queues provide a way to get notification of this so we can
 
59
free native memory resources.
 
60
 
 
61
 */
 
62
 
 
63
public final class StrikeCache {
 
64
 
 
65
    static final Unsafe unsafe = Unsafe.getUnsafe();
 
66
 
 
67
    static ReferenceQueue refQueue = Disposer.getQueue();
 
68
 
 
69
    /* Reference objects may have their referents cleared when GC chooses.
 
70
     * During application client start-up there is typically at least one
 
71
     * GC which causes the hotspot VM to clear soft (not just weak) references
 
72
     * Thus not only is there a GC pause, but the work done do rasterise
 
73
     * glyphs that are fairly certain to be needed again almost immediately
 
74
     * is thrown away. So for performance reasons a simple optimisation is to
 
75
     * keep up to 8 strong references to strikes to reduce the chance of
 
76
     * GC'ing strikes that have been used recently. Note that this may not
 
77
     * suffice in Solaris UTF-8 locales where a single composite strike may be
 
78
     * composed of 15 individual strikes, plus the composite strike.
 
79
     * And this assumes the new architecture doesn't maintain strikes for
 
80
     * natively accessed bitmaps. It may be worth "tuning" the number of
 
81
     * strikes kept around for the platform or locale.
 
82
     * Since no attempt is made to ensure uniqueness or ensure synchronized
 
83
     * access there is no guarantee that this cache will ensure that unique
 
84
     * strikes are cached. Every time a strike is looked up it is added
 
85
     * to the current index in this cache. All this cache has to do to be
 
86
     * worthwhile is prevent excessive cache flushing of strikes that are
 
87
     * referenced frequently. The logic that adds references here could be
 
88
     * tweaked to keep only strikes  that represent untransformed, screen
 
89
     * sizes as that's the typical performance case.
 
90
     */
 
91
    static int MINSTRIKES = 8; // can be overridden by property
 
92
    static int recentStrikeIndex = 0;
 
93
    static FontStrike[] recentStrikes;
 
94
    static boolean cacheRefTypeWeak;
 
95
 
 
96
    /*
 
97
     * Native sizes and offsets for glyph cache
 
98
     * There are 10 values.
 
99
     */
 
100
    static int nativeAddressSize;
 
101
    static int glyphInfoSize;
 
102
    static int xAdvanceOffset;
 
103
    static int yAdvanceOffset;
 
104
    static int boundsOffset;
 
105
    static int widthOffset;
 
106
    static int heightOffset;
 
107
    static int rowBytesOffset;
 
108
    static int topLeftXOffset;
 
109
    static int topLeftYOffset;
 
110
    static int pixelDataOffset;
 
111
    static long invisibleGlyphPtr;
 
112
 
 
113
    /* Native method used to return information used for unsafe
 
114
     * access to native data.
 
115
     * return values as follows:-
 
116
     * arr[0] = size of an address/pointer.
 
117
     * arr[1] = size of a GlyphInfo
 
118
     * arr[2] = offset of advanceX
 
119
     * arr[3] = offset of advanceY
 
120
     * arr[4] = offset of width
 
121
     * arr[5] = offset of height
 
122
     * arr[6] = offset of rowBytes
 
123
     * arr[7] = offset of topLeftX
 
124
     * arr[8] = offset of topLeftY
 
125
     * arr[9] = offset of pixel data.
 
126
     * arr[10] = address of a GlyphImageRef representing the invisible glyph
 
127
     */
 
128
    static void getGlyphCacheDescription(long[] infoArray){
 
129
        throw new NotYetImplementedError();
 
130
    }
 
131
 
 
132
    static {
 
133
 
 
134
        long[] nativeInfo = new long[11];
 
135
        getGlyphCacheDescription(nativeInfo);
 
136
        //Can also get address size from Unsafe class :-
 
137
        //nativeAddressSize = unsafe.addressSize();
 
138
        nativeAddressSize = (int)nativeInfo[0];
 
139
        glyphInfoSize     = (int)nativeInfo[1];
 
140
        xAdvanceOffset    = (int)nativeInfo[2];
 
141
        yAdvanceOffset    = (int)nativeInfo[3];
 
142
        widthOffset       = (int)nativeInfo[4];
 
143
        heightOffset      = (int)nativeInfo[5];
 
144
        rowBytesOffset    = (int)nativeInfo[6];
 
145
        topLeftXOffset    = (int)nativeInfo[7];
 
146
        topLeftYOffset    = (int)nativeInfo[8];
 
147
        pixelDataOffset   = (int)nativeInfo[9];
 
148
        invisibleGlyphPtr = nativeInfo[10];
 
149
        if (nativeAddressSize < 4) {
 
150
            throw new InternalError("Unexpected address size for font data: " +
 
151
                                    nativeAddressSize);
 
152
        }
 
153
 
 
154
        java.security.AccessController.doPrivileged(
 
155
                                    new java.security.PrivilegedAction() {
 
156
            public Object run() {
 
157
 
 
158
               /* Allow a client to override the reference type used to
 
159
                * cache strikes. The default is "soft" which hints to keep
 
160
                * the strikes around. This property allows the client to
 
161
                * override this to "weak" which hint to the GC to free
 
162
                * memory more agressively.
 
163
                */
 
164
               String refType =
 
165
                   System.getProperty("sun.java2d.font.reftype", "soft");
 
166
               cacheRefTypeWeak = refType.equals("weak");
 
167
 
 
168
                String minStrikesStr =
 
169
                    System.getProperty("sun.java2d.font.minstrikes");
 
170
                if (minStrikesStr != null) {
 
171
                    try {
 
172
                        MINSTRIKES = Integer.parseInt(minStrikesStr);
 
173
                        if (MINSTRIKES <= 0) {
 
174
                            MINSTRIKES = 1;
 
175
                        }
 
176
                    } catch (NumberFormatException e) {
 
177
                    }
 
178
                }
 
179
 
 
180
                recentStrikes = new FontStrike[MINSTRIKES];
 
181
 
 
182
                return null;
 
183
            }
 
184
        });
 
185
    }
 
186
 
 
187
 
 
188
    static void refStrike(FontStrike strike) {
 
189
        int index = recentStrikeIndex;
 
190
        recentStrikes[index] = strike;
 
191
        index++;
 
192
        if (index == MINSTRIKES) {
 
193
            index = 0;
 
194
        }
 
195
        recentStrikeIndex = index;
 
196
    }
 
197
 
 
198
    static void disposeStrike(FontStrikeDisposer disposer) {
 
199
        if (disposer.intGlyphImages != null) {
 
200
            freeIntMemory(disposer.intGlyphImages,
 
201
                          disposer.pScalerContext);
 
202
        } else if (disposer.longGlyphImages != null) {
 
203
            freeLongMemory(disposer.longGlyphImages,
 
204
                           disposer.pScalerContext);
 
205
        } else if (disposer.segIntGlyphImages != null) {
 
206
            /* NB Now making multiple JNI calls in this case.
 
207
             * But assuming that there's a reasonable amount of locality
 
208
             * rather than sparse references then it should be OK.
 
209
             */
 
210
            for (int i=0; i<disposer.segIntGlyphImages.length; i++) {
 
211
                if (disposer.segIntGlyphImages[i] != null) {
 
212
                    freeIntMemory(disposer.segIntGlyphImages[i],
 
213
                                  disposer.pScalerContext);
 
214
                    /* native will only free the scaler context once */
 
215
                    disposer.pScalerContext = 0L;
 
216
                    disposer.segIntGlyphImages[i] = null;
 
217
                }
 
218
            }
 
219
            /* This may appear inefficient but it should only be invoked
 
220
             * for a strike that never was asked to rasterise a glyph.
 
221
             */
 
222
            if (disposer.pScalerContext != 0L) {
 
223
                freeIntMemory(new int[0], disposer.pScalerContext);
 
224
            }
 
225
        } else if (disposer.segLongGlyphImages != null) {
 
226
            for (int i=0; i<disposer.segLongGlyphImages.length; i++) {
 
227
                if (disposer.segLongGlyphImages[i] != null) {
 
228
                    freeLongMemory(disposer.segLongGlyphImages[i],
 
229
                                   disposer.pScalerContext);
 
230
                    disposer.pScalerContext = 0L;
 
231
                    disposer.segLongGlyphImages[i] = null;
 
232
                }
 
233
            }
 
234
            if (disposer.pScalerContext != 0L) {
 
235
                freeLongMemory(new long[0], disposer.pScalerContext);
 
236
            }
 
237
        }
 
238
    }
 
239
 
 
240
    static void freeIntPointer(int ptr){
 
241
        throw new NotYetImplementedError();
 
242
    }
 
243
    static void freeLongPointer(long ptr){
 
244
        throw new NotYetImplementedError();
 
245
    }
 
246
    private static void freeIntMemory(int[] glyphPtrs, long pContext){
 
247
        throw new NotYetImplementedError();
 
248
    }
 
249
    private static void freeLongMemory(long[] glyphPtrs, long pContext){
 
250
        throw new NotYetImplementedError();
 
251
    }
 
252
 
 
253
 
 
254
    public static Reference getStrikeRef(FontStrike strike) {
 
255
        return getStrikeRef(strike, cacheRefTypeWeak);
 
256
    }
 
257
 
 
258
    public static Reference getStrikeRef(FontStrike strike, boolean weak) {
 
259
        /* Some strikes may have no disposer as there's nothing
 
260
         * for them to free, as they allocated no native resource
 
261
         * eg, if they did not allocate resources because of a problem,
 
262
         * or they never hold native resources. So they create no disposer.
 
263
         * But any strike that reaches here that has a null disposer is
 
264
         * a potential memory leak.
 
265
         */
 
266
        if (strike.disposer == null) {
 
267
            if (weak) {
 
268
                return new WeakReference(strike);
 
269
            } else {
 
270
                return new SoftReference(strike);
 
271
            }
 
272
        }
 
273
 
 
274
        if (weak) {
 
275
            return new WeakDisposerRef(strike);
 
276
        } else {
 
277
            return new SoftDisposerRef(strike);
 
278
        }
 
279
    }
 
280
 
 
281
    static interface DisposableStrike {
 
282
        FontStrikeDisposer getDisposer();
 
283
    }
 
284
 
 
285
    static class SoftDisposerRef
 
286
        extends SoftReference implements DisposableStrike {
 
287
 
 
288
        private FontStrikeDisposer disposer;
 
289
 
 
290
        public FontStrikeDisposer getDisposer() {
 
291
            return disposer;
 
292
        }
 
293
 
 
294
        SoftDisposerRef(FontStrike strike) {
 
295
            super(strike, StrikeCache.refQueue);
 
296
            disposer = strike.disposer;
 
297
            Disposer.addReference(this, disposer);
 
298
        }
 
299
    }
 
300
 
 
301
    static class WeakDisposerRef
 
302
        extends WeakReference implements DisposableStrike {
 
303
 
 
304
        private FontStrikeDisposer disposer;
 
305
 
 
306
        public FontStrikeDisposer getDisposer() {
 
307
            return disposer;
 
308
        }
 
309
 
 
310
        WeakDisposerRef(FontStrike strike) {
 
311
            super(strike, StrikeCache.refQueue);
 
312
            disposer = strike.disposer;
 
313
            Disposer.addReference(this, disposer);
 
314
        }
 
315
    }
 
316
 
 
317
}