Search in sources :

Example 1 with PhysicalFont

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

the class WPathGraphics method drawString.

/**
     * Renders the text specified by the specified <code>String</code>,
     * using the current <code>Font</code> and <code>Paint</code> attributes
     * in the <code>Graphics2D</code> context.
     * The baseline of the first character is at position
     * (<i>x</i>,&nbsp;<i>y</i>) in the User Space.
     * The rendering attributes applied include the <code>Clip</code>,
     * <code>Transform</code>, <code>Paint</code>, <code>Font</code> and
     * <code>Composite</code> attributes. For characters in script systems
     * such as Hebrew and Arabic, the glyphs can be rendered from right to
     * left, in which case the coordinate supplied is the location of the
     * leftmost character on the baseline.
     * @param s the <code>String</code> to be rendered
     * @param x,&nbsp;y the coordinates where the <code>String</code>
     * should be rendered
     * @see #setPaint
     * @see java.awt.Graphics#setColor
     * @see java.awt.Graphics#setFont
     * @see #setTransform
     * @see #setComposite
     * @see #setClip
     */
@Override
public void drawString(String str, float x, float y, Font font, FontRenderContext frc, float targetW) {
    if (str.length() == 0) {
        return;
    }
    if (WPrinterJob.shapeTextProp) {
        super.drawString(str, x, y, font, frc, targetW);
        return;
    }
    /* If the Font has layout attributes we need to delegate to TextLayout.
         * TextLayout renders text as GlyphVectors. We try to print those
         * using printer fonts - ie using Postscript text operators so
         * we may be reinvoked. In that case the "!printingGlyphVector" test
         * prevents us recursing and instead sends us into the body of the
         * method where we can safely ignore layout attributes as those
         * are already handled by TextLayout.
         * Similarly if layout is needed based on the text, then we
         * delegate to TextLayout if possible, or failing that we delegate
         * upwards to filled shapes.
         */
    boolean layoutNeeded = strNeedsTextLayout(str, font);
    if ((font.hasLayoutAttributes() || layoutNeeded) && !printingGlyphVector) {
        TextLayout layout = new TextLayout(str, font, frc);
        layout.draw(this, x, y);
        return;
    } else if (layoutNeeded) {
        super.drawString(str, x, y, font, frc, targetW);
        return;
    }
    AffineTransform deviceTransform = getTransform();
    AffineTransform fontTransform = new AffineTransform(deviceTransform);
    fontTransform.concatenate(font.getTransform());
    int transformType = fontTransform.getType();
    /* Use GDI for the text if the graphics transform is something
         * for which we can obtain a suitable GDI font.
         * A flip or shearing transform on the graphics or a transform
         * on the font force us to decompose the text into a shape.
         */
    boolean directToGDI = ((transformType != AffineTransform.TYPE_GENERAL_TRANSFORM) && ((transformType & AffineTransform.TYPE_FLIP) == 0));
    WPrinterJob wPrinterJob = (WPrinterJob) getPrinterJob();
    try {
        wPrinterJob.setTextColor((Color) getPaint());
    } catch (ClassCastException e) {
        // peek should detect such paints.
        directToGDI = false;
    }
    if (!directToGDI) {
        super.drawString(str, x, y, font, frc, targetW);
        return;
    }
    /* Now we have checked everything is OK to go through GDI as text
         * with the exception of testing GDI can find and use the font. That
         * is handled in the textOut() call.
         */
    /* Compute the starting position of the string in
         * device space.
         */
    Point2D.Float userpos = new Point2D.Float(x, y);
    Point2D.Float devpos = new Point2D.Float();
    /* Already have the translate from the deviceTransform,
         * but the font may have a translation component too.
         */
    if (font.isTransformed()) {
        AffineTransform fontTx = font.getTransform();
        float translateX = (float) (fontTx.getTranslateX());
        float translateY = (float) (fontTx.getTranslateY());
        if (Math.abs(translateX) < 0.00001)
            translateX = 0f;
        if (Math.abs(translateY) < 0.00001)
            translateY = 0f;
        userpos.x += translateX;
        userpos.y += translateY;
    }
    deviceTransform.transform(userpos, devpos);
    if (getClip() != null) {
        deviceClip(getClip().getPathIterator(deviceTransform));
    }
    /* Get the font size in device coordinates.
         * The size needed is the font height scaled to device space.
         * Although we have already tested that there is no shear,
         * there may be a non-uniform scale, so the width of the font
         * does not scale equally with the height. That is handled
         * by specifying an 'average width' scale to GDI.
         */
    float fontSize = font.getSize2D();
    double devResX = wPrinterJob.getXRes();
    double devResY = wPrinterJob.getYRes();
    double fontDevScaleY = devResY / DEFAULT_USER_RES;
    int orient = getPageFormat().getOrientation();
    if (orient == PageFormat.LANDSCAPE || orient == PageFormat.REVERSE_LANDSCAPE) {
        double tmp = devResX;
        devResX = devResY;
        devResY = tmp;
    }
    double devScaleX = devResX / DEFAULT_USER_RES;
    double devScaleY = devResY / DEFAULT_USER_RES;
    fontTransform.scale(1.0 / devScaleX, 1.0 / devScaleY);
    Point2D.Double pty = new Point2D.Double(0.0, 1.0);
    fontTransform.deltaTransform(pty, pty);
    double scaleFactorY = Math.sqrt(pty.x * pty.x + pty.y * pty.y);
    float scaledFontSizeY = (float) (fontSize * scaleFactorY * fontDevScaleY);
    Point2D.Double ptx = new Point2D.Double(1.0, 0.0);
    fontTransform.deltaTransform(ptx, ptx);
    double scaleFactorX = Math.sqrt(ptx.x * ptx.x + ptx.y * ptx.y);
    float awScale = getAwScale(scaleFactorX, scaleFactorY);
    int iangle = getAngle(ptx);
    ptx = new Point2D.Double(1.0, 0.0);
    deviceTransform.deltaTransform(ptx, ptx);
    double advanceScaleX = Math.sqrt(ptx.x * ptx.x + ptx.y * ptx.y);
    pty = new Point2D.Double(0.0, 1.0);
    deviceTransform.deltaTransform(pty, pty);
    double advanceScaleY = Math.sqrt(pty.x * pty.x + pty.y * pty.y);
    Font2D font2D = FontUtilities.getFont2D(font);
    if (font2D instanceof TrueTypeFont) {
        textOut(str, font, (TrueTypeFont) font2D, frc, scaledFontSizeY, iangle, awScale, advanceScaleX, advanceScaleY, x, y, devpos.x, devpos.y, targetW);
    } else if (font2D instanceof CompositeFont) {
        /* Composite fonts are made up of multiple fonts and each
             * substring that uses a particular component font needs to
             * be separately sent to GDI.
             * This works for standard composite fonts, alternate ones,
             * Fonts that are a physical font backed by a standard composite,
             * and with fallback fonts.
             */
        CompositeFont compFont = (CompositeFont) font2D;
        float userx = x, usery = y;
        float devx = devpos.x, devy = devpos.y;
        char[] chars = str.toCharArray();
        int len = chars.length;
        int[] glyphs = new int[len];
        compFont.getMapper().charsToGlyphs(len, chars, glyphs);
        int startChar = 0, endChar = 0, slot = 0;
        while (endChar < len) {
            startChar = endChar;
            slot = glyphs[startChar] >>> 24;
            while (endChar < len && ((glyphs[endChar] >>> 24) == slot)) {
                endChar++;
            }
            String substr = new String(chars, startChar, endChar - startChar);
            PhysicalFont slotFont = compFont.getSlotFont(slot);
            textOut(substr, font, slotFont, frc, scaledFontSizeY, iangle, awScale, advanceScaleX, advanceScaleY, userx, usery, devx, devy, 0f);
            Rectangle2D bds = font.getStringBounds(substr, frc);
            float xAdvance = (float) bds.getWidth();
            userx += xAdvance;
            userpos.x += xAdvance;
            deviceTransform.transform(userpos, devpos);
            devx = devpos.x;
            devy = devpos.y;
        }
    } else {
        super.drawString(str, x, y, font, frc, targetW);
    }
}
Also used : TrueTypeFont(sun.font.TrueTypeFont) CompositeFont(sun.font.CompositeFont) Font2D(sun.font.Font2D) Rectangle2D(java.awt.geom.Rectangle2D) TextLayout(java.awt.font.TextLayout) Point2D(java.awt.geom.Point2D) PhysicalFont(sun.font.PhysicalFont) AffineTransform(java.awt.geom.AffineTransform)

Example 2 with PhysicalFont

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

the class WPathGraphics method printGlyphVector.

/** return true if the Graphics instance can directly print
     * this glyphvector
     */
@Override
protected boolean printGlyphVector(GlyphVector gv, float x, float y) {
    /* We don't want to try to handle per-glyph transforms. GDI can't
         * handle per-glyph rotations, etc. There's no way to express it
         * in a single call, so just bail for this uncommon case.
         */
    if ((gv.getLayoutFlags() & GlyphVector.FLAG_HAS_TRANSFORMS) != 0) {
        return false;
    }
    if (gv.getNumGlyphs() == 0) {
        // nothing to do.
        return true;
    }
    AffineTransform deviceTransform = getTransform();
    AffineTransform fontTransform = new AffineTransform(deviceTransform);
    Font font = gv.getFont();
    fontTransform.concatenate(font.getTransform());
    int transformType = fontTransform.getType();
    /* Use GDI for the text if the graphics transform is something
         * for which we can obtain a suitable GDI font.
         * A flip or shearing transform on the graphics or a transform
         * on the font force us to decompose the text into a shape.
         */
    boolean directToGDI = ((transformType != AffineTransform.TYPE_GENERAL_TRANSFORM) && ((transformType & AffineTransform.TYPE_FLIP) == 0));
    WPrinterJob wPrinterJob = (WPrinterJob) getPrinterJob();
    try {
        wPrinterJob.setTextColor((Color) getPaint());
    } catch (ClassCastException e) {
        // peek should detect such paints.
        directToGDI = false;
    }
    if (WPrinterJob.shapeTextProp || !directToGDI) {
        return false;
    }
    /* Compute the starting position of the string in
         * device space.
         */
    Point2D.Float userpos = new Point2D.Float(x, y);
    /* Add the position of the first glyph - its not always 0,0 */
    Point2D g0pos = gv.getGlyphPosition(0);
    userpos.x += (float) g0pos.getX();
    userpos.y += (float) g0pos.getY();
    Point2D.Float devpos = new Point2D.Float();
    /* Already have the translate from the deviceTransform,
         * but the font may have a translation component too.
         */
    if (font.isTransformed()) {
        AffineTransform fontTx = font.getTransform();
        float translateX = (float) (fontTx.getTranslateX());
        float translateY = (float) (fontTx.getTranslateY());
        if (Math.abs(translateX) < 0.00001)
            translateX = 0f;
        if (Math.abs(translateY) < 0.00001)
            translateY = 0f;
        userpos.x += translateX;
        userpos.y += translateY;
    }
    deviceTransform.transform(userpos, devpos);
    if (getClip() != null) {
        deviceClip(getClip().getPathIterator(deviceTransform));
    }
    /* Get the font size in device coordinates.
         * The size needed is the font height scaled to device space.
         * Although we have already tested that there is no shear,
         * there may be a non-uniform scale, so the width of the font
         * does not scale equally with the height. That is handled
         * by specifying an 'average width' scale to GDI.
         */
    float fontSize = font.getSize2D();
    double devResX = wPrinterJob.getXRes();
    double devResY = wPrinterJob.getYRes();
    double fontDevScaleY = devResY / DEFAULT_USER_RES;
    int orient = getPageFormat().getOrientation();
    if (orient == PageFormat.LANDSCAPE || orient == PageFormat.REVERSE_LANDSCAPE) {
        double tmp = devResX;
        devResX = devResY;
        devResY = tmp;
    }
    double devScaleX = devResX / DEFAULT_USER_RES;
    double devScaleY = devResY / DEFAULT_USER_RES;
    fontTransform.scale(1.0 / devScaleX, 1.0 / devScaleY);
    Point2D.Double pty = new Point2D.Double(0.0, 1.0);
    fontTransform.deltaTransform(pty, pty);
    double scaleFactorY = Math.sqrt(pty.x * pty.x + pty.y * pty.y);
    float scaledFontSizeY = (float) (fontSize * scaleFactorY * fontDevScaleY);
    Point2D.Double ptx = new Point2D.Double(1.0, 0.0);
    fontTransform.deltaTransform(ptx, ptx);
    double scaleFactorX = Math.sqrt(ptx.x * ptx.x + ptx.y * ptx.y);
    float awScale = getAwScale(scaleFactorX, scaleFactorY);
    int iangle = getAngle(ptx);
    ptx = new Point2D.Double(1.0, 0.0);
    deviceTransform.deltaTransform(ptx, ptx);
    double advanceScaleX = Math.sqrt(ptx.x * ptx.x + ptx.y * ptx.y);
    pty = new Point2D.Double(0.0, 1.0);
    deviceTransform.deltaTransform(pty, pty);
    double advanceScaleY = Math.sqrt(pty.x * pty.x + pty.y * pty.y);
    int numGlyphs = gv.getNumGlyphs();
    int[] glyphCodes = gv.getGlyphCodes(0, numGlyphs, null);
    float[] glyphPos = gv.getGlyphPositions(0, numGlyphs, null);
    /* layout replaces glyphs which have been combined away
         * with 0xfffe or 0xffff. These are supposed to be invisible
         * and we need to handle this here as GDI will interpret it
         * as a missing glyph. We'll do it here by compacting the
         * glyph codes array, but we have to do it in conjunction with
         * compacting the positions/advances arrays too AND updating
         * the number of glyphs ..
         * Note that since the slot number for composites is in the
         * significant byte we need to mask out that for comparison of
         * the invisible glyph.
         */
    int invisibleGlyphCnt = 0;
    for (int gc = 0; gc < numGlyphs; gc++) {
        if ((glyphCodes[gc] & 0xffff) >= CharToGlyphMapper.INVISIBLE_GLYPHS) {
            invisibleGlyphCnt++;
        }
    }
    if (invisibleGlyphCnt > 0) {
        int visibleGlyphCnt = numGlyphs - invisibleGlyphCnt;
        int[] visibleGlyphCodes = new int[visibleGlyphCnt];
        float[] visiblePositions = new float[visibleGlyphCnt * 2];
        int index = 0;
        for (int i = 0; i < numGlyphs; i++) {
            if ((glyphCodes[i] & 0xffff) < CharToGlyphMapper.INVISIBLE_GLYPHS) {
                visibleGlyphCodes[index] = glyphCodes[i];
                visiblePositions[index * 2] = glyphPos[i * 2];
                visiblePositions[index * 2 + 1] = glyphPos[i * 2 + 1];
                index++;
            }
        }
        numGlyphs = visibleGlyphCnt;
        glyphCodes = visibleGlyphCodes;
        glyphPos = visiblePositions;
    }
    /* To get GDI to rotate glyphs we need to specify the angle
         * of rotation to GDI when creating the HFONT. This implicitly
         * also rotates the baseline, and this adjusts the X & Y advances
         * of the glyphs accordingly.
         * When we specify the advances, they are in device space, so
         * we don't want any further interpretation applied by GDI, but
         * since as noted the advances are interpreted in the HFONT's
         * coordinate space, our advances would be rotated again.
         * We don't have any way to tell GDI to rotate only the glyphs and
         * not the advances, so we need to account for this in the advances
         * we supply, by supplying unrotated advances.
         * Note that "iangle" is in the opposite direction to 2D's normal
         * direction of rotation, so this rotation inverts the
         * rotation element of the deviceTransform.
         */
    AffineTransform advanceTransform = AffineTransform.getScaleInstance(advanceScaleX, advanceScaleY);
    float[] glyphAdvPos = new float[glyphPos.length];
    //source
    advanceTransform.transform(//source
    glyphPos, //source
    0, //destination
    glyphAdvPos, //destination
    0, //num points
    glyphPos.length / 2);
    Font2D font2D = FontUtilities.getFont2D(font);
    if (font2D instanceof TrueTypeFont) {
        String family = font2D.getFamilyName(null);
        int style = font.getStyle() | font2D.getStyle();
        if (!wPrinterJob.setFont(family, scaledFontSizeY, style, iangle, awScale)) {
            return false;
        }
        wPrinterJob.glyphsOut(glyphCodes, devpos.x, devpos.y, glyphAdvPos);
    } else if (font2D instanceof CompositeFont) {
        /* Composite fonts are made up of multiple fonts and each
             * substring that uses a particular component font needs to
             * be separately sent to GDI.
             * This works for standard composite fonts, alternate ones,
             * Fonts that are a physical font backed by a standard composite,
             * and with fallback fonts.
             */
        CompositeFont compFont = (CompositeFont) font2D;
        float userx = x, usery = y;
        float devx = devpos.x, devy = devpos.y;
        int start = 0, end = 0, slot = 0;
        while (end < numGlyphs) {
            start = end;
            slot = glyphCodes[start] >>> 24;
            while (end < numGlyphs && ((glyphCodes[end] >>> 24) == slot)) {
                end++;
            }
            /* If we can't get the font, bail to outlines.
                 * But we should always be able to get all fonts for
                 * Composites, so this is unlikely, so any overstriking
                 * if only one slot is unavailable is not worth worrying
                 * about.
                 */
            PhysicalFont slotFont = compFont.getSlotFont(slot);
            if (!(slotFont instanceof TrueTypeFont)) {
                return false;
            }
            String family = slotFont.getFamilyName(null);
            int style = font.getStyle() | slotFont.getStyle();
            if (!wPrinterJob.setFont(family, scaledFontSizeY, style, iangle, awScale)) {
                return false;
            }
            int[] glyphs = Arrays.copyOfRange(glyphCodes, start, end);
            float[] posns = Arrays.copyOfRange(glyphAdvPos, start * 2, end * 2);
            if (start != 0) {
                Point2D.Float p = new Point2D.Float(x + glyphPos[start * 2], y + glyphPos[start * 2 + 1]);
                deviceTransform.transform(p, p);
                devx = p.x;
                devy = p.y;
            }
            wPrinterJob.glyphsOut(glyphs, devx, devy, posns);
        }
    } else {
        return false;
    }
    return true;
}
Also used : TrueTypeFont(sun.font.TrueTypeFont) CompositeFont(sun.font.CompositeFont) Font2D(sun.font.Font2D) TrueTypeFont(sun.font.TrueTypeFont) CompositeFont(sun.font.CompositeFont) Font(java.awt.Font) PhysicalFont(sun.font.PhysicalFont) Point2D(java.awt.geom.Point2D) PhysicalFont(sun.font.PhysicalFont) AffineTransform(java.awt.geom.AffineTransform)

Aggregations

AffineTransform (java.awt.geom.AffineTransform)2 Point2D (java.awt.geom.Point2D)2 CompositeFont (sun.font.CompositeFont)2 Font2D (sun.font.Font2D)2 PhysicalFont (sun.font.PhysicalFont)2 TrueTypeFont (sun.font.TrueTypeFont)2 Font (java.awt.Font)1 TextLayout (java.awt.font.TextLayout)1 Rectangle2D (java.awt.geom.Rectangle2D)1