blob: bcb1a457de1c63efc1fd08fbfa163852ef67df64 [file] [log] [blame]
/*******************************************************************************
* 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;
}
}