Package org.apache.batik.bridge

Source Code of org.apache.batik.bridge.SVGGVTFont

/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved.        *
* ------------------------------------------------------------------------- *
* This software is published under the terms of the Apache Software License *
* version 1.1, a copy of which has been included with this distribution in  *
* the LICENSE file.                                                         *
*****************************************************************************/

package org.apache.batik.bridge;

import java.awt.Font;
import java.awt.font.FontRenderContext;
import java.awt.font.LineMetrics;
import java.awt.font.GlyphVector;
import java.text.CharacterIterator;
import java.text.StringCharacterIterator;
import java.text.AttributedCharacterIterator;
import java.util.Vector;
import java.util.StringTokenizer;
import org.w3c.dom.Element;
import org.apache.batik.gvt.text.ArabicTextHandler;
import org.apache.batik.gvt.text.AttributedCharacterSpanIterator;
import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
import org.apache.batik.gvt.font.GVTFont;
import org.apache.batik.gvt.font.GVTGlyphVector;
import org.apache.batik.gvt.font.SVGGVTGlyphVector;
import org.apache.batik.gvt.font.GVTLineMetrics;
import org.apache.batik.gvt.font.Glyph;
import org.apache.batik.gvt.font.Kern;
import org.apache.batik.gvt.font.KerningTable;
import org.apache.batik.util.SVGConstants;
import org.apache.batik.dom.util.XMLSupport;
import org.apache.batik.css.CSSOMReadOnlyStyleDeclaration;
import org.w3c.dom.css.CSSPrimitiveValue;
import org.w3c.dom.css.CSSStyleDeclaration;

/**
* Represents an SVG font.
*
* @author <a href="mailto:bella.robinson@cmis.csiro.au">Bella Robinson</a>
* @version $Id: SVGGVTFont.java,v 1.5 2001/07/05 06:56:08 bella Exp $
*/
public final class SVGGVTFont implements GVTFont, SVGConstants {

    private float fontSize;
    private SVGFontFace fontFace;
    private String[] glyphUnicodes;
    private String[] glyphNames;
    private String[] glyphLangs;
    private String[] glyphOrientations;
    private String[] glyphForms;
    private Element[] glyphElements;
    private Element[] hkernElements;
    private Element[] vkernElements;
    private BridgeContext ctx;
    private Element textElement;
    private Element missingGlyphElement;
    private KerningTable hKerningTable;
    private KerningTable vKerningTable;
    private String language;
    private String orientation;

    /**
     * Constructs a new SVGGVTFont of the specified size.
     *
     * @param fontSize The size of the font to create.
     * @param fontFace The font face that describes the font.
     * @param glyphUnicodes An array containing the unicode values for all
     * the glyphs this font can display.
     * @param glyphNames An array containing the names of all the glyphs this
     * font can display.
     * @param ctx The bridge context.
     * @param glyphElements An array containing the children glyph elements
     * of the SVG font.
     * @param missingGlyphElement The missing glyph element for this font.
     * @param hkernElements An array containing all hkern elements for this font.
     * @param vkernElements An array containing all vkern elements for this font.
     * @param textElement The text element that contains the text to be rendered
     * using this font.
     */
    public SVGGVTFont(float fontSize, SVGFontFace fontFace, String[] glyphUnicodes,
                      String[] glyphNames, String[] glyphLangs,
                      String[] glyphOrientations, String[] glyphForms,
                      BridgeContext ctx,
                      Element[] glyphElements,
                      Element missingGlyphElement,
                      Element[] hkernElements,
                      Element[] vkernElements,
                      Element textElement) {
        this.fontFace = fontFace;
        this.fontSize = fontSize;
        this.glyphUnicodes = glyphUnicodes;
        this.glyphNames = glyphNames;
        this.glyphLangs = glyphLangs;
        this.glyphOrientations = glyphOrientations;
        this.glyphForms = glyphForms;
        this.ctx = ctx;
        this.glyphElements = glyphElements;
        this.missingGlyphElement = missingGlyphElement;
        this.hkernElements = hkernElements;
        this.vkernElements = vkernElements;
        this.textElement = textElement;

        this.language = XMLSupport.getXMLLang(textElement);

        CSSOMReadOnlyStyleDeclaration cssDecl = CSSUtilities.getComputedStyle(textElement);
        CSSPrimitiveValue v = (CSSPrimitiveValue)cssDecl.getPropertyCSSValueInternal(CSS_WRITING_MODE_PROPERTY);
        if (v.getStringValue().startsWith(CSS_TB_VALUE)) {
            // top to bottom, so set orientation to "v"
            this.orientation = SVG_V_VALUE;
        } else {
            this.orientation = SVG_H_VALUE;
        }

        createKerningTables();
    }


    /**
     * Creates the kerning tables for this font. Two tables are created,
     * horizontal and vertical. If there are not children vkern or hkern
     * elements these tables will be empty.
     */
    private void createKerningTables() {

        Kern[] hEntries = new Kern[hkernElements.length];
        for (int i = 0; i < hkernElements.length; i++) {
            Element hkernElement = hkernElements[i];
            SVGHKernElementBridge hkernBridge = (SVGHKernElementBridge)ctx.getBridge(hkernElement);
            Kern hkern = hkernBridge.createKern(ctx, hkernElement, this);
            hEntries[i] = hkern;
        }
        hKerningTable = new KerningTable(hEntries);

        Kern[] vEntries = new Kern[vkernElements.length];
        for (int i = 0; i < vkernElements.length; i++) {
            Element vkernElement = vkernElements[i];
            SVGVKernElementBridge vkernBridge = (SVGVKernElementBridge)ctx.getBridge(vkernElement);
            Kern vkern = vkernBridge.createKern(ctx, vkernElement, this);
            vEntries[i] = vkern;
        }
        vKerningTable = new KerningTable(vEntries);

    }

    /**
     * Returns the horizontal kerning value for the specified glyph pair.
     * This will be zero if there is no explicit horizontal kerning value
     * for this particular glyph pair.
     *
     * @param glyphCode1 The id of the first glyph.
     * @param glyphCode2 The id of the second glyph.
     *
     * @return The horizontal kerning value.
     */
    public float getHKern(int glyphCode1, int glyphCode2) {
        if (glyphCode1 < 0 || glyphCode1 >= glyphUnicodes.length
            || glyphCode2 < 0 || glyphCode2 >= glyphUnicodes.length) {
            return 0f;
        }
        return hKerningTable.getKerningValue(glyphCode1, glyphCode2,
                glyphUnicodes[glyphCode1], glyphUnicodes[glyphCode2]);
    }

    /**
     * Returns the vertical kerning value for the specified glyph pair.
     * This will be zero if there is no explicit vertical kerning value for
     * for this particular glyph pair.
     *
     * @param glyphCode1 The id of the first glyph.
     * @param glyphCode2 The id of the second glyph.
     *
     * @return The vertical kerning value.
     */
    public float getVKern(int glyphCode1, int glyphCode2) {
        if (glyphCode1 < 0 || glyphCode1 >= glyphUnicodes.length
            || glyphCode2 < 0 || glyphCode2 >= glyphUnicodes.length) {
            return 0f;
        }
        return vKerningTable.getKerningValue(glyphCode1, glyphCode2,
                glyphUnicodes[glyphCode1], glyphUnicodes[glyphCode2]);
    }

    /**
     * Returns an array of glyph codes (unique ids) of the glyphs with the
     * specified name (there may be more than one).
     *
     * @param name The name of the glyph.
     *
     * @return An array of matching glyph codes. This may be empty.
     */
    public int[] getGlyphCodesForName(String name) {
        Vector glyphCodes = new Vector();
        for (int i = 0; i < glyphNames.length; i++) {
            if (glyphNames[i] != null && glyphNames[i].equals(name)) {
                glyphCodes.add(new Integer(i));
            }
        }
        int[] glyphCodeArray = new int[glyphCodes.size()];
        for (int i = 0; i < glyphCodes.size(); i++) {
            glyphCodeArray[i] = ((Integer)glyphCodes.elementAt(i)).intValue();
        }
        return glyphCodeArray;
    }

    /**
     * Returns an array of glyph codes (unique ids) of the glyphs with the
     * specified unicode value (there may be more than one).
     *
     * @param unicode The unicode value of the glyph.
     *
     * @return An array of matching glyph codes. This may be empty.
     */
    public int[] getGlyphCodesForUnicode(String unicode) {
        Vector glyphCodes = new Vector();
        for (int i = 0; i < glyphUnicodes.length; i++) {
            if (glyphUnicodes[i] != null && glyphUnicodes[i].equals(unicode)) {
                glyphCodes.add(new Integer(i));
            }
        }
        int[] glyphCodeArray = new int[glyphCodes.size()];
        for (int i = 0; i < glyphCodes.size(); i++) {
            glyphCodeArray[i] = ((Integer)glyphCodes.elementAt(i)).intValue();
        }
        return glyphCodeArray;
    }

    /**
     * Returns true if the glyph language matches the language of the text node
     * to be rendered by this font.  This will be the case if one of the
     * languages in glyphLang matches exactly with the xml:lang attibute of
     * the text node, or if the xml:lang attribute exactly equals a prefix of one
     * glyph languages.
     *
     * @param glyphLang A comma separated list of languages that are associated
     * with a glyph.
     *
     * @return Whether or not the glyph language matches the language of the
     * text node.
     */
    private boolean languageMatches(String glyphLang) {
        if (glyphLang == null || glyphLang.length() == 0) {
            return true// will match all languages
        }
        StringTokenizer st = new StringTokenizer(glyphLang, ",");
        while (st.hasMoreTokens()) {
            String s = st.nextToken();
            if (s.equals(language)
               || (s.startsWith(language) && s.length() > language.length()
                   && s.charAt(language.length()) == '-')) {
                return true;
            }
        }
        return false;
    }

    /**
     * Returns true if the glyph orientation matches the orientation of the
     * text node to be rendered by this font.
     *
     * @param glyphOrientation The glyph orientation attribute value. Will be
     * "h", "v" or empty.
     *
     * @return Whether or not the glyph orientation matches the text to be
     * rendered by this font object.
     */
    private boolean orientationMatches(String glyphOrientation) {
        if (glyphOrientation == null || glyphOrientation.length() == 0) {
            return true;
        }
        return glyphOrientation.equals(orientation);
    }


    /**
     * Returns true if the glyph form matches that of the current character in
     * the aci.
     *
     * @param gyphUnicode The unicode value of the glyph.
     * @param glyphForm The arabic-form glyph attribute.
     * @param aci The aci containing the character to check.
     * @param currentIndex The index of the character to check.
     */
    private boolean formMatches(String glyphUnicode, String glyphForm,
                                AttributedCharacterIterator aci, int currentIndex) {
        if (aci == null || glyphForm == null || glyphForm.length() == 0) {
            // there aren't any attributes attached to the text
            // or the glyph doesn't have an arabic form
            return true;
        }

        char c = aci.setIndex(currentIndex);
        Integer form = (Integer)aci.getAttribute(GVTAttributedCharacterIterator.TextAttribute.ARABIC_FORM);

        if (form == null || form.equals(GVTAttributedCharacterIterator.TextAttribute.ARABIC_NONE)) {
            // the glyph has an arabic form and the current character form is "none" so don't match
            return false;
        }

        // see if c is the start of an arabic ligature
        if (glyphUnicode.length() > 1) {

            boolean matched = true;
            for (int j = 1; j < glyphUnicode.length(); j++) {
                c = aci.next();
                if (glyphUnicode.charAt(j) != c) {
                    matched = false;
                    break;
                }
            }

            // reset the aci
            aci.setIndex(currentIndex);

            if (matched) {

                // ligature matches, now check that the arabic forms are ok
                char lastChar = aci.setIndex(currentIndex + glyphUnicode.length() - 1);
                Integer lastForm = (Integer)aci.getAttribute(
                    GVTAttributedCharacterIterator.TextAttribute.ARABIC_FORM);

                // reset the aci again
                aci.setIndex(currentIndex);

                if (form != null && lastForm != null) {
                    if (form.equals(GVTAttributedCharacterIterator.TextAttribute.ARABIC_TERMINAL)
                        && lastForm.equals(GVTAttributedCharacterIterator.TextAttribute.ARABIC_INITIAL)) {
                        // return true if the glyph form is isolated
                        return glyphForm.equals(SVGConstants.SVG_ISOLATED_VALUE);

                    } else if (form.equals(GVTAttributedCharacterIterator.TextAttribute.ARABIC_TERMINAL)) {
                        // return true if the glyph form is terminal
                        return glyphForm.equals(SVGConstants.SVG_TERMINAL_VALUE);

                    } else if (form.equals(GVTAttributedCharacterIterator.TextAttribute.ARABIC_MEDIAL)
                            && lastForm.equals(GVTAttributedCharacterIterator.TextAttribute.ARABIC_MEDIAL)) {
                        // return true if the glyph form is medial
                        return glyphForm.equals(SVGConstants.SVG_MEDIAL_VALUE);
                    }
                    // should test for other combos as well here
                }
            }
        }

        if (form.equals(GVTAttributedCharacterIterator.TextAttribute.ARABIC_ISOLATED)) {
            return glyphForm.equals(SVGConstants.SVG_ISOLATED_VALUE);
        }
        if (form.equals(GVTAttributedCharacterIterator.TextAttribute.ARABIC_TERMINAL)) {
            return glyphForm.equals(SVGConstants.SVG_TERMINAL_VALUE);
        }
        if (form.equals(GVTAttributedCharacterIterator.TextAttribute.ARABIC_INITIAL)) {
            return glyphForm.equals(SVGConstants.SVG_INITIAL_VALUE);
        }
        if (form.equals(GVTAttributedCharacterIterator.TextAttribute.ARABIC_MEDIAL)) {
            return glyphForm.equals(SVGConstants.SVG_MEDIAL_VALUE);
        }
        return false;
    }

    /**
     * Indicates whether or not the specified glyph can be displayed by this
     * font.
     *
     * @param name The name of the glyph to check.
     *
     * @return True if the glyph can be displayed.
     */
    public boolean canDisplayGivenName(String name) {
        for (int i = 0; i < glyphNames.length; i++) {
            if (glyphNames[i] != null && glyphNames[i].equals(name)
                && languageMatches(glyphLangs[i])
                && orientationMatches(glyphOrientations[i])) {
                return true;
            }
        }
        return false;
    }


    /**
     * Indicates whether or not the specified character can be displayed by this
     * font.
     *
     * @param c The character to check.
     *
     * @param True if the character can be displayed.
     */
    public boolean canDisplay(char c) {
        for (int i = 0; i < glyphUnicodes.length; i++) {
            if (glyphUnicodes[i].indexOf(c) != -1
                && languageMatches(glyphLangs[i])
                && orientationMatches(glyphOrientations[i])) {
                return true;
            }
        }
        return false;
    }

    /**
     * Checks whether this Font can display the characters in the
     * specified character array starting at start and ending at limit.
     *
     * @param text An array containing the characters to check.
     * @param start The index of the first character to check.
     * @param limit The index of the last character to check.
     *
     * @return The index of the first character it can't display or -1 if
     * it can display the whole string.
     */
    public int canDisplayUpTo(char[] text, int start, int limit) {
        StringCharacterIterator sci = new StringCharacterIterator(new String(text));
        return canDisplayUpTo(sci, start, limit);
    }

    /**
     * Checks whether this Font can display the characters in the
     * specified character iterator starting at start and ending at limit.
     *
     * @param iter The iterator containing the characters to check.
     * @param start The index of the first character to check.
     * @param limit The index of the last character to check.
     *
     * @return The index of the first character it can't display or -1 if
     * it can display the whole string.
     */
    public int canDisplayUpTo(CharacterIterator iter, int start, int limit) {

        AttributedCharacterIterator aci = null;
        if (iter instanceof AttributedCharacterIterator) {
            aci = (AttributedCharacterIterator)iter;
        }

        char c = iter.setIndex(start);
        int currentIndex = start;

        while (c != iter.DONE && currentIndex < limit) {

            boolean foundMatchingGlyph = false;

            for (int i = 0; i < glyphUnicodes.length; i++) {
                if (glyphUnicodes[i].indexOf(c) == 0
                    && languageMatches(glyphLangs[i])
                    && orientationMatches(glyphOrientations[i])
                    && formMatches(glyphUnicodes[i], glyphForms[i], aci, currentIndex)) {  // found a possible match

                    if (glyphUnicodes[i].length() == 1)  { // not a ligature
                        foundMatchingGlyph = true;
                        break;

                    } else {
                        // glyphCodes[i] is a ligature so try and
                        // match the rest of the glyphCode chars
                        boolean matched = true;
                        for (int j = 1; j < glyphUnicodes[i].length(); j++) {
                            c = iter.next();
                            if (glyphUnicodes[i].charAt(j) != c) {
                                matched = false;
                                break;
                            }
                        }
                        if (matched) { // found a matching ligature!
                            foundMatchingGlyph = true;
                            break;

                        } else {
                            // did not match ligature, keep looking for another glyph
                            c = iter.setIndex(currentIndex);
                        }
                    }
                }
            }
            if (!foundMatchingGlyph) {
                return currentIndex;
            }
            c = iter.next();
            currentIndex = iter.getIndex();
        }
        return -1;
    }

    /**
     * Checks whether or not this font can display the characters in the
     * specified String.
     *
     * @param str The string containing the characters to check.
     *
     * @return The index of the first character it can't display or -1 if
     * it can display the whole string.
     */
    public int canDisplayUpTo(String str) {
        StringCharacterIterator sci = new StringCharacterIterator(str);
        return canDisplayUpTo(sci, 0, str.length());
    }

    /**
     * Returns a new GVTGlyphVector object for the specified array of
     * characters.
     *
     * @param frc The current font render context.
     * @param chars The array of chars that the glyph vector will represent.
     *
     * @return The new glyph vector.
     */
    public GVTGlyphVector createGlyphVector(FontRenderContext frc,
                                            char[] chars) {
         StringCharacterIterator sci = new StringCharacterIterator(new String(chars));
         return createGlyphVector(frc, sci);
    }

    /**
     * Returns a new GVTGlyphVector object for the characters in the
     * specified character iterator.
     *
     * @param frc The current font render context.
     * @param ci The character iterator that the glyph vector will represent.
     *
     * @return The new glyph vector.
     */
    public GVTGlyphVector createGlyphVector(FontRenderContext frc,
                                            CharacterIterator ci) {

        AttributedCharacterIterator aci = null;
        if (ci instanceof AttributedCharacterIterator) {
            aci = (AttributedCharacterIterator)ci;
        }

        Vector glyphs = new Vector();
        char c = ci.first();
        while (c != ci.DONE) {
            boolean foundMatchingGlyph = false;
            for (int i = 0; i < glyphUnicodes.length; i++) {
                if (glyphUnicodes[i].indexOf(c) == 0
                    && languageMatches(glyphLangs[i])
                    && orientationMatches(glyphOrientations[i])
                    && formMatches(glyphUnicodes[i], glyphForms[i], aci, ci.getIndex())) {  // found a possible match

                    if (glyphUnicodes[i].length() == 1)  { // not a ligature
                        Element glyphElement = glyphElements[i];
                        SVGGlyphElementBridge glyphBridge
                            = (SVGGlyphElementBridge)ctx.getBridge(glyphElement);
                        Glyph glyph = glyphBridge.createGlyph(
                            ctx, glyphElement, textElement, i, fontSize, fontFace);
                        glyphs.add(glyph);
                        foundMatchingGlyph = true;
                        break;

                    } else {
                        // glyphCodes[i] is a ligature so try and
                        // match the rest of the glyphCode chars
                        int current = ci.getIndex();
                        boolean matched = true;
                        for (int j = 1; j < glyphUnicodes[i].length(); j++) {
                            c = ci.next();
                            if (glyphUnicodes[i].charAt(j) != c) {
                                matched = false;
                                break;
                            }
                        }
                        if (matched) { // found a matching ligature!

                            Element glyphElement = glyphElements[i];
                            SVGGlyphElementBridge glyphBridge
                                = (SVGGlyphElementBridge)ctx.getBridge(glyphElement);
                            Glyph glyph = glyphBridge.createGlyph(
                                ctx, glyphElement, textElement, i, fontSize, fontFace);
                            glyphs.add(glyph);
                            foundMatchingGlyph = true;
                            break;

                        } else {
                            // did not match ligature, keep looking for another glyph
                            c = ci.setIndex(current);
                        }
                    }
                }
            }
            if (!foundMatchingGlyph) {
                // add the missing glyph
                SVGGlyphElementBridge glyphBridge
                    = (SVGGlyphElementBridge)ctx.getBridge(missingGlyphElement);
                Glyph glyph = glyphBridge.createGlyph(
                    ctx, missingGlyphElement, textElement, -1, fontSize, fontFace);
                glyphs.add(glyph);

            }
            c = ci.next();
        }

        // turn the vector of glyphs into an array;
        int numGlyphs = glyphs.size();
        Glyph[] glyphArray = new Glyph[numGlyphs];
        for (int i =0; i < numGlyphs; i++) {
            glyphArray[i] = (Glyph)glyphs.get(i);
        }
        // return a new SVGGVTGlyphVector
        return new SVGGVTGlyphVector(this, glyphArray, frc);
    }

    /**
     * Returns a new GVTGlyphVector object for the glyphs in the
     * the glyph code array.
     *
     * @param frc The current font render context.
     * @param glyphCodes An array containin the ids of the glyphs that
     * the glyph vector will represent.
     *
     * @return The new glyph vector.
     */
    public GVTGlyphVector createGlyphVector(FontRenderContext frc,
                                            int[] glyphCodes,
                                            CharacterIterator ci) {
        // costruct a string from the glyphCodes
        String str = "";
        for (int i = 0; i < glyphCodes.length; i++) {
            str += glyphUnicodes[glyphCodes[i]];
        }
        StringCharacterIterator sci = new StringCharacterIterator(str);
        return createGlyphVector(frc, sci);
    }

    /**
     * Returns a new GVTGlyphVector object for the specified String.
     *
     * @param frc The current font render context.
     * @param str The string that the glyph vector will represent.
     *
     * @return The new glyph vector.
     */
    public GVTGlyphVector createGlyphVector(FontRenderContext frc, String str) {
        StringCharacterIterator sci = new StringCharacterIterator(str);
        return createGlyphVector(frc, sci);
    }

    /**
     * Creates a new GVTFont object by replicating this font object and
     * applying a new size to it.
     *
     * @param size The size of the new font.
     *
     * @param return The new font object.
     */
    public GVTFont deriveFont(float size) {
        return new SVGGVTFont(size, fontFace, glyphUnicodes, glyphNames,
                              glyphLangs, glyphOrientations, glyphForms, ctx,
                              glyphElements, missingGlyphElement, hkernElements,
                              vkernElements, textElement);
    }

    /**
     * Returns the line metrics for the specified text.
     *
     * @param chars The character array containing the text.
     * @param beginIndex The index of the first character.
     * @param limit The limit of characters.
     * @param frc The current font render context.
     *
     * @return The new GVTLineMetrics object.
     */
    public GVTLineMetrics getLineMetrics(char[] chars, int beginIndex, int limit,
                                         FontRenderContext frc) {
        StringCharacterIterator sci = new StringCharacterIterator(new String(chars));
        return getLineMetrics(sci, beginIndex, limit, frc);
    }

    /**
     * Returns the line metrics for the specified text.
     *
     * @param ci The character iterator containing the text.
     * @param beginIndex The index of the first character.
     * @param limit The limit of characters.
     * @param frc The current font render context.
     *
     * @return The new GVTLineMetrics object.
     */
    public GVTLineMetrics getLineMetrics(CharacterIterator ci, int beginIndex,
                                         int limit, FontRenderContext frc) {

        // first create the character iterator that represents the subset
        // from beginIndex to limit
        String s = "";
        char c = ci.setIndex(beginIndex);
        int currentIndex = beginIndex;

        while (c != ci.DONE && currentIndex < limit) {
            s += c;
            currentIndex++;
            c = ci.next();
        }

        StringCharacterIterator sci = new StringCharacterIterator(s);
        GVTGlyphVector gv = createGlyphVector(frc, sci);

        float fontHeight = fontFace.getUnitsPerEm();
        float scale = fontSize/fontHeight;

        float ascent = fontFace.getAscent() * scale;
        float descent = fontFace.getDescent() * scale;

        int numGlyphs = gv.getNumGlyphs();

        float[] baselineOffsets = new float[numGlyphs];
        for (int i = 0; i < numGlyphs; i++) {
            baselineOffsets[i] = (float)( gv.getGlyphMetrics(i).getBounds2D().getMaxY()
                                - gv.getGlyphPosition(i).getY());
        }

        float strikethroughOffset = fontFace.getStrikethroughPosition() * -scale;
        float strikethroughThickness = fontFace.getStrikethroughThickness() * scale;
        float underlineOffset = fontFace.getUnderlinePosition() * scale;
        float underlineThickness = fontFace.getUnderlineThickness() * scale;
        float overlineOffset = fontFace.getOverlinePosition() * -scale;
        float overlineThickness = fontFace.getOverlineThickness() * scale;


        return new GVTLineMetrics(ascent, Font.ROMAN_BASELINE, baselineOffsets, descent,
                                  fontHeight, fontHeight, numGlyphs, strikethroughOffset,
                                  strikethroughThickness, underlineOffset,
                                  underlineThickness, overlineOffset, overlineThickness);
    }

    /**
     * Returns the line metrics for the specified text.
     *
     * @param str The string containing the text.
     * @param frc The current font render context.
     *
     * @return The new GVTLineMetrics object.
     */
    public GVTLineMetrics getLineMetrics(String str, FontRenderContext frc) {
        StringCharacterIterator sci = new StringCharacterIterator(str);
        return getLineMetrics(sci, 0, str.length(), frc);
    }

    /**
     * Returns the line metrics for the specified text.
     *
     * @param str The string containing the text.
     * @param beginIndex The index of the first character.
     * @param limit The limit of characters.
     * @param frc The current font render context.
     *
     * @return The new GVTLineMetrics object.
     */
    public GVTLineMetrics getLineMetrics(String str, int beginIndex, int limit,
                                         FontRenderContext frc) {
        StringCharacterIterator sci = new StringCharacterIterator(str);
        return getLineMetrics(sci, beginIndex, limit, frc);
    }

    /**
     * Returns the size of this font.
     *
     * @return The font size.
     */
    public float getSize() {
        return fontSize;
    }

    /**
     * Returns a string representation of this font.
     * This is for debugging purposes only.
     *
     * @return A string representation of this font.
     */
    public String toString() {
        return fontFace.getFamilyName() + " " + fontFace.getFontWeight() + " "
              + fontFace.getFontStyle();
    }
}

TOP

Related Classes of org.apache.batik.bridge.SVGGVTFont

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.