/*
 * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.font;

import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.concurrent.ConcurrentHashMap;
import static sun.awt.SunHints.*;


public class FileFontStrike extends PhysicalStrike {

    /* fffe and ffff are values we specially interpret as meaning
     * invisible glyphs.
     */
    static final int INVISIBLE_GLYPHS = 0x0fffe;

    private FileFont fileFont;

    /* REMIND: replace this scheme with one that installs a cache
     * instance of the appropriate type. It will require changes in
     * FontStrikeDisposer and NativeStrike etc.
     */
    private static final int UNINITIALISED = 0;
    private static final int INTARRAY      = 1;
    private static final int LONGARRAY     = 2;
    private static final int SEGINTARRAY   = 3;
    private static final int SEGLONGARRAY  = 4;

    private volatile int glyphCacheFormat = UNINITIALISED;

    /* segmented arrays are blocks of 32 */
    private static final int SEGSHIFT = 5;
    private static final int SEGSIZE  = 1 << SEGSHIFT;

    private boolean segmentedCache;
    private int[][] segIntGlyphImages;
    private long[][] segLongGlyphImages;

    /* The "metrics" information requested by clients is usually nothing
     * more than the horizontal advance of the character.
     * In most cases this advance and other metrics information is stored
     * in the glyph image cache.
     * But in some cases we do not automatically retrieve the glyph
     * image when the advance is requested. In those cases we want to
     * cache the advances since this has been shown to be important for
     * performance.
     * The segmented cache is used in cases when the single array
     * would be too large.
     */
    private float[] horizontalAdvances;
    private float[][] segHorizontalAdvances;

    /* Outline bounds are used when printing and when drawing outlines
     * to the screen. On balance the relative rarity of these cases
     * and the fact that getting this requires generating a path at
     * the scaler level means that its probably OK to store these
     * in a Java-level hashmap as the trade-off between time and space.
     * Later can revisit whether to cache these at all, or elsewhere.
     * Should also profile whether subsequent to getting the bounds, the
     * outline itself is also requested. The 1.4 implementation doesn't
     * cache outlines so you could generate the path twice - once to get
     * the bounds and again to return the outline to the client.
     * If the two uses are coincident then also look into caching outlines.
     * One simple optimisation is that we could store the last single
     * outline retrieved. This assumes that bounds then outline will always
     * be retrieved for a glyph rather than retrieving bounds for all glyphs
     * then outlines for all glyphs.
     */
    ConcurrentHashMap<Integer, Rectangle2D.Float> boundsMap;
    SoftReference<ConcurrentHashMap<Integer, Point2D.Float>>
        glyphMetricsMapRef;

    AffineTransform invertDevTx;

    boolean useNatives;
    NativeStrike[] nativeStrikes;

    /* Used only for communication to native layer */
    private int intPtSize;

    /* Perform global initialisation needed for Windows native rasterizer */
    private static native boolean initNative();
    private static boolean isXPorLater = false;
    static {
        if (FontUtilities.isWindows && !FontUtilities.useT2K &&
            !GraphicsEnvironment.isHeadless()) {
            isXPorLater = initNative();
        }
    }

    FileFontStrike(FileFont fileFont, FontStrikeDesc desc) {
        super(fileFont, desc);
        this.fileFont = fileFont;

        if (desc.style != fileFont.style) {
          /* If using algorithmic styling, the base values are
           * boldness = 1.0, italic = 0.0. The superclass constructor
           * initialises these.
           */
            if ((desc.style & Font.ITALIC) == Font.ITALIC &&
                (fileFont.style & Font.ITALIC) == 0) {
                algoStyle = true;
                italic = 0.7f;
            }
            if ((desc.style & Font.BOLD) == Font.BOLD &&
                ((fileFont.style & Font.BOLD) == 0)) {
                algoStyle = true;
                boldness = 1.33f;
            }
        }
        double[] matrix = new double[4];
        AffineTransform at = desc.glyphTx;
        at.getMatrix(matrix);
        if (!desc.devTx.isIdentity() &&
            desc.devTx.getType() != AffineTransform.TYPE_TRANSLATION) {
            try {
                invertDevTx = desc.devTx.createInverse();
            } catch (NoninvertibleTransformException e) {
            }
        }

        /* Amble fonts are better rendered unhinted although there's the
         * inevitable fuzziness that accompanies this due to no longer
         * snapping stems to the pixel grid. The exception is that in B&W
         * mode they are worse without hinting. The down side to that is that
         * B&W metrics will differ which normally isn't the case, although
         * since AA mode is part of the measuring context that should be OK.
         * We don't expect Amble to be installed in the Windows fonts folder.
         * If we were to, then we'd also might want to disable using the
         * native rasteriser path which is used for LCD mode for platform
         * fonts. since we have no way to disable hinting by GDI.
         * In the case of Amble, since its 'gasp' table says to disable
         * hinting, I'd expect GDI to follow that, so likely it should
         * all be consistent even if GDI used.
         */
        boolean disableHinting = desc.aaHint != INTVAL_TEXT_ANTIALIAS_OFF &&
                                 fileFont.familyName.startsWith("Amble");

        /* If any of the values is NaN then substitute the null scaler context.
         * This will return null images, zero advance, and empty outlines
         * as no rendering need take place in this case.
         * We pass in the null scaler as the singleton null context
         * requires it. However
         */
        if (Double.isNaN(matrix[0]) || Double.isNaN(matrix[1]) ||
            Double.isNaN(matrix[2]) || Double.isNaN(matrix[3]) ||
            fileFont.getScaler() == null) {
            pScalerContext = NullFontScaler.getNullScalerContext();
        } else {
            pScalerContext = fileFont.getScaler().createScalerContext(matrix,
                                    desc.aaHint, desc.fmHint,
                                    boldness, italic, disableHinting);
        }

        mapper = fileFont.getMapper();
        int numGlyphs = mapper.getNumGlyphs();

        /* Always segment for fonts with > 256 glyphs, but also for smaller
         * fonts with non-typical sizes and transforms.
         * Segmenting for all non-typical pt sizes helps to minimize memory
         * usage when very many distinct strikes are created.
         * The size range of 0->5 and 37->INF for segmenting is arbitrary
         * but the intention is that typical GUI integer point sizes (6->36)
         * should not segment unless there's another reason to do so.
         */
        float ptSize = (float)matrix[3]; // interpreted only when meaningful.
        int iSize = intPtSize = (int)ptSize;
        boolean isSimpleTx = (at.getType() & complexTX) == 0;
        segmentedCache =
            (numGlyphs > SEGSIZE << 3) ||
            ((numGlyphs > SEGSIZE << 1) &&
             (!isSimpleTx || ptSize != iSize || iSize < 6 || iSize > 36));

        /* This can only happen if we failed to allocate memory for context.
         * NB: in such case we may still have some memory in java heap
         *     but subsequent attempt to allocate null scaler context
         *     may fail too (cause it is allocate in the native heap).
         *     It is not clear how to make this more robust but on the
         *     other hand getting NULL here seems to be extremely unlikely.
         */
        if (pScalerContext == 0L) {
            /* REMIND: when the code is updated to install cache objects
             * rather than using a switch this will be more efficient.
             */
            this.disposer = new FontStrikeDisposer(fileFont, desc);
            initGlyphCache();
            pScalerContext = NullFontScaler.getNullScalerContext();
            SunFontManager.getInstance().deRegisterBadFont(fileFont);
            return;
        }
        /* First, see if native code should be used to create the glyph.
         * GDI will return the integer metrics, not fractional metrics, which
         * may be requested for this strike, so we would require here that :
         * desc.fmHint != INTVAL_FRACTIONALMETRICS_ON
         * except that the advance returned by GDI is always overwritten by
         * the JDK rasteriser supplied one (see getGlyphImageFromWindows()).
         */
        if (FontUtilities.isWindows && isXPorLater &&
            !FontUtilities.useT2K &&
            !GraphicsEnvironment.isHeadless() &&
            !fileFont.useJavaRasterizer &&
            (desc.aaHint == INTVAL_TEXT_ANTIALIAS_LCD_HRGB ||
             desc.aaHint == INTVAL_TEXT_ANTIALIAS_LCD_HBGR) &&
            (matrix[1] == 0.0 && matrix[2] == 0.0 &&
             matrix[0] == matrix[3] &&
             matrix[0] >= 3.0 && matrix[0] <= 100.0) &&
            !((TrueTypeFont)fileFont).useEmbeddedBitmapsForSize(intPtSize)) {
            useNatives = true;
        }
        else if (fileFont.checkUseNatives() && desc.aaHint==0 && !algoStyle) {
            /* Check its a simple scale of a pt size in the range
             * where native bitmaps typically exist (6-36 pts) */
            if (matrix[1] == 0.0 && matrix[2] == 0.0 &&
                matrix[0] >= 6.0 && matrix[0] <= 36.0 &&
                matrix[0] == matrix[3]) {
                useNatives = true;
                int numNatives = fileFont.nativeFonts.length;
                nativeStrikes = new NativeStrike[numNatives];
                /* Maybe initialise these strikes lazily?. But we
                 * know we need at least one
                 */
                for (int i=0; i<numNatives; i++) {
                    nativeStrikes[i] =
                        new NativeStrike(fileFont.nativeFonts[i], desc, false);
                }
            }
        }
        if (FontUtilities.isLogging() && FontUtilities.isWindows) {
            FontUtilities.getLogger().info
                ("Strike for " + fileFont + " at size = " + intPtSize +
                 " use natives = " + useNatives +
                 " useJavaRasteriser = " + fileFont.useJavaRasterizer +
                 " AAHint = " + desc.aaHint +
                 " Has Embedded bitmaps = " +
                 ((TrueTypeFont)fileFont).
                 useEmbeddedBitmapsForSize(intPtSize));
        }
        this.disposer = new FontStrikeDisposer(fileFont, desc, pScalerContext);

        /* Always get the image and the advance together for smaller sizes
         * that are likely to be important to rendering performance.
         * The pixel size of 48.0 can be thought of as
         * "maximumSizeForGetImageWithAdvance".
         * This should be no greater than OutlineTextRender.THRESHOLD.
         */
        double maxSz = 48.0;
        getImageWithAdvance =
            Math.abs(at.getScaleX()) <= maxSz &&
            Math.abs(at.getScaleY()) <= maxSz &&
            Math.abs(at.getShearX()) <= maxSz &&
            Math.abs(at.getShearY()) <= maxSz;

        /* Some applications request advance frequently during layout.
         * If we are not getting and caching the image with the advance,
         * there is a potentially significant performance penalty if the
         * advance is repeatedly requested before requesting the image.
         * We should at least cache the horizontal advance.
         * REMIND: could use info in the font, eg hmtx, to retrieve some
         * advances. But still want to cache it here.
         */

        if (!getImageWithAdvance) {
            if (!segmentedCache) {
                horizontalAdvances = new float[numGlyphs];
                /* use max float as uninitialised advance */
                for (int i=0; i<numGlyphs; i++) {
                    horizontalAdvances[i] = Float.MAX_VALUE;
                }
            } else {
                int numSegments = (numGlyphs + SEGSIZE-1)/SEGSIZE;
                segHorizontalAdvances = new float[numSegments][];
            }
        }
    }

    /* A number of methods are delegated by the strike to the scaler
     * context which is a shared resource on a physical font.
     */

    public int getNumGlyphs() {
        return fileFont.getNumGlyphs();
    }

    long getGlyphImageFromNative(int glyphCode) {
        if (FontUtilities.isWindows) {
            return getGlyphImageFromWindows(glyphCode);
        } else {
            return getGlyphImageFromX11(glyphCode);
        }
    }

    /* There's no global state conflicts, so this method is not
     * presently synchronized.
     */
    private native long _getGlyphImageFromWindows(String family,
                                                  int style,
                                                  int size,
                                                  int glyphCode,
                                                  boolean fracMetrics);

    long getGlyphImageFromWindows(int glyphCode) {
        String family = fileFont.getFamilyName(null);
        int style = desc.style & Font.BOLD | desc.style & Font.ITALIC
            | fileFont.getStyle();
        int size = intPtSize;
        long ptr = _getGlyphImageFromWindows
            (family, style, size, glyphCode,
             desc.fmHint == INTVAL_FRACTIONALMETRICS_ON);
        if (ptr != 0) {
            /* Get the advance from the JDK rasterizer. This is mostly
             * necessary for the fractional metrics case, but there are
             * also some very small number (<0.25%) of marginal cases where
             * there is some rounding difference between windows and JDK.
             * After these are resolved, we can restrict this extra
             * work to the FM case.
             */
            float advance = getGlyphAdvance(glyphCode, false);
            StrikeCache.unsafe.putFloat(ptr + StrikeCache.xAdvanceOffset,
                                        advance);
            return ptr;
        } else {
            return fileFont.getGlyphImage(pScalerContext, glyphCode);
        }
    }

    /* Try the native strikes first, then try the fileFont strike */
    long getGlyphImageFromX11(int glyphCode) {
        long glyphPtr;
        char charCode = fileFont.glyphToCharMap[glyphCode];
        for (int i=0;i<nativeStrikes.length;i++) {
            CharToGlyphMapper mapper = fileFont.nativeFonts[i].getMapper();
            int gc = mapper.charToGlyph(charCode)&0xffff;
            if (gc != mapper.getMissingGlyphCode()) {
                glyphPtr = nativeStrikes[i].getGlyphImagePtrNoCache(gc);
                if (glyphPtr != 0L) {
                    return glyphPtr;
                }
            }
        }
        return fileFont.getGlyphImage(pScalerContext, glyphCode);
    }

    long getGlyphImagePtr(int glyphCode) {
        if (glyphCode >= INVISIBLE_GLYPHS) {
            return StrikeCache.invisibleGlyphPtr;
        }
        long glyphPtr = 0L;
        if ((glyphPtr = getCachedGlyphPtr(glyphCode)) != 0L) {
            return glyphPtr;
        } else {
            if (useNatives) {
                glyphPtr = getGlyphImageFromNative(glyphCode);
                if (glyphPtr == 0L && FontUtilities.isLogging()) {
                    FontUtilities.getLogger().info
                        ("Strike for " + fileFont +
                         " at size = " + intPtSize +
                         " couldn't get native glyph for code = " + glyphCode);
                 }
            } if (glyphPtr == 0L) {
                glyphPtr = fileFont.getGlyphImage(pScalerContext,
                                                  glyphCode);
            }
            return setCachedGlyphPtr(glyphCode, glyphPtr);
        }
    }

    void getGlyphImagePtrs(int[] glyphCodes, long[] images, int  len) {

        for (int i=0; i<len; i++) {
            int glyphCode = glyphCodes[i];
            if (glyphCode >= INVISIBLE_GLYPHS) {
                images[i] = StrikeCache.invisibleGlyphPtr;
                continue;
            } else if ((images[i] = getCachedGlyphPtr(glyphCode)) != 0L) {
                continue;
            } else {
                long glyphPtr = 0L;
                if (useNatives) {
                    glyphPtr = getGlyphImageFromNative(glyphCode);
                } if (glyphPtr == 0L) {
                    glyphPtr = fileFont.getGlyphImage(pScalerContext,
                                                      glyphCode);
                }
                images[i] = setCachedGlyphPtr(glyphCode, glyphPtr);
            }
        }
    }

    /* The following method is called from CompositeStrike as a special case.
     */
    int getSlot0GlyphImagePtrs(int[] glyphCodes, long[] images, int len) {

        int convertedCnt = 0;

        for (int i=0; i<len; i++) {
            int glyphCode = glyphCodes[i];
            if (glyphCode >>> 24 != 0) {
                return convertedCnt;
            } else {
                convertedCnt++;
            }
            if (glyphCode >= INVISIBLE_GLYPHS) {
                images[i] = StrikeCache.invisibleGlyphPtr;
                continue;
            } else if ((images[i] = getCachedGlyphPtr(glyphCode)) != 0L) {
                continue;
            } else {
                long glyphPtr = 0L;
                if (useNatives) {
                    glyphPtr = getGlyphImageFromNative(glyphCode);
                }
                if (glyphPtr == 0L) {
                    glyphPtr = fileFont.getGlyphImage(pScalerContext,
                                                      glyphCode);
                }
                images[i] = setCachedGlyphPtr(glyphCode, glyphPtr);
            }
        }
        return convertedCnt;
    }

    /* Only look in the cache */
    long getCachedGlyphPtr(int glyphCode) {
        try {
            return getCachedGlyphPtrInternal(glyphCode);
        } catch (Exception e) {
          NullFontScaler nullScaler =
             (NullFontScaler)FontScaler.getNullScaler();
          long nullSC = NullFontScaler.getNullScalerContext();
          return nullScaler.getGlyphImage(nullSC, glyphCode);
        }
    }

    private long getCachedGlyphPtrInternal(int glyphCode) {
        switch (glyphCacheFormat) {
            case INTARRAY:
                return intGlyphImages[glyphCode] & INTMASK;
            case SEGINTARRAY:
                int segIndex = glyphCode >> SEGSHIFT;
                if (segIntGlyphImages[segIndex] != null) {
                    int subIndex = glyphCode % SEGSIZE;
                    return segIntGlyphImages[segIndex][subIndex] & INTMASK;
                } else {
                    return 0L;
                }
            case LONGARRAY:
                return longGlyphImages[glyphCode];
            case SEGLONGARRAY:
                segIndex = glyphCode >> SEGSHIFT;
                if (segLongGlyphImages[segIndex] != null) {
                    int subIndex = glyphCode % SEGSIZE;
                    return segLongGlyphImages[segIndex][subIndex];
                } else {
                    return 0L;
                }
        }
        /* If reach here cache is UNINITIALISED. */
        return 0L;
    }

    private synchronized long setCachedGlyphPtr(int glyphCode, long glyphPtr) {
        try {
            return setCachedGlyphPtrInternal(glyphCode, glyphPtr);
        } catch (Exception e) {
            switch (glyphCacheFormat) {
                case INTARRAY:
                case SEGINTARRAY:
                    StrikeCache.freeIntPointer((int)glyphPtr);
                    break;
                case LONGARRAY:
                case SEGLONGARRAY:
                    StrikeCache.freeLongPointer(glyphPtr);
                    break;
             }
             NullFontScaler nullScaler =
                 (NullFontScaler)FontScaler.getNullScaler();
             long nullSC = NullFontScaler.getNullScalerContext();
             return nullScaler.getGlyphImage(nullSC, glyphCode);
        }
    }

    private long setCachedGlyphPtrInternal(int glyphCode, long glyphPtr) {
        switch (glyphCacheFormat) {
            case INTARRAY:
                if (intGlyphImages[glyphCode] == 0) {
                    intGlyphImages[glyphCode] = (int)glyphPtr;
                    return glyphPtr;
                } else {
                    StrikeCache.freeIntPointer((int)glyphPtr);
                    return intGlyphImages[glyphCode] & INTMASK;
                }

            case SEGINTARRAY:
                int segIndex = glyphCode >> SEGSHIFT;
                int subIndex = glyphCode % SEGSIZE;
                if (segIntGlyphImages[segIndex] == null) {
                    segIntGlyphImages[segIndex] = new int[SEGSIZE];
                }
                if (segIntGlyphImages[segIndex][subIndex] == 0) {
                    segIntGlyphImages[segIndex][subIndex] = (int)glyphPtr;
                    return glyphPtr;
                } else {
                    StrikeCache.freeIntPointer((int)glyphPtr);
                    return segIntGlyphImages[segIndex][subIndex] & INTMASK;
                }

            case LONGARRAY:
                if (longGlyphImages[glyphCode] == 0L) {
                    longGlyphImages[glyphCode] = glyphPtr;
                    return glyphPtr;
                } else {
                    StrikeCache.freeLongPointer(glyphPtr);
                    return longGlyphImages[glyphCode];
                }

           case SEGLONGARRAY:
                segIndex = glyphCode >> SEGSHIFT;
                subIndex = glyphCode % SEGSIZE;
                if (segLongGlyphImages[segIndex] == null) {
                    segLongGlyphImages[segIndex] = new long[SEGSIZE];
                }
                if (segLongGlyphImages[segIndex][subIndex] == 0L) {
                    segLongGlyphImages[segIndex][subIndex] = glyphPtr;
                    return glyphPtr;
                } else {
                    StrikeCache.freeLongPointer(glyphPtr);
                    return segLongGlyphImages[segIndex][subIndex];
                }
        }

        /* Reach here only when the cache is not initialised which is only
         * for the first glyph to be initialised in the strike.
         * Initialise it and recurse. Note that we are already synchronized.
         */
        initGlyphCache();
        return setCachedGlyphPtr(glyphCode, glyphPtr);
    }

    /* Called only from synchronized code or constructor */
    private synchronized void initGlyphCache() {

        int numGlyphs = mapper.getNumGlyphs();
        int tmpFormat = UNINITIALISED;
        if (segmentedCache) {
            int numSegments = (numGlyphs + SEGSIZE-1)/SEGSIZE;
            if (longAddresses) {
                tmpFormat = SEGLONGARRAY;
                segLongGlyphImages = new long[numSegments][];
                this.disposer.segLongGlyphImages = segLongGlyphImages;
             } else {
                 tmpFormat = SEGINTARRAY;
                 segIntGlyphImages = new int[numSegments][];
                 this.disposer.segIntGlyphImages = segIntGlyphImages;
             }
        } else {
            if (longAddresses) {
                tmpFormat = LONGARRAY;
                longGlyphImages = new long[numGlyphs];
                this.disposer.longGlyphImages = longGlyphImages;
            } else {
                tmpFormat = INTARRAY;
                intGlyphImages = new int[numGlyphs];
                this.disposer.intGlyphImages = intGlyphImages;
            }
        }
        glyphCacheFormat = tmpFormat;
    }

    float getGlyphAdvance(int glyphCode) {
        return getGlyphAdvance(glyphCode, true);
    }

    /* Metrics info is always retrieved. If the GlyphInfo address is non-zero
     * then metrics info there is valid and can just be copied.
     * This is in user space coordinates unless getUserAdv == false.
     * Device space advance should not be propagated out of this class.
     */
    private float getGlyphAdvance(int glyphCode, boolean getUserAdv) {
        float advance;

        if (glyphCode >= INVISIBLE_GLYPHS) {
            return 0f;
        }

        /* Notes on the (getUserAdv == false) case.
         *
         * Setting getUserAdv == false is internal to this class.
         * If there's no graphics transform we can let
         * getGlyphAdvance take its course, and potentially caching in
         * advances arrays, except for signalling that
         * getUserAdv == false means there is no need to create an image.
         * It is possible that code already calculated the user advance,
         * and it is desirable to take advantage of that work.
         * But, if there's a transform and we want device advance, we
         * can't use any values cached in the advances arrays - unless
         * first re-transform them into device space using 'desc.devTx'.
         * invertDevTx is null if the graphics transform is identity,
         * a translate, or non-invertible. The latter case should
         * not ever occur in the getUserAdv == false path.
         * In other words its either null, or the inversion of a
         * simple uniform scale. If its null, we can populate and
         * use the advance caches as normal.
         *
         * If we don't find a cached value, obtain the device advance and
         * return it. This will get stashed on the image by the caller and any
         * subsequent metrics calls will be able to use it as is the case
         * whenever an image is what is initially requested.
         *
         * Don't query if there's a value cached on the image, since this
         * getUserAdv==false code path is entered solely when none exists.
         */
        if (horizontalAdvances != null) {
            advance = horizontalAdvances[glyphCode];
            if (advance != Float.MAX_VALUE) {
                if (!getUserAdv && invertDevTx != null) {
                    Point2D.Float metrics = new Point2D.Float(advance, 0f);
                    desc.devTx.deltaTransform(metrics, metrics);
                    return metrics.x;
                } else {
                    return advance;
                }
            }
        } else if (segmentedCache && segHorizontalAdvances != null) {
            int segIndex = glyphCode >> SEGSHIFT;
            float[] subArray = segHorizontalAdvances[segIndex];
            if (subArray != null) {
                advance = subArray[glyphCode % SEGSIZE];
                if (advance != Float.MAX_VALUE) {
                    if (!getUserAdv && invertDevTx != null) {
                        Point2D.Float metrics = new Point2D.Float(advance, 0f);
                        desc.devTx.deltaTransform(metrics, metrics);
                        return metrics.x;
                    } else {
                        return advance;
                    }
                }
            }
        }

        if (!getUserAdv && invertDevTx != null) {
            Point2D.Float metrics = new Point2D.Float();
            fileFont.getGlyphMetrics(pScalerContext, glyphCode, metrics);
            return metrics.x;
        }

        if (invertDevTx != null || !getUserAdv) {
            /* If there is a device transform need x & y advance to
             * transform back into user space.
             */
            advance = getGlyphMetrics(glyphCode, getUserAdv).x;
        } else {
            long glyphPtr;
            if (getImageWithAdvance) {
                /* A heuristic optimisation says that for most cases its
                 * worthwhile retrieving the image at the same time as the
                 * advance. So here we get the image data even if its not
                 * already cached.
                 */
                glyphPtr = getGlyphImagePtr(glyphCode);
            } else {
                glyphPtr = getCachedGlyphPtr(glyphCode);
            }
            if (glyphPtr != 0L) {
                advance = StrikeCache.unsafe.getFloat
                    (glyphPtr + StrikeCache.xAdvanceOffset);

            } else {
                advance = fileFont.getGlyphAdvance(pScalerContext, glyphCode);
            }
        }

        if (horizontalAdvances != null) {
            horizontalAdvances[glyphCode] = advance;
        } else if (segmentedCache && segHorizontalAdvances != null) {
            int segIndex = glyphCode >> SEGSHIFT;
            int subIndex = glyphCode % SEGSIZE;
            if (segHorizontalAdvances[segIndex] == null) {
                segHorizontalAdvances[segIndex] = new float[SEGSIZE];
                for (int i=0; i<SEGSIZE; i++) {
                     segHorizontalAdvances[segIndex][i] = Float.MAX_VALUE;
                }
            }
            segHorizontalAdvances[segIndex][subIndex] = advance;
        }
        return advance;
    }

    float getCodePointAdvance(int cp) {
        return getGlyphAdvance(mapper.charToGlyph(cp));
    }

    /**
     * Result and pt are both in device space.
     */
    void getGlyphImageBounds(int glyphCode, Point2D.Float pt,
                             Rectangle result) {

        long ptr = getGlyphImagePtr(glyphCode);
        float topLeftX, topLeftY;

        /* With our current design NULL ptr is not possible
           but if we eventually allow scalers to return NULL pointers
           this check might be actually useful. */
        if (ptr == 0L) {
            result.x = (int) Math.floor(pt.x);
            result.y = (int) Math.floor(pt.y);
            result.width = result.height = 0;
            return;
        }

        topLeftX = StrikeCache.unsafe.getFloat(ptr+StrikeCache.topLeftXOffset);
        topLeftY = StrikeCache.unsafe.getFloat(ptr+StrikeCache.topLeftYOffset);

        result.x = (int)Math.floor(pt.x + topLeftX);
        result.y = (int)Math.floor(pt.y + topLeftY);
        result.width =
            StrikeCache.unsafe.getShort(ptr+StrikeCache.widthOffset)  &0x0ffff;
        result.height =
            StrikeCache.unsafe.getShort(ptr+StrikeCache.heightOffset) &0x0ffff;

        /* HRGB LCD text may have padding that is empty. This is almost always
         * going to be when topLeftX is -2 or less.
         * Try to return a tighter bounding box in that case.
         * If the first three bytes of every row are all zero, then
         * add 1 to "x" and reduce "width" by 1.
         */
        if ((desc.aaHint == INTVAL_TEXT_ANTIALIAS_LCD_HRGB ||
             desc.aaHint == INTVAL_TEXT_ANTIALIAS_LCD_HBGR)
            && topLeftX <= -2.0f) {
            int minx = getGlyphImageMinX(ptr, (int)result.x);
            if (minx > result.x) {
                result.x += 1;
                result.width -=1;
            }
        }
    }

    private int getGlyphImageMinX(long ptr, int origMinX) {

        int width = StrikeCache.unsafe.getChar(ptr+StrikeCache.widthOffset);
        int height = StrikeCache.unsafe.getChar(ptr+StrikeCache.heightOffset);
        int rowBytes =
            StrikeCache.unsafe.getChar(ptr+StrikeCache.rowBytesOffset);

        if (rowBytes == width) {
            return origMinX;
        }

        long pixelData =
            StrikeCache.unsafe.getAddress(ptr + StrikeCache.pixelDataOffset);

        if (pixelData == 0L) {
            return origMinX;
        }

        for (int y=0;y<height;y++) {
            for (int x=0;x<3;x++) {
                if (StrikeCache.unsafe.getByte(pixelData+y*rowBytes+x) != 0) {
                    return origMinX;
                }
            }
        }
        return origMinX+1;
    }

    /* These 3 metrics methods below should be implemented to return
     * values in user space.
     */
    StrikeMetrics getFontMetrics() {
        if (strikeMetrics == null) {
            strikeMetrics =
                fileFont.getFontMetrics(pScalerContext);
            if (invertDevTx != null) {
                strikeMetrics.convertToUserSpace(invertDevTx);
            }
        }
        return strikeMetrics;
    }

    Point2D.Float getGlyphMetrics(int glyphCode) {
        return getGlyphMetrics(glyphCode, true);
    }

    private Point2D.Float getGlyphMetrics(int glyphCode, boolean getImage) {
        Point2D.Float metrics = new Point2D.Float();

        // !!! or do we force sgv user glyphs?
        if (glyphCode >= INVISIBLE_GLYPHS) {
            return metrics;
        }
        long glyphPtr;
        if (getImageWithAdvance && getImage) {
            /* A heuristic optimisation says that for most cases its
             * worthwhile retrieving the image at the same time as the
             * metrics. So here we get the image data even if its not
             * already cached.
             */
            glyphPtr = getGlyphImagePtr(glyphCode);
        } else {
             glyphPtr = getCachedGlyphPtr(glyphCode);
        }
        if (glyphPtr != 0L) {
            metrics = new Point2D.Float();
            metrics.x = StrikeCache.unsafe.getFloat
                (glyphPtr + StrikeCache.xAdvanceOffset);
            metrics.y = StrikeCache.unsafe.getFloat
                (glyphPtr + StrikeCache.yAdvanceOffset);
            /* advance is currently in device space, need to convert back
             * into user space.
             * This must not include the translation component. */
            if (invertDevTx != null) {
                invertDevTx.deltaTransform(metrics, metrics);
            }
        } else {
            /* We sometimes cache these metrics as they are expensive to
             * generate for large glyphs.
             * We never reach this path if we obtain images with advances.
             * But if we do not obtain images with advances its possible that
             * we first obtain this information, then the image, and never
             * will access this value again.
             */
            Integer key = Integer.valueOf(glyphCode);
            Point2D.Float value = null;
            ConcurrentHashMap<Integer, Point2D.Float> glyphMetricsMap = null;
            if (glyphMetricsMapRef != null) {
                glyphMetricsMap = glyphMetricsMapRef.get();
            }
            if (glyphMetricsMap != null) {
                value = glyphMetricsMap.get(key);
                if (value != null) {
                    metrics.x = value.x;
                    metrics.y = value.y;
                    /* already in user space */
                    return metrics;
                }
            }
            if (value == null) {
                fileFont.getGlyphMetrics(pScalerContext, glyphCode, metrics);
                /* advance is currently in device space, need to convert back
                 * into user space.
                 */
                if (invertDevTx != null) {
                    invertDevTx.deltaTransform(metrics, metrics);
                }
                value = new Point2D.Float(metrics.x, metrics.y);
                /* We aren't synchronizing here so it is possible to
                 * overwrite the map with another one but this is harmless.
                 */
                if (glyphMetricsMap == null) {
                    glyphMetricsMap =
                        new ConcurrentHashMap<Integer, Point2D.Float>();
                    glyphMetricsMapRef =
                        new SoftReference<ConcurrentHashMap<Integer,
                        Point2D.Float>>(glyphMetricsMap);
                }
                glyphMetricsMap.put(key, value);
            }
        }
        return metrics;
    }

    Point2D.Float getCharMetrics(char ch) {
        return getGlyphMetrics(mapper.charToGlyph(ch));
    }

    /* The caller of this can be trusted to return a copy of this
     * return value rectangle to public API. In fact frequently it
     * can't use use this return value directly anyway.
     * This returns bounds in device space. Currently the only
     * caller is SGV and it converts back to user space.
     * We could change things so that this code does the conversion so
     * that all coords coming out of the font system are converted back
     * into user space even if they were measured in device space.
     * The same applies to the other methods that return outlines (below)
     * But it may make particular sense for this method that caches its
     * results.
     * There'd be plenty of exceptions, to this too, eg getGlyphPoint needs
     * device coords as its called from native layout and getGlyphImageBounds
     * is used by GlyphVector.getGlyphPixelBounds which is specified to
     * return device coordinates, the image pointers aren't really used
     * up in Java code either.
     */
    Rectangle2D.Float getGlyphOutlineBounds(int glyphCode) {

        if (boundsMap == null) {
            boundsMap = new ConcurrentHashMap<Integer, Rectangle2D.Float>();
        }

        Integer key = Integer.valueOf(glyphCode);
        Rectangle2D.Float bounds = boundsMap.get(key);

        if (bounds == null) {
            bounds = fileFont.getGlyphOutlineBounds(pScalerContext, glyphCode);
            boundsMap.put(key, bounds);
        }
        return bounds;
    }

    public Rectangle2D getOutlineBounds(int glyphCode) {
        return fileFont.getGlyphOutlineBounds(pScalerContext, glyphCode);
    }

    private
        WeakReference<ConcurrentHashMap<Integer,GeneralPath>> outlineMapRef;

    GeneralPath getGlyphOutline(int glyphCode, float x, float y) {

        GeneralPath gp = null;
        ConcurrentHashMap<Integer, GeneralPath> outlineMap = null;

        if (outlineMapRef != null) {
            outlineMap = outlineMapRef.get();
            if (outlineMap != null) {
                gp = (GeneralPath)outlineMap.get(glyphCode);
            }
        }

        if (gp == null) {
            gp = fileFont.getGlyphOutline(pScalerContext, glyphCode, 0, 0);
            if (outlineMap == null) {
                outlineMap = new ConcurrentHashMap<Integer, GeneralPath>();
                outlineMapRef =
                   new WeakReference
                       <ConcurrentHashMap<Integer,GeneralPath>>(outlineMap);
            }
            outlineMap.put(glyphCode, gp);
        }
        gp = (GeneralPath)gp.clone(); // mutable!
        if (x != 0f || y != 0f) {
            gp.transform(AffineTransform.getTranslateInstance(x, y));
        }
        return gp;
    }

    GeneralPath getGlyphVectorOutline(int[] glyphs, float x, float y) {
        return fileFont.getGlyphVectorOutline(pScalerContext,
                                              glyphs, glyphs.length, x, y);
    }

    protected void adjustPoint(Point2D.Float pt) {
        if (invertDevTx != null) {
            invertDevTx.deltaTransform(pt, pt);
        }
    }
}
