src/share/classes/sun/font/Font2D.java

Print this page


   1 /*
   2  * Copyright (c) 2003, 2010, 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


  74     protected int style = Font.PLAIN;
  75     protected FontFamily family;
  76     protected int fontRank = DEFAULT_RANK;
  77 
  78     /*
  79      * A mapper can be independent of the strike.
  80      * Perhaps the reference to the mapper ought to be held on the
  81      * scaler, as it may be implemented via scaler functionality anyway
  82      * and so the mapper would be useless if its native portion was
  83      * freed when the scaler was GC'd.
  84      */
  85     protected CharToGlyphMapper mapper;
  86 
  87     /*
  88      * The strike cache is maintained per "Font2D" as that is the
  89      * principal object by which you look up fonts.
  90      * It means more Hashmaps, but look ups can be quicker because
  91      * the map will have fewer entries, and there's no need to try to
  92      * make the Font2D part of the key.
  93      */
  94     protected ConcurrentHashMap<FontStrikeDesc, Reference>
  95         strikeCache = new ConcurrentHashMap<FontStrikeDesc, Reference>();
  96 
  97     /* Store the last Strike in a Reference object.
  98      * Similarly to the strike that was stored on a C++ font object,
  99      * this is an optimisation which helps if multiple clients (ie
 100      * typically SunGraphics2D instances) are using the same font, then
 101      * as may be typical of many UIs, they are probably using it in the
 102      * same style, so it can be a win to first quickly check if the last
 103      * strike obtained from this Font2D satifies the needs of the next
 104      * client too.
 105      * This pre-supposes that a FontStrike is a shareable object, which
 106      * it should.
 107      */
 108     protected Reference lastFontStrike = new SoftReference(null);
 109 
 110     /*
 111      * POSSIBLE OPTIMISATION:
 112      * Array of length 1024 elements of 64 bits indicating if a font
 113      * contains these. This kind of information can be shared between
 114      * all point sizes.
 115      * if corresponding bit in knownBitmaskMap is set then canDisplayBitmaskMap
 116      * is valid. This is 16Kbytes of data per composite font style.
 117      * What about UTF-32 and surrogates?
 118      * REMIND: This is too much storage. Probably can only cache this
 119      * information for latin range, although possibly OK to store all
 120      * for just the "logical" fonts.
 121      * Or instead store arrays of subranges of 1024 bits (128 bytes) in
 122      * the range below surrogate pairs.
 123      */
 124 //     protected long[] knownBitmaskMap;
 125 //     protected long[] canDisplayBitmaskMap;
 126 
 127     /* Returns the "real" style of this Font2D. Eg the font face
 128      * Lucida Sans Bold" has a real style of Font.BOLD, even though


 178     protected int getValidatedGlyphCode(int glyphCode) {
 179         if (glyphCode < 0 || glyphCode >= getMapper().getNumGlyphs()) {
 180             glyphCode = getMapper().getMissingGlyphCode();
 181         }
 182         return glyphCode;
 183     }
 184 
 185     /*
 186      * Creates an appropriate strike for the Font2D subclass
 187      */
 188     abstract FontStrike createStrike(FontStrikeDesc desc);
 189 
 190     /* this may be useful for APIs like canDisplay where the answer
 191      * is dependent on the font and its scaler, but not the strike.
 192      * If no strike has ever been returned, then create a one that matches
 193      * this font with the default FRC. It will become the lastStrike and
 194      * there's a good chance that the next call will be to get exactly that
 195      * strike.
 196      */
 197     public FontStrike getStrike(Font font) {
 198         FontStrike strike = (FontStrike)lastFontStrike.get();
 199         if (strike != null) {
 200             return strike;
 201         } else {
 202             return getStrike(font, DEFAULT_FRC);
 203         }
 204     }
 205 
 206     /* SunGraphics2D has font, tx, aa and fm. From this info
 207      * can get a Strike object from the cache, creating it if necessary.
 208      * This code is designed for multi-threaded access.
 209      * For that reason it creates a local FontStrikeDesc rather than filling
 210      * in a shared one. Up to two AffineTransforms and one FontStrikeDesc will
 211      * be created by every lookup. This appears to perform more than
 212      * adequately. But it may make sense to expose FontStrikeDesc
 213      * as a parameter so a caller can use its own.
 214      * In such a case if a FontStrikeDesc is stored as a key then
 215      * we would need to use a private copy.
 216      *
 217      * Note that this code doesn't prevent two threads from creating
 218      * two different FontStrike instances and having one of the threads


 290     }
 291 
 292     FontStrike getStrike(FontStrikeDesc desc) {
 293         return getStrike(desc, true);
 294     }
 295 
 296     private FontStrike getStrike(FontStrikeDesc desc, boolean copy) {
 297         /* Before looking in the map, see if the descriptor matches the
 298          * last strike returned from this Font2D. This should often be a win
 299          * since its common for the same font, in the same size to be
 300          * used frequently, for example in many parts of a UI.
 301          *
 302          * If its not the same then we use the descriptor to locate a
 303          * Reference to the strike. If it exists and points to a strike,
 304          * then we update the last strike to refer to that and return it.
 305          *
 306          * If the key isn't in the map, or its reference object has been
 307          * collected, then we create a new strike, put it in the map and
 308          * set it to be the last strike.
 309          */
 310         FontStrike strike = (FontStrike)lastFontStrike.get();
 311         if (strike != null && desc.equals(strike.desc)) {
 312             //strike.lastlookupTime = System.currentTimeMillis();
 313             return strike;
 314         } else {
 315             Reference strikeRef = strikeCache.get(desc);
 316             if (strikeRef != null) {
 317                 strike = (FontStrike)strikeRef.get();
 318                 if (strike != null) {
 319                     //strike.lastlookupTime = System.currentTimeMillis();
 320                     lastFontStrike = new SoftReference(strike);
 321                     StrikeCache.refStrike(strike);
 322                     return strike;
 323                 }
 324             }
 325             /* When we create a new FontStrike instance, we *must*
 326              * ask the StrikeCache for a reference. We must then ensure
 327              * this reference remains reachable, by storing it in the
 328              * Font2D's strikeCache map.
 329              * So long as the Reference is there (reachable) then if the
 330              * reference is cleared, it will be enqueued for disposal.
 331              * If for some reason we explicitly remove this reference, it
 332              * must only be done when holding a strong reference to the
 333              * referent (the FontStrike), or if the reference is cleared,
 334              * then we must explicitly "dispose" of the native resources.
 335              * The only place this currently happens is in this same method,
 336              * where we find a cleared reference and need to overwrite it
 337              * here with a new reference.
 338              * Clearing the whilst holding a strong reference, should only
 339              * be done if the
 340              */


 343             }
 344             strike = createStrike(desc);
 345             //StrikeCache.addStrike();
 346             /* If we are creating many strikes on this font which
 347              * involve non-quadrant rotations, or more general
 348              * transforms which include shears, then force the use
 349              * of weak references rather than soft references.
 350              * This means that it won't live much beyond the next GC,
 351              * which is what we want for what is likely a transient strike.
 352              */
 353             int txType = desc.glyphTx.getType();
 354             if (txType == AffineTransform.TYPE_GENERAL_TRANSFORM ||
 355                 (txType & AffineTransform.TYPE_GENERAL_ROTATION) != 0 &&
 356                 strikeCache.size() > 10) {
 357                 strikeRef = StrikeCache.getStrikeRef(strike, true);
 358             } else {
 359                 strikeRef = StrikeCache.getStrikeRef(strike);
 360             }
 361             strikeCache.put(desc, strikeRef);
 362             //strike.lastlookupTime = System.currentTimeMillis();
 363             lastFontStrike = new SoftReference(strike);
 364             StrikeCache.refStrike(strike);
 365             return strike;
 366         }
 367     }
 368 
 369     void removeFromCache(FontStrikeDesc desc) {
 370         Reference ref = strikeCache.get(desc);
 371         if (ref != null) {
 372             Object o = ref.get();
 373             if (o == null) {
 374                 strikeCache.remove(desc);
 375             }
 376         }
 377     }
 378 
 379     /**
 380      * The length of the metrics array must be >= 8.  This method will
 381      * store the following elements in that array before returning:
 382      *    metrics[0]: ascent
 383      *    metrics[1]: descent
 384      *    metrics[2]: leading
 385      *    metrics[3]: max advance
 386      *    metrics[4]: strikethrough offset
 387      *    metrics[5]: strikethrough thickness
 388      *    metrics[6]: underline offset
 389      *    metrics[7]: underline thickness
 390      */


   1 /*
   2  * Copyright (c) 2003, 2014, 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


  74     protected int style = Font.PLAIN;
  75     protected FontFamily family;
  76     protected int fontRank = DEFAULT_RANK;
  77 
  78     /*
  79      * A mapper can be independent of the strike.
  80      * Perhaps the reference to the mapper ought to be held on the
  81      * scaler, as it may be implemented via scaler functionality anyway
  82      * and so the mapper would be useless if its native portion was
  83      * freed when the scaler was GC'd.
  84      */
  85     protected CharToGlyphMapper mapper;
  86 
  87     /*
  88      * The strike cache is maintained per "Font2D" as that is the
  89      * principal object by which you look up fonts.
  90      * It means more Hashmaps, but look ups can be quicker because
  91      * the map will have fewer entries, and there's no need to try to
  92      * make the Font2D part of the key.
  93      */
  94     protected ConcurrentHashMap<FontStrikeDesc, Reference<FontStrike>>
  95         strikeCache = new ConcurrentHashMap<>();
  96 
  97     /* Store the last Strike in a Reference object.
  98      * Similarly to the strike that was stored on a C++ font object,
  99      * this is an optimisation which helps if multiple clients (ie
 100      * typically SunGraphics2D instances) are using the same font, then
 101      * as may be typical of many UIs, they are probably using it in the
 102      * same style, so it can be a win to first quickly check if the last
 103      * strike obtained from this Font2D satifies the needs of the next
 104      * client too.
 105      * This pre-supposes that a FontStrike is a shareable object, which
 106      * it should.
 107      */
 108     protected Reference<FontStrike> lastFontStrike = new SoftReference<>(null);
 109 
 110     /*
 111      * POSSIBLE OPTIMISATION:
 112      * Array of length 1024 elements of 64 bits indicating if a font
 113      * contains these. This kind of information can be shared between
 114      * all point sizes.
 115      * if corresponding bit in knownBitmaskMap is set then canDisplayBitmaskMap
 116      * is valid. This is 16Kbytes of data per composite font style.
 117      * What about UTF-32 and surrogates?
 118      * REMIND: This is too much storage. Probably can only cache this
 119      * information for latin range, although possibly OK to store all
 120      * for just the "logical" fonts.
 121      * Or instead store arrays of subranges of 1024 bits (128 bytes) in
 122      * the range below surrogate pairs.
 123      */
 124 //     protected long[] knownBitmaskMap;
 125 //     protected long[] canDisplayBitmaskMap;
 126 
 127     /* Returns the "real" style of this Font2D. Eg the font face
 128      * Lucida Sans Bold" has a real style of Font.BOLD, even though


 178     protected int getValidatedGlyphCode(int glyphCode) {
 179         if (glyphCode < 0 || glyphCode >= getMapper().getNumGlyphs()) {
 180             glyphCode = getMapper().getMissingGlyphCode();
 181         }
 182         return glyphCode;
 183     }
 184 
 185     /*
 186      * Creates an appropriate strike for the Font2D subclass
 187      */
 188     abstract FontStrike createStrike(FontStrikeDesc desc);
 189 
 190     /* this may be useful for APIs like canDisplay where the answer
 191      * is dependent on the font and its scaler, but not the strike.
 192      * If no strike has ever been returned, then create a one that matches
 193      * this font with the default FRC. It will become the lastStrike and
 194      * there's a good chance that the next call will be to get exactly that
 195      * strike.
 196      */
 197     public FontStrike getStrike(Font font) {
 198         FontStrike strike = lastFontStrike.get();
 199         if (strike != null) {
 200             return strike;
 201         } else {
 202             return getStrike(font, DEFAULT_FRC);
 203         }
 204     }
 205 
 206     /* SunGraphics2D has font, tx, aa and fm. From this info
 207      * can get a Strike object from the cache, creating it if necessary.
 208      * This code is designed for multi-threaded access.
 209      * For that reason it creates a local FontStrikeDesc rather than filling
 210      * in a shared one. Up to two AffineTransforms and one FontStrikeDesc will
 211      * be created by every lookup. This appears to perform more than
 212      * adequately. But it may make sense to expose FontStrikeDesc
 213      * as a parameter so a caller can use its own.
 214      * In such a case if a FontStrikeDesc is stored as a key then
 215      * we would need to use a private copy.
 216      *
 217      * Note that this code doesn't prevent two threads from creating
 218      * two different FontStrike instances and having one of the threads


 290     }
 291 
 292     FontStrike getStrike(FontStrikeDesc desc) {
 293         return getStrike(desc, true);
 294     }
 295 
 296     private FontStrike getStrike(FontStrikeDesc desc, boolean copy) {
 297         /* Before looking in the map, see if the descriptor matches the
 298          * last strike returned from this Font2D. This should often be a win
 299          * since its common for the same font, in the same size to be
 300          * used frequently, for example in many parts of a UI.
 301          *
 302          * If its not the same then we use the descriptor to locate a
 303          * Reference to the strike. If it exists and points to a strike,
 304          * then we update the last strike to refer to that and return it.
 305          *
 306          * If the key isn't in the map, or its reference object has been
 307          * collected, then we create a new strike, put it in the map and
 308          * set it to be the last strike.
 309          */
 310         FontStrike strike = lastFontStrike.get();
 311         if (strike != null && desc.equals(strike.desc)) {
 312             //strike.lastlookupTime = System.currentTimeMillis();
 313             return strike;
 314         } else {
 315             Reference<FontStrike> strikeRef = strikeCache.get(desc);
 316             if (strikeRef != null) {
 317                 strike = strikeRef.get();
 318                 if (strike != null) {
 319                     //strike.lastlookupTime = System.currentTimeMillis();
 320                     lastFontStrike = new SoftReference<>(strike);
 321                     StrikeCache.refStrike(strike);
 322                     return strike;
 323                 }
 324             }
 325             /* When we create a new FontStrike instance, we *must*
 326              * ask the StrikeCache for a reference. We must then ensure
 327              * this reference remains reachable, by storing it in the
 328              * Font2D's strikeCache map.
 329              * So long as the Reference is there (reachable) then if the
 330              * reference is cleared, it will be enqueued for disposal.
 331              * If for some reason we explicitly remove this reference, it
 332              * must only be done when holding a strong reference to the
 333              * referent (the FontStrike), or if the reference is cleared,
 334              * then we must explicitly "dispose" of the native resources.
 335              * The only place this currently happens is in this same method,
 336              * where we find a cleared reference and need to overwrite it
 337              * here with a new reference.
 338              * Clearing the whilst holding a strong reference, should only
 339              * be done if the
 340              */


 343             }
 344             strike = createStrike(desc);
 345             //StrikeCache.addStrike();
 346             /* If we are creating many strikes on this font which
 347              * involve non-quadrant rotations, or more general
 348              * transforms which include shears, then force the use
 349              * of weak references rather than soft references.
 350              * This means that it won't live much beyond the next GC,
 351              * which is what we want for what is likely a transient strike.
 352              */
 353             int txType = desc.glyphTx.getType();
 354             if (txType == AffineTransform.TYPE_GENERAL_TRANSFORM ||
 355                 (txType & AffineTransform.TYPE_GENERAL_ROTATION) != 0 &&
 356                 strikeCache.size() > 10) {
 357                 strikeRef = StrikeCache.getStrikeRef(strike, true);
 358             } else {
 359                 strikeRef = StrikeCache.getStrikeRef(strike);
 360             }
 361             strikeCache.put(desc, strikeRef);
 362             //strike.lastlookupTime = System.currentTimeMillis();
 363             lastFontStrike = new SoftReference<>(strike);
 364             StrikeCache.refStrike(strike);
 365             return strike;
 366         }
 367     }
 368 
 369     void removeFromCache(FontStrikeDesc desc) {
 370         Reference<FontStrike> ref = strikeCache.get(desc);
 371         if (ref != null) {
 372             Object o = ref.get();
 373             if (o == null) {
 374                 strikeCache.remove(desc);
 375             }
 376         }
 377     }
 378 
 379     /**
 380      * The length of the metrics array must be >= 8.  This method will
 381      * store the following elements in that array before returning:
 382      *    metrics[0]: ascent
 383      *    metrics[1]: descent
 384      *    metrics[2]: leading
 385      *    metrics[3]: max advance
 386      *    metrics[4]: strikethrough offset
 387      *    metrics[5]: strikethrough thickness
 388      *    metrics[6]: underline offset
 389      *    metrics[7]: underline thickness
 390      */