1935 lines · 69.8 KB · Java
RawDownload
                            }                        }                    }                     if (removeSlot && addSlot) { // reuse old slot with new transform                        newIndex = oldIndex;                        System.arraycopy(temp, 0, transforms, (newIndex - 1) * 6, 6);                    } else if (removeSlot) {                        if (transforms.length == 6) { // removing last one, so clear arrays                            indices = null;                            transforms = null;                             sgv.clearCaches(glyphIndex);                            sgv.clearFlags(FLAG_HAS_TRANSFORMS);                            strikesRef = null;                             return;                        }                         double[] ttemp = new double[transforms.length - 6];                        System.arraycopy(transforms, 0, ttemp, 0, (oldIndex - 1) * 6);                        System.arraycopy(transforms, oldIndex * 6, ttemp, (oldIndex - 1) * 6,                                         transforms.length - oldIndex * 6);                        transforms = ttemp;                         // clean up indices                        for (int i = 0; i < indices.length; ++i) {                            if (indices[i] > oldIndex) { // ignore == oldIndex, it's going away                                indices[i] -= 1;                            }                        }                        if (newIndex > oldIndex) { // don't forget to decrement this too if we need to                            --newIndex;                        }                    } else if (addSlot) {                        double[] ttemp = new double[transforms.length + 6];                        System.arraycopy(transforms, 0, ttemp, 0, transforms.length);                        System.arraycopy(temp, 0, ttemp, transforms.length, 6);                        transforms = ttemp;                    }                     indices[glyphIndex] = newIndex;                }            }             sgv.clearCaches(glyphIndex);            sgv.addFlags(FLAG_HAS_TRANSFORMS);            strikesRef = null;        }         // implements sgv.getGlyphTransform        AffineTransform getGlyphTransform(int ix) {            int index = indices[ix];            if (index == 0) {                return null;            }             int x = (index - 1) * 6;            return new AffineTransform(transforms[x + 0],                                       transforms[x + 1],                                       transforms[x + 2],                                       transforms[x + 3],                                       transforms[x + 4],                                       transforms[x + 5]);        }         int transformCount() {            if (transforms == null) {                return 0;            }            return transforms.length / 6;        }         /**         * The strike cache works like this.         *         * -Each glyph is thought of as having a transform, usually identity.         * -Each request for a strike is based on a device transform, either the         * one in the frc or the rendering transform.         * -For general info, strikes are held with soft references.         * -When rendering, strikes must be held with hard references for the         * duration of the rendering call.  GlyphList will have to hold this         * info along with the image and position info, but toss the strike info         * when done.         * -Build the strike cache as needed.  If the dev transform we want to use         * has changed from the last time it is built, the cache is flushed by         * the caller before these methods are called.         *         * Use a tx that doesn't include translation components of dst tx.         */        Object setupGlyphImages(long[] images, float[] positions, AffineTransform tx) {            int len = sgv.glyphs.length;             GlyphStrike[] sl = getAllStrikes();            for (int i = 0; i < len; ++i) {                GlyphStrike gs = sl[indices[i]];                int glyphID = sgv.glyphs[i];                images[i] = gs.strike.getGlyphImagePtr(glyphID);                 gs.getGlyphPosition(glyphID, i*2, sgv.positions, positions);            }            tx.transform(positions, 0, positions, 0, len);             return sl;        }         Rectangle getGlyphsPixelBounds(AffineTransform tx, float x, float y, int start, int count) {            Rectangle result = null;            Rectangle r = new Rectangle();            Point2D.Float pt = new Point.Float();            int n = start * 2;            while (--count >= 0) {                GlyphStrike gs = getStrike(start);                pt.x = x + sgv.positions[n++] + gs.dx;                pt.y = y + sgv.positions[n++] + gs.dy;                tx.transform(pt, pt);                gs.strike.getGlyphImageBounds(sgv.glyphs[start++], pt, r);                if (!r.isEmpty()) {                    if (result == null) {                        result = new Rectangle(r);                    } else {                        result.add(r);                    }                }            }            return result != null ? result : r;        }         GlyphStrike getStrike(int glyphIndex) {            if (indices != null) {                GlyphStrike[] strikes = getStrikeArray();                return getStrikeAtIndex(strikes, indices[glyphIndex]);            }            return sgv.getDefaultStrike();        }         private GlyphStrike[] getAllStrikes() {            if (indices == null) {                return null;            }             GlyphStrike[] strikes = getStrikeArray();            if (!haveAllStrikes) {                for (int i = 0; i < strikes.length; ++i) {                    getStrikeAtIndex(strikes, i);                }                haveAllStrikes = true;            }             return strikes;        }         private GlyphStrike[] getStrikeArray() {            GlyphStrike[] strikes = null;            if (strikesRef != null) {                strikes = (GlyphStrike[])strikesRef.get();            }            if (strikes == null) {                haveAllStrikes = false;                strikes = new GlyphStrike[transformCount() + 1];                strikesRef = new SoftReference(strikes);            }             return strikes;        }         private GlyphStrike getStrikeAtIndex(GlyphStrike[] strikes, int strikeIndex) {            GlyphStrike strike = strikes[strikeIndex];            if (strike == null) {                if (strikeIndex == 0) {                    strike = sgv.getDefaultStrike();                } else {                    int ix = (strikeIndex - 1) * 6;                    AffineTransform gtx = new AffineTransform(transforms[ix],                                                              transforms[ix+1],                                                              transforms[ix+2],                                                              transforms[ix+3],                                                              transforms[ix+4],                                                              transforms[ix+5]);                     strike = GlyphStrike.create(sgv, sgv.dtx, gtx);                }                strikes[strikeIndex] = strike;            }            return strike;        }    }     // This adjusts the metrics by the translation components of the glyph    // transform.  It is done here since the translation is not known by the    // strike.    // It adjusts the position of the image and the advance.     public static final class GlyphStrike {        StandardGlyphVector sgv;        FontStrike strike; // hard reference        float dx;        float dy;         static GlyphStrike create(StandardGlyphVector sgv, AffineTransform dtx, AffineTransform gtx) {            float dx = 0;            float dy = 0;             AffineTransform tx = sgv.ftx;            if (!dtx.isIdentity() || gtx != null) {                tx = new AffineTransform(sgv.ftx);                if (gtx != null) {                    tx.preConcatenate(gtx);                    dx = (float)tx.getTranslateX(); // uses ftx then gtx to get translation                    dy = (float)tx.getTranslateY();                }                if (!dtx.isIdentity()) {                    tx.preConcatenate(dtx);                }            }             int ptSize = 1; // only matters for 'gasp' case.            Object aaHint = sgv.frc.getAntiAliasingHint();            if (aaHint == VALUE_TEXT_ANTIALIAS_GASP) {                /* Must pass in the calculated point size for rendering.                 * If the glyph tx is anything other than identity or a                 *  simple translate, calculate the transformed point size.                 */                if (!tx.isIdentity() &&                    (tx.getType() & ~AffineTransform.TYPE_TRANSLATION) != 0) {                    double shearx = tx.getShearX();                    if (shearx != 0) {                        double scaley = tx.getScaleY();                        ptSize =                            (int)Math.sqrt(shearx * shearx + scaley * scaley);                    } else {                        ptSize = (int)(Math.abs(tx.getScaleY()));                    }                }            }            int aa = FontStrikeDesc.getAAHintIntVal(aaHint,sgv.font2D, ptSize);            int fm = FontStrikeDesc.getFMHintIntVal                (sgv.frc.getFractionalMetricsHint());            FontStrikeDesc desc = new FontStrikeDesc(dtx,                                                     tx,                                                     sgv.font.getStyle(),                                                     aa, fm);             FontStrike strike = sgv.font2D.getStrike(desc);  // !!! getStrike(desc, false)             return new GlyphStrike(sgv, strike, dx, dy);        }         private GlyphStrike(StandardGlyphVector sgv, FontStrike strike, float dx, float dy) {            this.sgv = sgv;            this.strike = strike;            this.dx = dx;            this.dy = dy;        }         void getADL(ADL result) {            StrikeMetrics sm = strike.getFontMetrics();            Point2D.Float delta = null;            if (sgv.font.isTransformed()) {                delta = new Point2D.Float();                delta.x = (float)sgv.font.getTransform().getTranslateX();                delta.y = (float)sgv.font.getTransform().getTranslateY();            }             result.ascentX = -sm.ascentX;            result.ascentY = -sm.ascentY;            result.descentX = sm.descentX;            result.descentY = sm.descentY;            result.leadingX = sm.leadingX;            result.leadingY = sm.leadingY;        }         void getGlyphPosition(int glyphID, int ix, float[] positions, float[] result) {            result[ix] = positions[ix] + dx;            ++ix;            result[ix] = positions[ix] + dy;        }         void addDefaultGlyphAdvance(int glyphID, Point2D.Float result) {            // !!! change this API?  Creates unnecessary garbage.  Also the name doesn't quite fit.            // strike.addGlyphAdvance(Point2D.Float adv);  // hey, whaddya know, matches my api :-)            Point2D.Float adv = strike.getGlyphMetrics(glyphID);            result.x += adv.x + dx;            result.y += adv.y + dy;        }         Rectangle2D getGlyphOutlineBounds(int glyphID, float x, float y) {            Rectangle2D result = null;            if (sgv.invdtx == null) {                result = new Rectangle2D.Float();                result.setRect(strike.getGlyphOutlineBounds(glyphID)); // don't mutate cached rect            } else {                GeneralPath gp = strike.getGlyphOutline(glyphID, 0, 0);                gp.transform(sgv.invdtx);                result = gp.getBounds2D();            }            /* Since x is the logical advance of the glyph to this point.             * Because of the way that Rectangle.union is specified, this             * means that subsequent unioning of a rect including that             * will be affected, even if the glyph is empty. So skip such             * cases. This alone isn't a complete solution since x==0             * may also not be what is wanted. The code that does the             * unioning also needs to be aware to ignore empty glyphs.             */            if (!result.isEmpty()) {                result.setRect(result.getMinX() + x + dx,                               result.getMinY() + y + dy,                               result.getWidth(), result.getHeight());            }            return result;        }         void appendGlyphOutline(int glyphID, GeneralPath result, float x, float y) {            // !!! fontStrike needs a method for this.  For that matter, GeneralPath does.            GeneralPath gp = null;            if (sgv.invdtx == null) {                gp = strike.getGlyphOutline(glyphID, x + dx, y + dy);            } else {                gp = strike.getGlyphOutline(glyphID, 0, 0);                gp.transform(sgv.invdtx);                gp.transform(AffineTransform.getTranslateInstance(x + dx, y + dy));            }            PathIterator iterator = gp.getPathIterator(null);            result.append(iterator, false);        }    }     public String toString() {        return appendString(null).toString();    }     StringBuffer appendString(StringBuffer buf) {        if (buf == null) {            buf = new StringBuffer();        }        try {            buf.append("SGV{font: ");            buf.append(font.toString());            buf.append(", frc: ");            buf.append(frc.toString());            buf.append(", glyphs: (");            buf.append(glyphs.length);            buf.append(")[");            for (int i = 0; i < glyphs.length; ++i) {                if (i > 0) {                    buf.append(", ");                }                buf.append(Integer.toHexString(glyphs[i]));            }            buf.append("]");            if (positions != null) {                buf.append(", positions: (");                buf.append(positions.length);                buf.append(")[");                for (int i = 0; i < positions.length; i += 2) {                    if (i > 0) {                        buf.append(", ");                    }                    buf.append(positions[i]);                    buf.append("@");                    buf.append(positions[i+1]);                }                buf.append("]");            }            if (charIndices != null) {                buf.append(", indices: (");                buf.append(charIndices.length);                buf.append(")[");                for (int i = 0; i < charIndices.length; ++i) {                    if (i > 0) {                        buf.append(", ");                    }                    buf.append(charIndices[i]);                }                buf.append("]");            }            buf.append(", flags:");            if (getLayoutFlags() == 0) {                buf.append(" default");            } else {                if ((flags & FLAG_HAS_TRANSFORMS) != 0) {                    buf.append(" tx");                }                if ((flags & FLAG_HAS_POSITION_ADJUSTMENTS) != 0) {                    buf.append(" pos");                }                if ((flags & FLAG_RUN_RTL) != 0) {                    buf.append(" rtl");                }                if ((flags & FLAG_COMPLEX_GLYPHS) != 0) {                    buf.append(" complex");                }            }        }        catch(Exception e) {            buf.append(" " + e.getMessage());        }        buf.append("}");         return buf;    }     static class ADL {        public float ascentX;        public float ascentY;        public float descentX;        public float descentY;        public float leadingX;        public float leadingY;         public String toString() {            return toStringBuffer(null).toString();        }         protected StringBuffer toStringBuffer(StringBuffer result) {            if (result == null) {                result = new StringBuffer();            }            result.append("ax: ");            result.append(ascentX);            result.append(" ay: ");            result.append(ascentY);            result.append(" dx: ");            result.append(descentX);            result.append(" dy: ");            result.append(descentY);            result.append(" lx: ");            result.append(leadingX);            result.append(" ly: ");            result.append(leadingY);             return result;        }    }}

Lines 1501–1935 of 1935. Previous lines