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.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.10 2001/05/18 16:52:53 billh 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(TextAttribute.BIDI_EMBEDDING);
        glyphPositionKeys.retainAll(keys);

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

            return new GlyphLayout(aci, offset, frc);
        }
    }

    private boolean isRTL(char ch) {
        int bidiCode = UnicodeData.getBiDiCode(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(char ch) {
            int i;
      /* 
            try {
                 i = ((Integer) Array.get(getUnicodeData(ch), BIDI_CODE_NDX)).intValue();
            } catch (Exception e) {
     System.out.println("Error getting BiDi code "+e);
                 i = 0;
      }
            */

            /* intermediate solution: rather than parsing the whole unicode database,
             * we will check for known RTL codepages.  It will return incorrect values
             * for chars that are LTR within RTL codepages (such as arabic numerals?)
             * but should suffice for our current purpose of flagging BiDi or RTL strings.
             *
             * KNOWN Bug:  Alphabetic Presentation Forms (block contains RTL and LTR)
             */                  

            Character.UnicodeBlock ucb = Character.UnicodeBlock.of(ch);

            if ((ucb == Character.UnicodeBlock.ARABIC_PRESENTATION_FORMS_A) ||
                (ucb == Character.UnicodeBlock.ARABIC_PRESENTATION_FORMS_B) ||
                (ucb == Character.UnicodeBlock.ARABIC) ||
                (ucb == Character.UnicodeBlock.HEBREW)) {
    i = RLO;
            } else {
                i = LRO;
            }
      return i;
        }

        public static Array getUnicodeData(int ch) {
             Array array = null;
             Object data = unicodeValues[ch];
             if (!(data instanceof Array)) {
                 try {
                 array = parseUnicodeDataEntry(ch);
                 unicodeValues[ch] = array;
                 } catch (Exception e) {
         System.out.println("Error parsing Unicode data "+e);
                 }
             } else {
                 array = (Array) data;
             }
             return array;
        }

        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.