Package org.apache.batik.gvt.text

Source Code of org.apache.batik.gvt.text.ConcreteTextLayoutFactory$UnicodeData

/*****************************************************************************
* 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.gvt.text;

import java.util.Set;
import java.util.HashSet;
import java.util.StringTokenizer;
import java.io.StreamTokenizer;
import java.io.FileReader;
import java.io.IOException;
import java.io.FileNotFoundException;
import java.awt.geom.Point2D;
import java.awt.font.TextLayout;
import java.awt.font.TextAttribute;
import java.awt.font.FontRenderContext;
import java.text.CharacterIterator;
import java.text.AttributedCharacterIterator;
import java.text.AttributedString;
import java.lang.reflect.Array;
import java.util.Vector;

import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
import org.apache.batik.gvt.text.TextSpanLayout;
import org.apache.batik.gvt.text.TextLayoutFactory;
import org.apache.batik.bridge.SVGFontFamily;   // don't like having to import this
import org.apache.batik.gvt.font.GVTFontFamily;
import org.apache.batik.gvt.font.FontFamilyResolver;
import org.apache.batik.gvt.font.UnresolvedFontFamily;

/**
* Factory instance that returns
* TextSpanLayouts appropriate to AttributedCharacterIterator
* instances.
*
* @see org.apache.batik.gvt.text.TextSpanLayout
* @author <a href="bill.haneman@ireland.sun.com>Bill Haneman</a>
* @version $Id: ConcreteTextLayoutFactory.java,v 1.6 2001/04/29 08:22:55 dino Exp $
*/
public class ConcreteTextLayoutFactory implements TextLayoutFactory {

   public static final int L = 0x0002;
   public static final int R = 0x0001;
   public static final int AL = 0x0005;
   public static final int RLE = 0x0011;
   public static final int RLO = 0x0031;
   public static final int LRE = 0x0010;
   public static final int LRO = 0x0030;
   public static final int B =  0x0080;
   public static final int BN = 0x0180;
   public static final int S =  0x000c;
   public static final int WS = 0x0008;
   public static final int AN = 0x0140;
   public static final int ON = 0x0102;
   public static final int EN = 0x0100;
   public static final int ET = 0x0200;

   public static String unicodeFileName = "UnicodeData.txt";

    /**
     * Returns an instance of TextSpanLayout suitable for rendering the
     * AttributedCharacterIterator.
     * @param aci the character iterator to be laid out
     */
    public TextSpanLayout createTextLayout(AttributedCharacterIterator aci,
                                                Point2D offset,
                                                FontRenderContext frc) {

        Set keys = aci.getAllAttributeKeys();
        Set glyphPositionKeys = new HashSet();
        glyphPositionKeys.add(
              GVTAttributedCharacterIterator.TextAttribute.EXPLICIT_LAYOUT);
        glyphPositionKeys.add(
              GVTAttributedCharacterIterator.TextAttribute.CUSTOM_SPACING);
        glyphPositionKeys.add(
              GVTAttributedCharacterIterator.TextAttribute.BBOX_WIDTH);
        glyphPositionKeys.add(GVTAttributedCharacterIterator.TextAttribute.DX);
        glyphPositionKeys.add(GVTAttributedCharacterIterator.TextAttribute.DY);
        glyphPositionKeys.add(
                GVTAttributedCharacterIterator.TextAttribute.ROTATION);
        glyphPositionKeys.add(
                GVTAttributedCharacterIterator.TextAttribute.BASELINE_SHIFT);
        glyphPositionKeys.add(
                GVTAttributedCharacterIterator.TextAttribute.TEXTPATH);
        glyphPositionKeys.retainAll(keys);

        Vector fontFamilies = (Vector)aci.getAttribute(GVTAttributedCharacterIterator.TextAttribute.GVT_FONT_FAMILIES);

        if (fontFamilies == null) {
            fontFamilies = new Vector();
        }

        // need to see if any of the fontFamilies are for SVGFonts
        boolean containsSVGFont = false;
        for (int i = 0; i < fontFamilies.size(); i++) {
            if (fontFamilies.get(i) instanceof SVGFontFamily) {
                containsSVGFont = true;
            }
        }

      // We really want to use the new GlyphLayout to layout
      // the text. At the moment, use the old code if there is
      // only one resolved font and it isn't an SVG Font.
      // Of course, we shouldn't explicitly test for SVG here
      // (don't want SVG mentioned in GVT :) but we'll try to
      // use GlyphLayout for everything soon!

  /*      if (fontFamilies.size() <= 1 && !containsSVGFont) {

            if (fontFamilies.size() == 1) {

                // need to add the awt font back into the aci attributes, otherwise
                // it uses the default font.

                AttributedString as = new AttributedString(aci);

                GVTFontFamily fontFamily = (GVTFontFamily)fontFamilies.get(0);
                GVTFontFamily resolvedFontFamily;
                if (fontFamily instanceof UnresolvedFontFamily) {
                    resolvedFontFamily = FontFamilyResolver.resolve((UnresolvedFontFamily)fontFamily);
                } else {
                    resolvedFontFamily = fontFamily;
                }
                as.addAttribute(TextAttribute.FAMILY, resolvedFontFamily.getFamilyName());
                aci = as.getIterator();
            }
*/

  if (!containsSVGFont) {

            // the folowing code does what the old font code used to do
            // using this will prevent any font switching within the text
            if (fontFamilies.size() > 0) {

                // need to add the awt font back into the aci attributes, otherwise
                // it uses the default font.

                AttributedString as = new AttributedString(aci);
                boolean fontAssigned = false;
                // find the first font family in the list that is not the
                // default font (the default font indicates that a matching font
                // could not be found) and assign that
                for (int i = 0; i < fontFamilies.size(); i++) {

                    GVTFontFamily fontFamily = (GVTFontFamily)fontFamilies.get(i);
                    GVTFontFamily resolvedFontFamily;
                    if (fontFamily instanceof UnresolvedFontFamily) {
                        resolvedFontFamily = FontFamilyResolver.resolve((UnresolvedFontFamily)fontFamily);
                    } else {
                        resolvedFontFamily = fontFamily;
                    }
                    if (resolvedFontFamily != null) {
                        as.addAttribute(TextAttribute.FAMILY, resolvedFontFamily.getFamilyName());
                        aci = as.getIterator();
                        fontAssigned = true;
                        break;
                    }
                }
                if (!fontAssigned) {
                    // could not match any of the fonts, use the default font
                    as.addAttribute(TextAttribute.FAMILY, FontFamilyResolver.defaultFont.getFamilyName());
                    aci = as.getIterator();
                }
            }

            if (glyphPositionKeys.isEmpty()) {
                return new TextLayoutAdapter(new TextLayout(aci, frc), offset, aci);
            } else {
                char ch = aci.first();
                do {
                    if (isRTL(ch)) {
                      return new TextLayoutAdapter(new TextLayout(aci, frc), offset, aci);
                    }
                    ch = aci.next();
                } while (ch != CharacterIterator.DONE);
            }
        }
  //  System.out.println("Using GlyphLayout");
        return new GlyphLayout(aci, offset, frc);
    }

    private boolean isRTL(char ch) {
        int bidiCode = UnicodeData.getBiDiCode(Character.getNumericValue(ch));
        switch (bidiCode) {
            case R:
            case AL:
            case RLE:
            case RLO:
                return true;
            default:
                return false;
        }
    }


    public static class UnicodeData {

        protected static int BIDI_CODE_NDX = 4;

        protected static Object[] unicodeValues = new Object[0xFF00];

        public static int getBiDiCode(int ch) {
            int i;
            try {
                 i = ((Integer) Array.get(getUnicodeData(ch), BIDI_CODE_NDX)).intValue();
            } catch (Exception e) {
                 i = 0;
            }
            return i;
        }

        public static Array getUnicodeData(int ch) {
             Array data = (Array) unicodeValues[ch];
             if (data == null) {
                 data = parseUnicodeDataEntry(ch);
                 unicodeValues[ch] = data;
             }
             return data;
        }

        public static Array parseUnicodeDataEntry(int ch) {
            Array values = (Array) Array.newInstance(Object.class, 14);
            String s = readUnicodeData(ch, unicodeFileName);
            StringTokenizer st = new StringTokenizer(s, ";");
            Array.set(values, 0, new Integer(st.nextToken())); // unicode value
            Array.set(values, 1, st.nextToken()); // character name
            Array.set(values, 2, st.nextToken()); // case
            Array.set(values, 3, st.nextToken())//
            Array.set(values, 4, new Integer(getBiDiValue(st.nextToken()))); // BiDi value
            Array.set(values, 5, new Integer(st.nextToken())); // unicode value
            Array.set(values, 6, st.nextToken());
            Array.set(values, 7, st.nextToken());
            Array.set(values, 8, st.nextToken());
            Array.set(values, 9, st.nextToken());
            Array.set(values, 10, st.nextToken());
            Array.set(values, 11, st.nextToken());
            Array.set(values, 12, st.nextToken());
            Array.set(values, 13, st.nextToken());
            return values;
        }

        private static int getBiDiValue(String string) {
            int val = 0;
            char s[] = string.toCharArray();

            switch (s[0]) {
            case 'L':
                if (s.length > 2) {
                    switch (s[2]) {
                    case 'E':
                        val = LRE;
                        break;
                    default:
                        val = LRO;
                    }
                } else {
                   val = L;
                }
                break;
            case 'R':
                if (s.length > 2) {
                    switch (s[2]) {
                    case 'E':
                        val = RLE;
                        break;
                    default:
                        val = RLO;
                    }
                } else {
                   val = R;
                }
                break;
            case 'A':
                switch (s[2]) {
                case 'L':
                    val = AL;
                    break;
                default:
                    val = AN;
                }
                break;
            case 'B':
                if (s.length > 1) {
                    val = BN;
                } else {
                    val = B;
                }
                break;
            case 'E':
                switch (s[1]) {
                case 'N':
                    val = EN;
                    break;
                default:
                    val = ET;
                }
                break;
            case 'O':
                val = ON;
                break;
            case 'S':
                val = S;
            }
            return val;
        }

        private static String readUnicodeData(int ch, String filename) {
            String s = null;
            try {
                StreamTokenizer st = new StreamTokenizer(new FileReader(filename));
                st.resetSyntax();
                st.eolIsSignificant(true);
                for (int i=0; i<ch; ++i) {
                    s = st.toString();
                    st.nextToken(); // eol token
                    st.nextToken(); // next line
                }
                System.out.println("UnicodeData for "+ch+": "+s);
            } catch (FileNotFoundException fnfe) {
                System.out.println(fnfe);
            } catch (IOException ioe) {
                System.out.println("Error reading Unicode Database: "+ioe);
            }
            return s;
        }

    }
}
TOP

Related Classes of org.apache.batik.gvt.text.ConcreteTextLayoutFactory$UnicodeData

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.