Package flash.swf.builder.tags

Source Code of flash.swf.builder.tags.FontBuilder$SWFFontNotSupportedException

/*
*
*  Licensed to the Apache Software Foundation (ASF) under one or more
*  contributor license agreements.  See the NOTICE file distributed with
*  this work for additional information regarding copyright ownership.
*  The ASF licenses this file to You under the Apache License, Version 2.0
*  (the "License"); you may not use this file except in compliance with
*  the License.  You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*
*/

package flash.swf.builder.tags;

import flash.fonts.FontFace;
import flash.fonts.FontManager;
import flash.fonts.FSType;
import flash.swf.Tag;
import flash.swf.TagValues;
import flash.swf.builder.types.ZoneRecordBuilder;
import flash.swf.tags.DefineFont2;
import flash.swf.tags.DefineFont3;
import flash.swf.tags.DefineTag;
import flash.swf.tags.DefineFontName;
import flash.swf.tags.DefineFontAlignZones;
import flash.swf.tags.ZoneRecord;
import flash.swf.types.GlyphEntry;
import flash.swf.types.KerningRecord;
import flash.swf.types.Rect;
import flash.swf.types.Shape;
import flash.util.IntMap;
import flash.util.Trace;

import java.net.URL;
import java.util.Iterator;
import java.util.Map;

/**
* A utility class to build a DefineFont2 or DefineFont3 tag.  One
* must supply a font family name and style to establish a default
* font face and a <code>FontManager</code> to locate and cache fonts
* and glyphs.
*
* @author Peter Farland
*/
@SuppressWarnings("unchecked")
public final class FontBuilder implements TagBuilder
{
    public DefineFont2 tag;

    private boolean flashType;
    private IntMap glyphEntryMap; // Code-point ordered collection of glyphs
    private FontFace defaultFace;
    private double fontHeight;
    private ZoneRecordBuilder zoneRecordBuilder;

    private static final Rect IDENTITY_RECT = new Rect();
    private static boolean useLicenseTag = true;

    private FontBuilder(int code, boolean hasLayout, boolean useFlashType)
    {
        if (code == Tag.stagDefineFont2)
            tag = new DefineFont2();
        else if (code == Tag.stagDefineFont3)
            tag = new DefineFont3();
        else
            throw new SWFFontNotSupportedException("Cannot build DefineFont for SWF tag code " + code);

        tag.hasLayout = hasLayout;
        glyphEntryMap = new IntMap(100); //Sorted by code point order
      flashType = useFlashType;
    }

    /**
     * Build a DefineFont2 or DefineFont3 tag for a given FontFace.
     *
     * Note that with this constructor, hasLayout is assumed to be true
     * but flashType is assumed to be false.
     *
     * @param code Determines the version of DefineFont SWF tag to use.
     * @param fontFace The FontFace to build into a DefineFont tag.
     * @param alias The name used to bind a DefineFont tag to other SWF tags
     * (such as DefineEditText).
     * @deprecated
     */
    public FontBuilder(int code, FontFace fontFace, String alias)
    {
       this(code, fontFace, alias, false);
    }

    /**
     * Build a DefineFont2 or DefineFont3 tag for a given FontFace.
     *
     * Note that with this constructor, hasLayout is assumed to be true.
     *
     * @param code Determines the version of DefineFont SWF tag to use.
     * @param fontFace The FontFace to build into a DefineFont tag.
     * @param alias The name used to bind a DefineFont tag to other SWF tags
     * (such as DefineEditText).
     */
    public FontBuilder(int code, FontFace fontFace, String alias, boolean flashType)
    {
        this(code, true, flashType);
        defaultFace = fontFace;

        if (Trace.font)
            Trace.trace("Initializing font '" + fontFace.getFamily() + "' as '" + alias + "'");

        init(alias);
    }
   
    /**
     * Build a DefineFont2 or DefineFont3 tag from a system font by family name.
     *
     * @param code Determines the version of DefineFont SWF tag to use.
     * @param manager A FontManager resolves the fontFamily and style to
     * a FontFace.
     * @param alias The name used to bind a DefineFont tag to other SWF tags
     * (such as DefineEditText).
     * @param fontFamily The name of the font family.
     * @param style An integer describing the style variant of the FontFace,
     * either plain, bold, italic, or bolditalic.
     * @param hasLayout Determines whether font layout metrics should be encoded.
     * @param flashType Determines whether FlashType advanced anti-aliasing
     * information should be included.
     */
    public FontBuilder(int code, FontManager manager, String alias,
            String fontFamily, int style, boolean hasLayout, boolean flashType)
    {
        this(code, hasLayout, flashType);

        if (manager == null)
            throw new NoFontManagerException();

        if (Trace.font)
            Trace.trace("Locating font using FontManager '" + manager.getClass().getName() + "'");

      boolean useTwips = code != TagValues.stagDefineFont && code != TagValues.stagDefineFont2;
        FontFace fontFace = manager.getEntryFromSystem(fontFamily, style, useTwips);

        if (fontFace == null)
            FontManager.throwFontNotFound(alias, fontFamily, style, null);

        if (Trace.font)
            Trace.trace("Initializing font '" + fontFamily + "' as '" + alias + "'");

        defaultFace = fontFace;

        init(alias);
    }

    /**
     * Load a font from a URL
     *
     * @param code
     * @param alias The name used to bind a DefineFont tag to a DefineEditText tag.
     * @param location remote url or a relative, local file path
     * @param style
     * @param hasLayout
     */
    public FontBuilder(int code, FontManager manager, String alias,
            URL location, int style, boolean hasLayout, boolean flashType)
    {
        this(code, hasLayout, flashType);

        if (manager == null)
            throw new NoFontManagerException();

        if (Trace.font)
            Trace.trace("Locating font using FontManager '" + manager.getClass().getName() + "'");

      boolean useTwips = code != TagValues.stagDefineFont && code != TagValues.stagDefineFont2;
        FontFace fontFace = manager.getEntryFromLocation(location, style, useTwips);

        if (fontFace == null)
            FontManager.throwFontNotFound(alias, null, style, location.toString());

        if (Trace.font)
            Trace.trace("Initializing font at '" + location.toString() + "' as '" + alias + "'");

        this.defaultFace = fontFace;

        init(alias);
    }

    private void init(String alias)
    {
        fontHeight = defaultFace.getPointSize();

        if (tag.code != Tag.stagDefineFont)
        {
            tag.fontName = alias;
            tag.bold = defaultFace.isBold();
            tag.italic = defaultFace.isItalic();

            if (tag.hasLayout)
            {
                tag.ascent = defaultFace.getAscent();
                tag.descent = defaultFace.getDescent();
                tag.leading = defaultFace.getLineGap();

                if (Trace.font)
                {
                    Trace.trace("\tBold: " + tag.bold);
                    Trace.trace("\tItalic: " + tag.italic);
                    Trace.trace("\tAscent: " + tag.ascent);
                    Trace.trace("\tDescent: " + tag.descent);
                    Trace.trace("\tLeading: " + tag.leading);
                }
            }
        }

        // If flashType enabled we must have z, Z, l, L
        if (flashType)
        {
            GlyphEntry adfGE = defaultFace.getGlyphEntry('z');
            if (adfGE == null)
                flashType = false;

            adfGE = defaultFace.getGlyphEntry('Z');
            if (adfGE == null)
                flashType = false;

            adfGE = defaultFace.getGlyphEntry('l');
            if (adfGE == null)
                flashType = false;

            adfGE = defaultFace.getGlyphEntry('L');
            if (adfGE == null)
                flashType = false;
        }

        if (flashType)
        {
            zoneRecordBuilder = ZoneRecordBuilder.createInstance();
            if (zoneRecordBuilder != null)
            {
                zoneRecordBuilder.setFontAlias(alias);
                zoneRecordBuilder.setFontBuilder(this);
                zoneRecordBuilder.setFontFace(defaultFace);
            }
            else
            {
                // FlashType Zone Records are not available, so we should
                // disable flashType
                flashType = false;
            }
        }

        addChar(' '); // Add at least a space char by default
    }

    /**
     * Creates a DefineFont2 or DefineFont3 tag depending on the code specified
     * on construction.
     */
    public DefineTag build()
    {
        int count = glyphEntryMap.size();

        if (Trace.font)
            Trace.trace("Building font '" + tag.fontName + "' with " + count + " characters.");

      if (flashType && tag instanceof DefineFont3)
      {
          DefineFont3 df3 = (DefineFont3)tag;
          df3.zones = new DefineFontAlignZones();
          df3.zones.font = df3;
          df3.zones.zoneTable = new ZoneRecord[count];
        df3.zones.csmTableHint = 1;
      }

        tag.glyphShapeTable = new Shape[count];

        if (tag.code != Tag.stagDefineFont)
        {
            tag.codeTable = new char[count];

            if (tag.hasLayout)
            {
                tag.advanceTable = new short[count];
                tag.boundsTable = new Rect[count];
            }
        }

        // Process each GlyphEntry
        Iterator it = glyphEntryMap.iterator();
        int i = 0;

      // long flashTypeTime = 0;
        while (it.hasNext() && i < count)
        {
            GlyphEntry ge = (GlyphEntry)((Map.Entry)it.next()).getValue();

            if (flashType && tag instanceof DefineFont3)
            {
                ((DefineFont3)tag).zones.zoneTable[i] = ge.zoneRecord;
            }

            // Note: offsets to shape table entries calculated on encoding
            tag.glyphShapeTable[i] = ge.shape;

            // IMPORTANT! Update GlyphEntry Index
            ge.setIndex(i);

            // DEFINEFONT2/3 specific properties
            if (tag.code != Tag.stagDefineFont)
            {
                tag.codeTable[i] = ge.character; // unsigned code point

                // Layout information
                if (tag.hasLayout)
                {
                    tag.advanceTable[i] = (short)ge.advance; //advance in emScale
                  // The player doesn't need ge.bounds, so we ignore it.
                    // We must still generate this value, however, for ADF use.
                    tag.boundsTable[i] = IDENTITY_RECT;
                }
                else
                {
                    if (Trace.font)
                        Trace.trace("Warning: font tag created without layout information.");
                }
            }

            i++;
        }

        if (tag.hasLayout)
        {
            tag.kerningTable = new KerningRecord[0];
        }

      // FIXME: we should allow the user to set the language code
      //tag.langCode = 1;

      // if we have any license info, create a DefineFontName tag
      if (useLicenseTag && ((getFSType() != null && ! getFSType().installable) || getCopyright() != null || getName() != null))
      {
        tag.license = new DefineFontName();
        tag.license.font = tag;
        tag.license.fontName = getName();
        tag.license.copyright = getCopyright();
      }

       return tag;
    }

    /**
     * Adds all supported characters from 0 to the highest glyph
     * contained in the default font face.
     */
    public void addAllChars()
    {
        addAllChars(defaultFace);
    }

    /**
     * Adds all supported characters from 0 to the highest glyph
     * contained in the given font face.
     *
     * @param face
     */
    public void addAllChars(FontFace face)
    {
        int min = face.getFirstChar();
        int count = face.getNumGlyphs();

        if (Trace.font)
            Trace.trace("\tAdding " + count + " chars, starting from " + min);

        addCharset(min, count);
    }

    /**
     * Adds supported characters in the specified range from the default
     * font face.
     *
     * @param fromChar
     * @param count
     */
    public void addCharset(int fromChar, int count)
    {
        addCharset(defaultFace, fromChar, count);
    }

    /**
     * Adds supported characters in the specified range from the given
     * font face.
     *
     * @param face
     * @param fromChar
     * @param count
     */
    public void addCharset(FontFace face, int fromChar, int count)
    {
        int remaining = count;

        for (int i = fromChar; remaining > 0 && i < Character.MAX_VALUE; i++)
        {
            char c = (char)i;
            GlyphEntry ge = addChar(face, c);
            if (ge != null)
            {
              remaining--;
            }
        }
    }

  /**
   * Adds all supported characters in the given array from the
   * default font face.
   *
   * @param chars
   */
  public void addCharset(char[] chars)
  {
      addCharset(defaultFace, chars);
  }

    /**
     * Adds all supported characters in array from the given font face.
     *
     * @param face
     * @param chars
     */
    public void addCharset(FontFace face, char[] chars)
    {
        //TODO: Sort before adding to optimize IntMap addition
        for (int i = 0; i < chars.length; i++)
        {
            char c = chars[i];
            addChar(face, c);
        }
    }

    /**
     * If supported, includes a given character from the default font face.
     *
     * @param c
     */
    public void addChar(char c)
    {
        addChar(defaultFace, c);
    }

    /**
     * If supported, includes a character from the given font face.
     *
     * @param c
     */
    public GlyphEntry addChar(FontFace face, char c)
    {
        GlyphEntry ge = (GlyphEntry)glyphEntryMap.get(c);

        if (ge == null)
        {
            ge = face.getGlyphEntry(c);

            if (ge != null)
            {
                //Add to this tag's collection
                glyphEntryMap.put(c, ge);
            }
        }

        if (flashType && ge != null && ge.zoneRecord == null && zoneRecordBuilder != null)
        {
            ge.zoneRecord = zoneRecordBuilder.build(c);
        }

        return ge;
    }

  public String getCopyright()
  {
    return defaultFace.getCopyright();
  }

  public String getName()
  {
    return defaultFace.getFamily();
  }

  public FSType getFSType()
  {
    return defaultFace.getFSType();
  }

    public void setLangcode(int code)
    {
        if (code >= 0 && code < 6)
            tag.langCode = code;
    }

    public GlyphEntry getGlyph(char c)
    {
        return (GlyphEntry)glyphEntryMap.get(c);
    }

    public double getFontHeight()
    {
        return fontHeight;
    }

    public int size()
    {
        return glyphEntryMap.size();
    }

    public static final class NoFontManagerException extends RuntimeException
    {
        private static final long serialVersionUID = 755054716704678420L;

        public NoFontManagerException()
        {
            super("No FontManager provided. Cannot build font.");
        }
    }

    public static final class SWFFontNotSupportedException extends RuntimeException
    {
        private static final long serialVersionUID = -7381079883711386211L;

        public SWFFontNotSupportedException(String message)
        {
            super(message);
        }
    }
}
TOP

Related Classes of flash.swf.builder.tags.FontBuilder$SWFFontNotSupportedException

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.