001: /*
002:
003: Licensed to the Apache Software Foundation (ASF) under one or more
004: contributor license agreements. See the NOTICE file distributed with
005: this work for additional information regarding copyright ownership.
006: The ASF licenses this file to You under the Apache License, Version 2.0
007: (the "License"); you may not use this file except in compliance with
008: the License. You may obtain a copy of the License at
009:
010: http://www.apache.org/licenses/LICENSE-2.0
011:
012: Unless required by applicable law or agreed to in writing, software
013: distributed under the License is distributed on an "AS IS" BASIS,
014: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: See the License for the specific language governing permissions and
016: limitations under the License.
017:
018: */
019: package org.apache.batik.bridge;
020:
021: import java.lang.ref.SoftReference;
022: import java.text.AttributedCharacterIterator;
023: import java.util.Map;
024:
025: import org.apache.batik.gvt.font.GVTFont;
026: import org.apache.batik.gvt.font.GVTFontFace;
027: import org.apache.batik.gvt.font.GVTFontFamily;
028: import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
029: import org.apache.batik.util.SVGConstants;
030:
031: import org.w3c.dom.Element;
032: import org.w3c.dom.Node;
033: import org.w3c.dom.NodeList;
034:
035: /**
036: * A font family class for SVG fonts.
037: *
038: * @author <a href="mailto:bella.robinson@cmis.csiro.au">Bella Robinson</a>
039: * @version $Id: SVGFontFamily.java 489226 2006-12-21 00:05:36Z cam $
040: */
041: public class SVGFontFamily implements GVTFontFamily {
042:
043: public static final AttributedCharacterIterator.Attribute TEXT_COMPOUND_ID = GVTAttributedCharacterIterator.TextAttribute.TEXT_COMPOUND_ID;
044:
045: protected GVTFontFace fontFace;
046: protected Element fontElement;
047: protected BridgeContext ctx;
048: protected Boolean complex = null;
049:
050: /**
051: * Constructs an SVGFontFamily.
052: *
053: * @param fontFace The font face object that describes this font family.
054: * @param fontElement The element that contains the font data for this family.
055: * @param ctx The bridge context. This is required for lazily loading the
056: * font data at render time.
057: */
058: public SVGFontFamily(GVTFontFace fontFace, Element fontElement,
059: BridgeContext ctx) {
060: this .fontFace = fontFace;
061: this .fontElement = fontElement;
062: this .ctx = ctx;
063: }
064:
065: /**
066: * Returns the family name of this font.
067: *
068: * @return The font family name.
069: */
070: public String getFamilyName() {
071: return fontFace.getFamilyName();
072: }
073:
074: /**
075: * Returns the font-face associated with this font family.
076: *
077: * @return The font face.
078: */
079: public GVTFontFace getFontFace() {
080: return fontFace;
081: }
082:
083: /**
084: * Derives a GVTFont object of the correct size.
085: *
086: * @param size The required size of the derived font.
087: * @param aci The character iterator containing the text to be rendered
088: * using the derived font.
089: *
090: * @return The derived font.
091: */
092: public GVTFont deriveFont(float size,
093: AttributedCharacterIterator aci) {
094: return deriveFont(size, aci.getAttributes());
095: }
096:
097: /**
098: * Derives a GVTFont object of the correct size from an attribute Map.
099: * @param size The required size of the derived font.
100: * @param attrs The Attribute Map to get Values from.
101: */
102: public GVTFont deriveFont(float size, Map attrs) {
103: SVGFontElementBridge fontBridge;
104: fontBridge = (SVGFontElementBridge) ctx.getBridge(fontElement);
105: SoftReference sr = (SoftReference) attrs.get(TEXT_COMPOUND_ID);
106: Element textElement = (Element) sr.get();
107: return fontBridge.createFont(ctx, fontElement, textElement,
108: size, fontFace);
109: }
110:
111: /**
112: * This method looks at the SVG font and checks if any of
113: * the glyphs use renderable child elements. If so this
114: * is a complex font in that full CSS inheritance needs to
115: * be applied. Otherwise if it only uses the 'd' attribute
116: * it does not need CSS treatment.
117: */
118: public boolean isComplex() {
119: if (complex != null)
120: return complex.booleanValue();
121: boolean ret = isComplex(fontElement, ctx);
122: complex = ret ? Boolean.TRUE : Boolean.FALSE;
123: return ret;
124: }
125:
126: public static boolean isComplex(Element fontElement,
127: BridgeContext ctx) {
128: NodeList glyphElements = fontElement.getElementsByTagNameNS(
129: SVGConstants.SVG_NAMESPACE_URI,
130: SVGConstants.SVG_GLYPH_TAG);
131:
132: int numGlyphs = glyphElements.getLength();
133: for (int i = 0; i < numGlyphs; i++) {
134: Element glyph = (Element) glyphElements.item(i);
135: Node child = glyph.getFirstChild();
136: for (; child != null; child = child.getNextSibling()) {
137: if (child.getNodeType() != Node.ELEMENT_NODE)
138: continue;
139: Element e = (Element) child;
140: Bridge b = ctx.getBridge(e);
141: if ((b != null) && (b instanceof GraphicsNodeBridge)) {
142: return true;
143: }
144: }
145: }
146: return false;
147: }
148: }
|