001/*
002 * SVG Salamander
003 * Copyright (c) 2004, Mark McKay
004 * All rights reserved.
005 *
006 * Redistribution and use in source and binary forms, with or 
007 * without modification, are permitted provided that the following
008 * conditions are met:
009 *
010 *   - Redistributions of source code must retain the above 
011 *     copyright notice, this list of conditions and the following
012 *     disclaimer.
013 *   - Redistributions in binary form must reproduce the above
014 *     copyright notice, this list of conditions and the following
015 *     disclaimer in the documentation and/or other materials 
016 *     provided with the distribution.
017 *
018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
019 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
020 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
021 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
022 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
023 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
025 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
026 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
027 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
028 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
029 * OF THE POSSIBILITY OF SUCH DAMAGE. 
030 * 
031 * Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
032 * projects can be found at http://www.kitfox.com
033 *
034 * Created on February 20, 2004, 10:00 PM
035 */
036package com.kitfox.svg;
037
038import com.kitfox.svg.xml.StyleAttribute;
039import java.util.HashMap;
040
041/**
042 * Implements an embedded font.
043 *
044 * SVG specification: http://www.w3.org/TR/SVG/fonts.html
045 *
046 * @author Mark McKay
047 * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
048 */
049public class Font extends SVGElement
050{
051
052    public static final String TAG_NAME = "font";
053    int horizOriginX = 0;
054    int horizOriginY = 0;
055    int horizAdvX = -1;  //Must be specified
056    int vertOriginX = -1;  //Defaults to horizAdvX / 2
057    int vertOriginY = -1;  //Defaults to font's ascent
058    int vertAdvY = -1;  //Defaults to one 'em'.  See font-face
059    FontFace fontFace = null;
060    MissingGlyph missingGlyph = null;
061    final HashMap glyphs = new HashMap();
062
063    /**
064     * Creates a new instance of Font
065     */
066    public Font()
067    {
068    }
069
070    public String getTagName()
071    {
072        return TAG_NAME;
073    }
074
075    /**
076     * Called after the start element but before the end element to indicate
077     * each child tag that has been processed
078     */
079    public void loaderAddChild(SVGLoaderHelper helper, SVGElement child) throws SVGElementException
080    {
081        super.loaderAddChild(helper, child);
082
083        if (child instanceof Glyph)
084        {
085            glyphs.put(((Glyph) child).getUnicode(), child);
086        } else if (child instanceof MissingGlyph)
087        {
088            missingGlyph = (MissingGlyph) child;
089        } else if (child instanceof FontFace)
090        {
091            fontFace = (FontFace) child;
092        }
093    }
094
095    public void loaderEndElement(SVGLoaderHelper helper) throws SVGParseException
096    {
097        super.loaderEndElement(helper);
098
099        //build();
100
101        helper.universe.registerFont(this);
102    }
103
104    protected void build() throws SVGException
105    {
106        super.build();
107
108        StyleAttribute sty = new StyleAttribute();
109
110        if (getPres(sty.setName("horiz-origin-x")))
111        {
112            horizOriginX = sty.getIntValue();
113        }
114
115        if (getPres(sty.setName("horiz-origin-y")))
116        {
117            horizOriginY = sty.getIntValue();
118        }
119
120        if (getPres(sty.setName("horiz-adv-x")))
121        {
122            horizAdvX = sty.getIntValue();
123        }
124
125        if (getPres(sty.setName("vert-origin-x")))
126        {
127            vertOriginX = sty.getIntValue();
128        }
129
130        if (getPres(sty.setName("vert-origin-y")))
131        {
132            vertOriginY = sty.getIntValue();
133        }
134
135        if (getPres(sty.setName("vert-adv-y")))
136        {
137            vertAdvY = sty.getIntValue();
138        }
139    }
140
141    public FontFace getFontFace()
142    {
143        return fontFace;
144    }
145
146    public void setFontFace(FontFace face)
147    {
148        fontFace = face;
149    }
150
151    public MissingGlyph getGlyph(String unicode)
152    {
153        Glyph retVal = (Glyph) glyphs.get(unicode);
154        if (retVal == null)
155        {
156            return missingGlyph;
157        }
158        return retVal;
159    }
160
161    public int getHorizOriginX()
162    {
163        return horizOriginX;
164    }
165
166    public int getHorizOriginY()
167    {
168        return horizOriginY;
169    }
170
171    public int getHorizAdvX()
172    {
173        return horizAdvX;
174    }
175
176    public int getVertOriginX()
177    {
178        if (vertOriginX != -1)
179        {
180            return vertOriginX;
181        }
182        vertOriginX = getHorizAdvX() / 2;
183        return vertOriginX;
184    }
185
186    public int getVertOriginY()
187    {
188        if (vertOriginY != -1)
189        {
190            return vertOriginY;
191        }
192        vertOriginY = fontFace.getAscent();
193        return vertOriginY;
194    }
195
196    public int getVertAdvY()
197    {
198        if (vertAdvY != -1)
199        {
200            return vertAdvY;
201        }
202        vertAdvY = fontFace.getUnitsPerEm();
203        return vertAdvY;
204    }
205
206    /**
207     * Updates all attributes in this diagram associated with a time event. Ie,
208     * all attributes with track information.
209     *
210     * @return - true if this node has changed state as a result of the time
211     * update
212     */
213    public boolean updateTime(double curTime) throws SVGException
214    {
215        //Fonts can't change
216        return false;
217        /*
218         if (trackManager.getNumTracks() == 0) return false;
219        
220         //Get current values for parameters
221         StyleAttribute sty = new StyleAttribute();
222         boolean stateChange = false;
223        
224         if (getPres(sty.setName("horiz-origin-x")))
225         {
226         int newVal = sty.getIntValue();
227         if (newVal != horizOriginX)
228         {
229         horizOriginX = newVal;
230         stateChange = true;
231         }
232         }
233        
234         if (getPres(sty.setName("horiz-origin-y")))
235         {
236         int newVal = sty.getIntValue();
237         if (newVal != horizOriginY)
238         {
239         horizOriginY = newVal;
240         stateChange = true;
241         }
242         }
243        
244         if (getPres(sty.setName("horiz-adv-x")))
245         {
246         int newVal = sty.getIntValue();
247         if (newVal != horizAdvX)
248         {
249         horizAdvX = newVal;
250         stateChange = true;
251         }
252         }
253        
254         if (getPres(sty.setName("vert-origin-x")))
255         {
256         int newVal = sty.getIntValue();
257         if (newVal != vertOriginX)
258         {
259         vertOriginX = newVal;
260         stateChange = true;
261         }
262         }
263        
264         if (getPres(sty.setName("vert-origin-y")))
265         {
266         int newVal = sty.getIntValue();
267         if (newVal != vertOriginY)
268         {
269         vertOriginY = newVal;
270         stateChange = true;
271         }
272         }
273        
274         if (getPres(sty.setName("vert-adv-y")))
275         {
276         int newVal = sty.getIntValue();
277         if (newVal != vertAdvY)
278         {
279         vertAdvY = newVal;
280         stateChange = true;
281         }
282         }
283        
284         return shapeChange;
285         */
286    }
287}