/******************************************************************************* * Copyright (c) 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation ******************************************************************************/ package org.eclipse.equinox.bidi.custom; import org.eclipse.equinox.bidi.advanced.IStructuredTextExpert; import org.eclipse.equinox.bidi.advanced.StructuredTextEnvironment; /** * Provides services related to the bidi classification of characters. */ public class StructuredTextCharTypes { // In the following lines, B, L, R and AL represent bidi categories // as defined in the Unicode Bidirectional Algorithm // ( http://www.unicode.org/reports/tr9/ ). // B represents the category Block Separator. // L represents the category Left to Right character. // R represents the category Right to Left character. // AL represents the category Arabic Letter. // AN represents the category Arabic Number. // EN represents the category European Number. static final byte B = Character.DIRECTIONALITY_PARAGRAPH_SEPARATOR; static final byte L = Character.DIRECTIONALITY_LEFT_TO_RIGHT; static final byte R = Character.DIRECTIONALITY_RIGHT_TO_LEFT; static final byte AL = Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC; static final byte AN = Character.DIRECTIONALITY_ARABIC_NUMBER; static final byte EN = Character.DIRECTIONALITY_EUROPEAN_NUMBER; private static final int CHARTYPES_ADD = 2; /** * The IStructuredTextExpert instance which created this instance. */ final protected IStructuredTextExpert expert; /** * The StructuredTextTypeHandler instance utilized by the expert. */ final protected StructuredTextTypeHandler handler; /** * The environment associated with the expert. */ final protected StructuredTextEnvironment environment; /** * The source text whose characters are analyzed. */ final protected String text; // 1 byte for each char in text private byte[] types; // structured text direction. -1 means not yet computed; -2 means within handler.getDirection private int direction = -1; /** * Constructor * * @param expert IStructuredTextExpert instance through which this handler * is invoked. The handler can use IStructuredTextExpert methods to * query items stored in the expert instance, like the current * {@link StructuredTextEnvironment environment}. * * @param text is the text whose characters are analyzed. */ public StructuredTextCharTypes(IStructuredTextExpert expert, String text) { this.expert = expert; this.handler = expert.getTypeHandler(); this.environment = expert.getEnvironment(); this.text = text; types = new byte[text.length()]; } /** * Indicates the base text direction appropriate for an instance of * structured text. * * @return the base direction of the structured text. This direction * may not be the same depending on the environment and on * whether the structured text contains Arabic or Hebrew * letters.<br> * The value returned is either * {@link IStructuredTextExpert#DIR_LTR DIR_LTR} or * {@link IStructuredTextExpert#DIR_RTL DIR_RTL}. */ public int getDirection() { if (direction < 0) direction = handler.getDirection(expert, text, this); return direction; } private byte getCachedTypeAt(int index) { return (byte) (types[index] - CHARTYPES_ADD); } private boolean hasCachedTypeAt(int i) { return (types[i] != 0); // "0" means "unknown" } /** * Gets the directionality of the character in the original string * at the specified index. * * @param index position of the character in the <i>lean</i> text * * @return the bidi type of the character. It is one of the * values which can be returned by * {@link Character#getDirectionality(char)}. */ public byte getBidiTypeAt(int index) { if (hasCachedTypeAt(index)) return getCachedTypeAt(index); byte charType = Character.getDirectionality(text.charAt(index)); if (charType == B) { if (direction < 0) { if (direction < -1) // called by handler.getDirection return charType; // avoid infinite recursion direction = -2; // signal we go within handler.getDirection direction = handler.getDirection(expert, text, this); } charType = (direction == StructuredTextEnvironment.ORIENT_RTL) ? R : L; } setBidiTypeAt(index, charType); return charType; } /** * Forces a bidi type on a character. * * @param index position of the character whose bidi type is set. * * @param charType bidirectional type of the character. It must be * one of the values which can be returned by * <code>java.lang.Character.getDirectionality</code>. */ public void setBidiTypeAt(int index, byte charType) { types[index] = (byte) (charType + CHARTYPES_ADD); } /** * Gets the orientation of the component in which the text will * be displayed. * * @return the orientation as either * {@link StructuredTextEnvironment#ORIENT_LTR}, * {@link StructuredTextEnvironment#ORIENT_RTL}, * {@link StructuredTextEnvironment#ORIENT_UNKNOWN} or * {@link StructuredTextEnvironment#ORIENT_IGNORE}. */ public int resolveOrientation() { int orient = environment.getOrientation(); if ((orient & StructuredTextEnvironment.ORIENT_CONTEXTUAL) == 0) { // absolute orientation return orient; } // contextual orientation: orient &= ~StructuredTextEnvironment.ORIENT_CONTEXTUAL; // initiate to the default orientation minus contextual bit int len = text.length(); byte charType; for (int i = 0; i < len; i++) { if (!hasCachedTypeAt(i)) { charType = Character.getDirectionality(text.charAt(i)); if (charType == B) // B char resolves to L or R depending on orientation continue; setBidiTypeAt(i, charType); } else charType = getCachedTypeAt(i); if (charType == L) return StructuredTextEnvironment.ORIENT_LTR; if (charType == R || charType == AL) return StructuredTextEnvironment.ORIENT_RTL; } return orient; } }