Search in sources :

Example 1 with CoreMetrics

use of sun.font.CoreMetrics in project jdk8u_jdk by JetBrains.

the class TextLayout method fastInit.

/*
     * the fast init generates a single glyph set.  This requires:
     * all one style
     * all renderable by one font (ie no embedded graphics)
     * all on one baseline
     */
private void fastInit(char[] chars, Font font, Map<? extends Attribute, ?> attrs, FontRenderContext frc) {
    // Object vf = attrs.get(TextAttribute.ORIENTATION);
    // isVerticalLine = TextAttribute.ORIENTATION_VERTICAL.equals(vf);
    isVerticalLine = false;
    LineMetrics lm = font.getLineMetrics(chars, 0, chars.length, frc);
    CoreMetrics cm = CoreMetrics.get(lm);
    byte glyphBaseline = (byte) cm.baselineIndex;
    if (attrs == null) {
        baseline = glyphBaseline;
        baselineOffsets = cm.baselineOffsets;
        justifyRatio = 1.0f;
    } else {
        paragraphInit(glyphBaseline, cm, attrs, chars);
    }
    characterCount = chars.length;
    textLine = TextLine.fastCreateTextLine(frc, chars, font, cm, attrs);
}
Also used : CoreMetrics(sun.font.CoreMetrics) FontLineMetrics(sun.font.FontLineMetrics) TextLineMetrics(java.awt.font.TextLine.TextLineMetrics)

Example 2 with CoreMetrics

use of sun.font.CoreMetrics in project jdk8u_jdk by JetBrains.

the class TextLayout method hitTestChar.

/**
     * Returns a <code>TextHitInfo</code> corresponding to the
     * specified point.
     * Coordinates outside the bounds of the <code>TextLayout</code>
     * map to hits on the leading edge of the first logical character,
     * or the trailing edge of the last logical character, as appropriate,
     * regardless of the position of that character in the line.  Only the
     * direction along the baseline is used to make this evaluation.
     * @param x the x offset from the origin of this
     *     <code>TextLayout</code>.  This is in standard coordinates.
     * @param y the y offset from the origin of this
     *     <code>TextLayout</code>.  This is in standard coordinates.
     * @param bounds the bounds of the <code>TextLayout</code>.  This
     *     is in baseline-relative coordinates.
     * @return a hit describing the character and edge (leading or trailing)
     *     under the specified point.
     */
public TextHitInfo hitTestChar(float x, float y, Rectangle2D bounds) {
    // check boundary conditions
    LayoutPathImpl lp = textLine.getLayoutPath();
    boolean prev = false;
    if (lp != null) {
        Point2D.Float pt = new Point2D.Float(x, y);
        prev = lp.pointToPath(pt, pt);
        x = pt.x;
        y = pt.y;
    }
    if (isVertical()) {
        if (y < bounds.getMinY()) {
            return TextHitInfo.leading(0);
        } else if (y >= bounds.getMaxY()) {
            return TextHitInfo.trailing(characterCount - 1);
        }
    } else {
        if (x < bounds.getMinX()) {
            return isLeftToRight() ? TextHitInfo.leading(0) : TextHitInfo.trailing(characterCount - 1);
        } else if (x >= bounds.getMaxX()) {
            return isLeftToRight() ? TextHitInfo.trailing(characterCount - 1) : TextHitInfo.leading(0);
        }
    }
    // revised hit test
    // the original seems too complex and fails miserably with italic offsets
    // the natural tendency is to move towards the character you want to hit
    // so we'll just measure distance to the center of each character's visual
    // bounds, pick the closest one, then see which side of the character's
    // center line (italic) the point is on.
    // this tends to make it easier to hit narrow characters, which can be a
    // bit odd if you're visually over an adjacent wide character. this makes
    // a difference with bidi, so perhaps i need to revisit this yet again.
    double distance = Double.MAX_VALUE;
    int index = 0;
    int trail = -1;
    CoreMetrics lcm = null;
    float icx = 0, icy = 0, ia = 0, cy = 0, dya = 0, ydsq = 0;
    for (int i = 0; i < characterCount; ++i) {
        if (!textLine.caretAtOffsetIsValid(i)) {
            continue;
        }
        if (trail == -1) {
            trail = i;
        }
        CoreMetrics cm = textLine.getCoreMetricsAt(i);
        if (cm != lcm) {
            lcm = cm;
            // just work around baseline mess for now
            if (cm.baselineIndex == GraphicAttribute.TOP_ALIGNMENT) {
                cy = -(textLine.getMetrics().ascent - cm.ascent) + cm.ssOffset;
            } else if (cm.baselineIndex == GraphicAttribute.BOTTOM_ALIGNMENT) {
                cy = textLine.getMetrics().descent - cm.descent + cm.ssOffset;
            } else {
                cy = cm.effectiveBaselineOffset(baselineOffsets) + cm.ssOffset;
            }
            float dy = (cm.descent - cm.ascent) / 2 - cy;
            dya = dy * cm.italicAngle;
            cy += dy;
            ydsq = (cy - y) * (cy - y);
        }
        float cx = textLine.getCharXPosition(i);
        float ca = textLine.getCharAdvance(i);
        float dx = ca / 2;
        cx += dx - dya;
        // proximity in x (along baseline) is two times as important as proximity in y
        double nd = Math.sqrt(4 * (cx - x) * (cx - x) + ydsq);
        if (nd < distance) {
            distance = nd;
            index = i;
            trail = -1;
            icx = cx;
            icy = cy;
            ia = cm.italicAngle;
        }
    }
    boolean left = x < icx - (y - icy) * ia;
    boolean leading = textLine.isCharLTR(index) == left;
    if (trail == -1) {
        trail = characterCount;
    }
    TextHitInfo result = leading ? TextHitInfo.leading(index) : TextHitInfo.trailing(trail - 1);
    return result;
}
Also used : CoreMetrics(sun.font.CoreMetrics) LayoutPathImpl(sun.font.LayoutPathImpl) Point2D(java.awt.geom.Point2D)

Example 3 with CoreMetrics

use of sun.font.CoreMetrics in project jdk8u_jdk by JetBrains.

the class Font method defaultLineMetrics.

private FontLineMetrics defaultLineMetrics(FontRenderContext frc) {
    FontLineMetrics flm = null;
    if (flmref == null || (flm = flmref.get()) == null || !flm.frc.equals(frc)) {
        /* The device transform in the frc is not used in obtaining line
             * metrics, although it probably should be: REMIND find why not?
             * The font transform is used but its applied in getFontMetrics, so
             * just pass identity here
             */
        float[] metrics = new float[8];
        getFont2D().getFontMetrics(this, identityTx, frc.getAntiAliasingHint(), frc.getFractionalMetricsHint(), metrics);
        float ascent = metrics[0];
        float descent = metrics[1];
        float leading = metrics[2];
        float ssOffset = 0;
        if (values != null && values.getSuperscript() != 0) {
            ssOffset = (float) getTransform().getTranslateY();
            ascent -= ssOffset;
            descent += ssOffset;
        }
        float height = ascent + descent + leading;
        // need real index, assumes roman for everything
        int baselineIndex = 0;
        // need real baselines eventually
        float[] baselineOffsets = { 0, (descent / 2f - ascent) / 2f, -ascent };
        float strikethroughOffset = metrics[4];
        float strikethroughThickness = metrics[5];
        float underlineOffset = metrics[6];
        float underlineThickness = metrics[7];
        float italicAngle = getItalicAngle(frc);
        if (isTransformed()) {
            // extract rotation
            AffineTransform ctx = values.getCharTransform();
            if (ctx != null) {
                Point2D.Float pt = new Point2D.Float();
                pt.setLocation(0, strikethroughOffset);
                ctx.deltaTransform(pt, pt);
                strikethroughOffset = pt.y;
                pt.setLocation(0, strikethroughThickness);
                ctx.deltaTransform(pt, pt);
                strikethroughThickness = pt.y;
                pt.setLocation(0, underlineOffset);
                ctx.deltaTransform(pt, pt);
                underlineOffset = pt.y;
                pt.setLocation(0, underlineThickness);
                ctx.deltaTransform(pt, pt);
                underlineThickness = pt.y;
            }
        }
        strikethroughOffset += ssOffset;
        underlineOffset += ssOffset;
        CoreMetrics cm = new CoreMetrics(ascent, descent, leading, height, baselineIndex, baselineOffsets, strikethroughOffset, strikethroughThickness, underlineOffset, underlineThickness, ssOffset, italicAngle);
        flm = new FontLineMetrics(0, cm, frc);
        flmref = new SoftReference<FontLineMetrics>(flm);
    }
    return (FontLineMetrics) flm.clone();
}
Also used : CoreMetrics(sun.font.CoreMetrics) Point2D(java.awt.geom.Point2D) FontLineMetrics(sun.font.FontLineMetrics) AffineTransform(java.awt.geom.AffineTransform)

Example 4 with CoreMetrics

use of sun.font.CoreMetrics in project jdk8u_jdk by JetBrains.

the class TextLayout method getCaretInfoTestInternal.

// this version provides extra info in the float array
// the first two values are as above
// the next four values are the endpoints of the caret, as computed
// using the hit character's offset (baseline + ssoffset) and
// natural ascent and descent.
// these  values are trimmed to the bounds where required to fit,
// but otherwise independent of it.
private float[] getCaretInfoTestInternal(TextHitInfo hit, Rectangle2D bounds) {
    ensureCache();
    checkTextHit(hit);
    float[] info = new float[6];
    // get old data first
    getCaretInfo(hitToCaret(hit), bounds, info);
    // then add our new data
    double iangle, ixbase, p1x, p1y, p2x, p2y;
    int charix = hit.getCharIndex();
    boolean lead = hit.isLeadingEdge();
    boolean ltr = textLine.isDirectionLTR();
    boolean horiz = !isVertical();
    if (charix == -1 || charix == characterCount) {
        // !!! note: want non-shifted, baseline ascent and descent here!
        // TextLine should return appropriate line metrics object for these values
        TextLineMetrics m = textLine.getMetrics();
        boolean low = ltr == (charix == -1);
        iangle = 0;
        if (horiz) {
            p1x = p2x = low ? 0 : m.advance;
            p1y = -m.ascent;
            p2y = m.descent;
        } else {
            p1y = p2y = low ? 0 : m.advance;
            p1x = m.descent;
            p2x = m.ascent;
        }
    } else {
        CoreMetrics thiscm = textLine.getCoreMetricsAt(charix);
        iangle = thiscm.italicAngle;
        ixbase = textLine.getCharLinePosition(charix, lead);
        if (thiscm.baselineIndex < 0) {
            // this is a graphic, no italics, use entire line height for caret
            TextLineMetrics m = textLine.getMetrics();
            if (horiz) {
                p1x = p2x = ixbase;
                if (thiscm.baselineIndex == GraphicAttribute.TOP_ALIGNMENT) {
                    p1y = -m.ascent;
                    p2y = p1y + thiscm.height;
                } else {
                    p2y = m.descent;
                    p1y = p2y - thiscm.height;
                }
            } else {
                p1y = p2y = ixbase;
                p1x = m.descent;
                p2x = m.ascent;
            // !!! top/bottom adjustment not implemented for vertical
            }
        } else {
            float bo = baselineOffsets[thiscm.baselineIndex];
            if (horiz) {
                ixbase += iangle * thiscm.ssOffset;
                p1x = ixbase + iangle * thiscm.ascent;
                p2x = ixbase - iangle * thiscm.descent;
                p1y = bo - thiscm.ascent;
                p2y = bo + thiscm.descent;
            } else {
                ixbase -= iangle * thiscm.ssOffset;
                p1y = ixbase + iangle * thiscm.ascent;
                p2y = ixbase - iangle * thiscm.descent;
                p1x = bo + thiscm.ascent;
                p2x = bo + thiscm.descent;
            }
        }
    }
    info[2] = (float) p1x;
    info[3] = (float) p1y;
    info[4] = (float) p2x;
    info[5] = (float) p2y;
    return info;
}
Also used : CoreMetrics(sun.font.CoreMetrics) TextLineMetrics(java.awt.font.TextLine.TextLineMetrics)

Example 5 with CoreMetrics

use of sun.font.CoreMetrics in project jdk8u_jdk by JetBrains.

the class TextLine method init.

private void init() {
    // first, we need to check for graphic components on the TOP or BOTTOM baselines.  So
    // we perform the work that used to be in getMetrics here.
    float ascent = 0;
    float descent = 0;
    float leading = 0;
    float advance = 0;
    // ascent + descent must not be less than this value
    float maxGraphicHeight = 0;
    float maxGraphicHeightWithLeading = 0;
    // walk through EGA's
    TextLineComponent tlc;
    boolean fitTopAndBottomGraphics = false;
    isSimple = true;
    for (int i = 0; i < fComponents.length; i++) {
        tlc = fComponents[i];
        isSimple &= tlc.isSimple();
        CoreMetrics cm = tlc.getCoreMetrics();
        byte baseline = (byte) cm.baselineIndex;
        if (baseline >= 0) {
            float baselineOffset = fBaselineOffsets[baseline];
            ascent = Math.max(ascent, -baselineOffset + cm.ascent);
            float gd = baselineOffset + cm.descent;
            descent = Math.max(descent, gd);
            leading = Math.max(leading, gd + cm.leading);
        } else {
            fitTopAndBottomGraphics = true;
            float graphicHeight = cm.ascent + cm.descent;
            float graphicHeightWithLeading = graphicHeight + cm.leading;
            maxGraphicHeight = Math.max(maxGraphicHeight, graphicHeight);
            maxGraphicHeightWithLeading = Math.max(maxGraphicHeightWithLeading, graphicHeightWithLeading);
        }
    }
    if (fitTopAndBottomGraphics) {
        if (maxGraphicHeight > ascent + descent) {
            descent = maxGraphicHeight - ascent;
        }
        if (maxGraphicHeightWithLeading > ascent + leading) {
            leading = maxGraphicHeightWithLeading - ascent;
        }
    }
    leading -= descent;
    if (fitTopAndBottomGraphics) {
        // we have top or bottom baselines, so expand the baselines array
        // full offsets are needed by CoreMetrics.effectiveBaselineOffset
        fBaselineOffsets = new float[] { fBaselineOffsets[0], fBaselineOffsets[1], fBaselineOffsets[2], descent, -ascent };
    }
    float x = 0;
    float y = 0;
    CoreMetrics pcm = null;
    boolean needPath = false;
    locs = new float[fComponents.length * 2 + 2];
    for (int i = 0, n = 0; i < fComponents.length; ++i, n += 2) {
        tlc = fComponents[getComponentLogicalIndex(i)];
        CoreMetrics cm = tlc.getCoreMetrics();
        if ((pcm != null) && // adjust because of italics
        (pcm.italicAngle != 0 || cm.italicAngle != 0) && (pcm.italicAngle != cm.italicAngle || pcm.baselineIndex != cm.baselineIndex || pcm.ssOffset != cm.ssOffset)) {
            // 1) compute the area of overlap - min effective ascent and min effective descent
            // 2) compute the x positions along italic angle of ascent and descent for left and right
            // 3) compute maximum left - right, adjust right position by this value
            // this is a crude form of kerning between textcomponents
            // note glyphvectors preposition glyphs based on offset,
            // so tl doesn't need to adjust glyphvector position
            // 1)
            float pb = pcm.effectiveBaselineOffset(fBaselineOffsets);
            float pa = pb - pcm.ascent;
            float pd = pb + pcm.descent;
            // pb += pcm.ssOffset;
            float cb = cm.effectiveBaselineOffset(fBaselineOffsets);
            float ca = cb - cm.ascent;
            float cd = cb + cm.descent;
            // cb += cm.ssOffset;
            float a = Math.max(pa, ca);
            float d = Math.min(pd, cd);
            // 2)
            float pax = pcm.italicAngle * (pb - a);
            float pdx = pcm.italicAngle * (pb - d);
            float cax = cm.italicAngle * (cb - a);
            float cdx = cm.italicAngle * (cb - d);
            // 3)
            float dax = pax - cax;
            float ddx = pdx - cdx;
            float dx = Math.max(dax, ddx);
            x += dx;
            y = cb;
        } else {
            // no italic adjustment for x, but still need to compute y
            // + cm.ssOffset;
            y = cm.effectiveBaselineOffset(fBaselineOffsets);
        }
        locs[n] = x;
        locs[n + 1] = y;
        x += tlc.getAdvance();
        pcm = cm;
        needPath |= tlc.getBaselineTransform() != null;
    }
    // do we want italic padding at the right of the line?
    if (pcm.italicAngle != 0) {
        float pb = pcm.effectiveBaselineOffset(fBaselineOffsets);
        float pa = pb - pcm.ascent;
        float pd = pb + pcm.descent;
        pb += pcm.ssOffset;
        float d;
        if (pcm.italicAngle > 0) {
            d = pb + pcm.ascent;
        } else {
            d = pb - pcm.descent;
        }
        d *= pcm.italicAngle;
        x += d;
    }
    locs[locs.length - 2] = x;
    // locs[locs.length - 1] = 0; // final offset is always back on baseline
    // ok, build fMetrics since we have the final advance
    advance = x;
    fMetrics = new TextLineMetrics(ascent, descent, leading, advance);
    // build path if we need it
    if (needPath) {
        isSimple = false;
        Point2D.Double pt = new Point2D.Double();
        double tx = 0, ty = 0;
        SegmentPathBuilder builder = new SegmentPathBuilder();
        builder.moveTo(locs[0], 0);
        for (int i = 0, n = 0; i < fComponents.length; ++i, n += 2) {
            tlc = fComponents[getComponentLogicalIndex(i)];
            AffineTransform at = tlc.getBaselineTransform();
            if (at != null && ((at.getType() & AffineTransform.TYPE_TRANSLATION) != 0)) {
                double dx = at.getTranslateX();
                double dy = at.getTranslateY();
                builder.moveTo(tx += dx, ty += dy);
            }
            pt.x = locs[n + 2] - locs[n];
            pt.y = 0;
            if (at != null) {
                at.deltaTransform(pt, pt);
            }
            builder.lineTo(tx += pt.x, ty += pt.y);
        }
        lp = builder.complete();
        if (lp == null) {
            // empty path
            tlc = fComponents[getComponentLogicalIndex(0)];
            AffineTransform at = tlc.getBaselineTransform();
            if (at != null) {
                lp = new EmptyPath(at);
            }
        }
    }
}
Also used : CoreMetrics(sun.font.CoreMetrics) Point2D(java.awt.geom.Point2D) TextLineComponent(sun.font.TextLineComponent) AffineTransform(java.awt.geom.AffineTransform) SegmentPathBuilder(sun.font.LayoutPathImpl.SegmentPathBuilder) EmptyPath(sun.font.LayoutPathImpl.EmptyPath)

Aggregations

CoreMetrics (sun.font.CoreMetrics)5 Point2D (java.awt.geom.Point2D)3 TextLineMetrics (java.awt.font.TextLine.TextLineMetrics)2 AffineTransform (java.awt.geom.AffineTransform)2 FontLineMetrics (sun.font.FontLineMetrics)2 LayoutPathImpl (sun.font.LayoutPathImpl)1 EmptyPath (sun.font.LayoutPathImpl.EmptyPath)1 SegmentPathBuilder (sun.font.LayoutPathImpl.SegmentPathBuilder)1 TextLineComponent (sun.font.TextLineComponent)1