home *** CD-ROM | disk | FTP | other *** search
Java Source | 1998-03-20 | 19.9 KB | 555 lines |
- /*
- * @(#)GlyphSet.java 1.26 98/03/18
- *
- * Copyright 1997, 1998 by Sun Microsystems, Inc.,
- * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
- * All rights reserved.
- *
- * This software is the confidential and proprietary information
- * of Sun Microsystems, Inc. ("Confidential Information"). You
- * shall not disclose such Confidential Information and shall use
- * it only in accordance with the terms of the license agreement
- * you entered into with Sun.
- */
-
- /*
- * (C) Copyright Taligent, Inc. 1996 - 1997, All Rights Reserved
- * (C) Copyright IBM Corp. 1996 - 1998, All Rights Reserved
- *
- * The original version of this source code and documentation is
- * copyrighted and owned by Taligent, Inc., a wholly-owned subsidiary
- * of IBM. These materials are provided under terms of a License
- * Agreement between Taligent and Sun. This technology is protected
- * by multiple US and International patents.
- *
- * This notice and attribution to Taligent may not be removed.
- * Taligent is a registered trademark of Taligent, Inc.
- *
- */
-
- package java.awt.font;
-
- import java.text.AttributedCharacterIterator;
- import java.awt.Graphics2D;
- import java.awt.Font;
- import java.awt.geom.Rectangle2D;
-
- /**
- * GlyphSet is a graphical representation of text with bidirectional ordering.
- * Instances of GlyphSet are
- * produced by Font (or subclasses of Font) and contain a sequence of integer
- * glyph codes, used by the Font to represent text graphically. The glyph codes
- * are not characters; they are meaningful only
- * to the Font which produced them. GlyphSets may be displayed on a graphics
- * device. Metrics for the entire GlyphSet or for individual glyphs may be
- * queried. Additionally, new GlyphSets may be produced from old ones for
- * operations such as taking a subset of a glyphset, justification, changing
- * a single character in the source text, and setting the direction of the
- * glyphs in a GlyphSet.
- * <p>
- * GlyphSets are immutable; once created, their state never changes. In particular,
- * changes to the text from which they were created do not affect existing GlyphSets.
- * <p>
- * The glyphs in a GlyphSet are stored in <em>logical order</em>; that is, they
- * are stored in the same order as the characters from which they were generated.
- * GlyphSets also maintain a <em>visual order</em> for their glyphs. The visual
- * order is the order, from left to right, in which the glyphs will be displayed.
- * For text with right-to-left or bidirectional ordering, the logical order will
- * not be the same as the visual order. Glyphs are available in logical order
- * directly from the GlyphSet. Additionally, <code>visualToLogicalIndex</code>
- * will convert a visual position to a logical position.
- * <p>
- * A GlyphSet may contain more glyphs
- * than the number of characters in the sequence it represents (but never less).
- * Methods on GlyphSet which return information on glyphs require a glyph index. Other
- * methods on GlyphSet are commonly associated with text editing (such as inserting or
- * deleting a character, or taking a subset). These operations used character indices.
- * <p>
- * <strong>Example</strong>:
- * <p>
- * Examine glyphs in visual order
- * <blockquote><pre>
- * GlyphSet glyphSet = ...;
- * for (int i=0; i < getNumGlyphs(); i++) {
- * int logIndex = glyphSet.visualToLogicalIndex(i);
- * int glyphCode = glyphSet.getGlyphCode(logIndex);
- * // do something with glyphCode...
- * }
- * </blockquote></pre>
- * @see Font
- * @see GlyphMetrics
- * @see TextLayout
- */
-
- public abstract class GlyphSet implements Cloneable {
- /**
- * Return the advance of the glyphset.
- */
- public abstract float getAdvance();
-
- /**
- * Return the ascent of the glyphset relative to the baseline.
- *
- * This is the distance above (to the right of) the baseline.
- * The ascent is always positive or zero.
- * @see #getBaseline
- */
- public abstract float getAscent();
-
- /**
- * return the descent of the glyphset relative to the baseline.
- *
- * This is the distance below (to the left of) the baseline.
- * The descent is always positive or zero.
- * @see #getBaseline
- */
- public abstract float getDescent();
-
- /**
- * Return the font that created this glyphset.
- */
- public abstract Font getFont();
-
- /**
- * Return the number of glyphs in this glyphset.
- */
- public abstract int getNumGlyphs();
-
- /**
- * Return the number of characters represented by this glyphset.
- *
- * Some fonts may use several glyphs to represent a single
- * character. There are never fewer glyphs than characters.
- * Glyphs representing more than one character are always followed
- * (logically) by an invisible combining glyph for each additional
- * character.
- */
- public abstract int getNumCharacters();
-
- /**
- * Return the glyphcode at the given logical position in this glyphset.
- *
- * @see #getNumGlyphs
- */
- public abstract int getGlyphCode(int index);
-
- /**
- * Return the baseline used by this glyphset. All glyphs in a single
- * glyphset align to the same baseline.
- * @see Font#getBaselineFor
- */
- public abstract byte getBaseline();
-
- /**
- * Return the x position of the first visual glyph in the glyphset.
- *
- * The first visual glyph in the glyphset is offset by x, y from the
- * origin of the glyphset. This supports attributes like superscript.
- * @see #getYAdjust
- */
- public abstract float getXAdjust();
-
- /**
- * Return the x-direction advance of the glyph at the given logical
- * position.
- * @see #getGlyphYAdvance
- * @see #getNumGlyphs
- */
- public abstract float getGlyphXAdvance(int index);
-
- /**
- * Return the y position of the first visual glyph in the glyphset.
- *
- * The first visual glyph in the glyphset is offset by x, y from the
- * origin of the glyphset. This supports attributes like superscript.
- * @see #getXAdjust
- */
- public abstract float getYAdjust();
-
- /**
- * Return the y-direction advance of the glyph at the given logical
- * position.
- * @see #getGlyphXAdvance
- * @see #getNumGlyphs
- */
- public abstract float getGlyphYAdvance(int index);
-
- /**
- * Return the advance for the glyph at the given logical position.
- * The X-advance is returned on a horizontal line; the Y-advance is
- * returned on a vertical line.
- */
- public abstract float getGlyphAdvance(int index);
-
- /**
- * Map from visual position to logical position.
- *
- * For example, visualToLogicalIndex(0) = 5 means that the first
- * glyph drawn is at position five in the glyphCodes, levels, and
- * advances arrays.
- * @see #getNumGlyphs
- */
- public abstract int visualToLogicalIndex(int index);
-
- /**
- * Return the bidirection level of the glyph at the given logical position.
- *
- * Glyphs whose level is even are left to right (top to bottom),
- * glyphs whose level is odd are right to left (bottom to top).
- * @see #getNumGlyphs
- */
- public abstract byte getLevel(int index);
-
- /**
- * Return true if every glyph in the glyphset is left-to-right, and
- * the glyphs all run from left to right.
- * @see #getLevel
- */
- public abstract boolean isCompletelyLTR();
-
- /**
- * Return a justified copy of this glyphset.
- * @param deltas an array of amounts by which to change the left
- * and right sides of each glyph, in visual order. The array has
- * at least twice as many entries as there are glyphs in the glyphset.
- * For example, deltas[index] is the delta for the left side of
- * the visually leftmost glyph, deltas[index+1] is for the right side
- * of the visually leftmost glyph, deltas[index+2] is for the left side
- * of the visually second leftmost glyph, and so on.
- * @param index the starting position in the deltas array. It
- * corresponds to the left side of the leftmost glyph.
- * @param shouldRejustify an array containing a single input/output
- * boolean value. On entry, it indicates whether the returned glyphset
- * is allowed to cause rejustification, for example, if a ligature can
- * be formed or broken. On exit, it indicates whether the returned
- * glyphset will require rejustification (for example, due to the
- * formation or removal of a ligature).
- */
- public abstract GlyphSet applyJustification(float[] deltas,
- int index, boolean[] flags);
-
- /**
- * Return the sum of the advances for the glyphs corresponding to
- * characters in logical positions from start up to limit. Note these
- * are character indices, not glyph indices. They will be mapped
- * internally to glyph indices.
- *
- * @param start the character index at which to start measuring
- * @param limit the character index at which to stop measuring
- */
- public abstract float getAdvanceBetween(int start, int limit);
-
- /**
- * Return the logical position of a possible break. This adds up
- * advances of glyphs in logical order starting from the glyph for the
- * character at start, stopping before the first spacing glyph whose
- * advance would cause hitAdvance to be exceeded. The character
- * position of that glyph is returned. If no glyph would reach the
- * hitAdvance, the number of characters in the set is returned.
- * This will not break between combining or component glyphs and their
- * base glyph.
- */
- public abstract int getLineBreakIndex(int start, float hitAdvance);
-
- /**
- * Generate a GlyphSet that contains the subset of this from logical
- * start up to limit. The new glyphset shares the same baseline,
- * xAdjust, and yAdjust as the previous one.
- * @param start the character index where the subset will begin
- * @param limit the character index immediately after the end of
- * the subset
- */
- public abstract GlyphSet subset(int start, int limit);
-
- /**
- * Return a new GlyphSet which is an incremental modification of this
- * one.
- *
- * This glyphset must have been generated from text identical to
- * newText, with exactly one difference: an inserted character at
- * insertPos at newText.
- *
- * @param newText the text for the new glyphset. This represents
- * the text after the insertion occurred. The new glyphset will
- * represent the text beginning at start, up to (but not including)
- * limit.
- * @param start the start of the subrange in newText for the glyphset
- * @param limit the limit of the subrange in newText for the glyphset,
- * including the inserted character.
- * @param insertPos the character position in the glyphset at which
- * the single character was inserted.
- * @param order the logical-to-visual mapping array for newText.
- * If null, left-to-right is assumed.
- * @param levels the bidirection level of each character in newText.
- * If null, all levels are assumed to be 0.
- * @return a new GlyphSet representing newText.
- */
- public abstract GlyphSet insertChar(AttributedCharacterIterator newText,
- int start, int limit, int insertPos, int[] order, byte[] levels);
-
- /**
- * Return a new GlyphSet which is an incremental modification of this
- * one.
- *
- * This glyphset must have been generated from text identical to newText,
- * with exactly one difference: a deleted character at deletePos at
- * newText.
- *
- * @param newText the text for the new glyphset. This represents the
- * text after the deletion occurred. The new glyphset will represent
- * the text beginning at start, up to (but not including) limit.
- * @param start the start of the subrange in newText for the glyphset.
- * @param limit the limit of the subrange in newText for the glyphset,
- * not including the deleted character.
- * @param deletePos the character position in the glyphset at which the
- * single character was deleted.
- * @param order the logical-to-visual mapping array for newText.
- * If null, left-to-right is assumed.
- * @param levels the bidirection level of each character in newText.
- * If null, all levels are assumed to be 0.
- * @return a new GlyphSet representing newText.
- */
- public abstract GlyphSet deleteChar(AttributedCharacterIterator newText,
- int start, int limit, int deletePos, int[] order, byte[] levels);
-
- /**
- * Reshape a glyph set after a change to neighboring text.
- *
- * If this GlyphSet's font does context-sensitive glyph shaping, then
- * a change in a character can affect the glyphs before and after it.
- * This method allows the Font to inspect the new text and (possibly)
- * return a new glyphset with different shaping. This method is used
- * in conjunction with insertChar and deleteChar.
- * @param newText styled text represented by this GlyphSet over the
- * range start, limit.
- * @param start the start of the range in newText represented by this
- * GlyphSet.
- * @param limit the limit of the range in newText represented by this
- * GlyphSet.
- * @param changePos the position in newText that has changed since this
- * GlyphSet was created. This parameter must be either start-1 or limit.
- * @param order the logical-to-visual mapping array for newText.
- * If null, left-to-right is assumed.
- * @param levels the bidirection level of each character in newText.
- * If null, all levels are assumed to be 0.
- * @return a GlyphSet representing newText over the range start, limit,
- * with updated glyph shaping (if any).
- * @see #insertChar
- * @see #deleteChar
- */
- public abstract GlyphSet reshape(AttributedCharacterIterator newText,
- int start, int limit, int changePos, int[] order, byte[] levels);
-
- /**
- * Draw this glyphset at the provided position.
- */
- public abstract void draw(Graphics2D graphics, float x, float y);
-
- /**
- * Return the bounds in which contains all of the bits drawn by
- * this GlyphSet.
- */
- public abstract Rectangle2D getBounds();
-
- /**
- * An argument to setDirection indicating LEFT_TO_RIGHT glyphs.
- * @see #setDirection
- */
- public static final boolean LEFT_TO_RIGHT = true;
-
- /**
- * An argument to setDirection indicating RIGHT_TO_LEFT glyphs.
- * @see #setDirection
- */
- public static final boolean RIGHT_TO_LEFT = false;
-
- /**
- * Return a GlyphSet identical to this one, except with all glyphs
- * going in the same direction.
- * @see #LEFT_TO_RIGHT
- * @see #RIGHT_TO_LEFT
- */
- public abstract GlyphSet setDirection(boolean leftToRight);
-
- /**
- * Return a hashCode for this glyphset.
- */
- public abstract int hashCode();
-
- /**
- * Test for full equality. Font, glyphs, baseline, advances, adjusts,
- * order, levels, count must all match.
- */
- public abstract boolean equals(GlyphSet set);
-
- /**
- * Return the inverse array, source array must map 1-1
- *
- * i.e. if values[i] = j, then inverse[j] = i.
- */
- public static int[] getInverseOrder(int[] values) {
- if (values == null) {
- return null;
- }
-
- int[] result = new int[values.length];
- for (int i = 0; i < values.length; i++) {
- result[values[i]] = i;
- }
-
- return result;
- }
-
- /**
- * Compute a contiguous order for the range start, limit.
- */
- private static int[] computeContiguousOrder(int[] values, int start,
- int limit) {
-
- int[] result = new int[limit-start];
- for (int i=0; i < result.length; i++) {
- result[i] = i + start;
- }
-
- // now we'll sort result[], with the following comparison:
- // result[i] lessthan result[j] iff values[result[i]] < values[result[j]]
-
- // selection sort for now; use more elaborate sorts if desired
- for (int i=0; i < result.length-1; i++) {
- int minIndex = i;
- int currentValue = values[result[minIndex]];
- for (int j=i; j < result.length; j++) {
- if (values[result[j]] < currentValue) {
- minIndex = j;
- currentValue = values[result[minIndex]];
- }
- }
- int temp = result[i];
- result[i] = result[minIndex];
- result[minIndex] = temp;
- }
-
- // shift result by start:
- if (start != 0) {
- for (int i=0; i < result.length; i++) {
- result[i] -= start;
- }
- }
-
- // next, check for canonical order:
- int k;
- for (k=0; k < result.length; k++) {
- if (result[k] != k) {
- break;
- }
- }
-
- if (k == result.length) {
- return null;
- }
-
- // now return inverse of result:
- return getInverseOrder(result);
- }
-
- /**
- * Return an array containing contiguous values from 0 to length
- * having the same ordering as the source array. If this would be
- * a canonical ltr ordering, return null. values[] is NOT
- * required to be a permutation.
- */
- public static int[] getContiguousOrder(int[] values) {
- if (values != null) {
- return computeContiguousOrder(values, 0, values.length);
- }
-
- return null;
- }
-
- /**
- * Return an array containing the values from start up to limit,
- * normalized to fall within the range from 0 up to limit - start.
- * If this would be a canonical ltr ordering, return null.
- * NOTE: This method assumes that values[] is a permutation
- * generated from levels[].
- */
- public static int[] getNormalizedOrder(int[] values, byte[] levels,
- int start, int limit) {
-
- if (values != null) {
- if (start != 0 || limit != values.length) {
- // levels optimization
- boolean copyRange, canonical;
- byte primaryLevel;
-
- if (levels == null) {
- primaryLevel = (byte) 0x0;
- copyRange = true;
- canonical = true;
- }
- else {
- if (levels[start] == levels[limit-1]) {
- primaryLevel = levels[start];
- canonical = (primaryLevel & (byte)0x1) == 0;
-
- // scan for levels below primary
- int i;
- for (i=start; i < limit; i++) {
- if (levels[i] < primaryLevel) {
- break;
- }
- if (canonical) {
- canonical = levels[i] == primaryLevel;
- }
- }
-
- copyRange = (i == limit);
- }
- else {
- copyRange = false;
-
- // these don't matter; but the compiler cares:
- primaryLevel = (byte) 0x0;
- canonical = false;
- }
- }
-
- if (copyRange) {
- if (canonical) {
- return null;
- }
-
- int[] result = new int[limit-start];
- int baseValue;
-
- if ((primaryLevel & (byte)0x1) != 0) {
- baseValue = values[limit-1];
- } else {
- baseValue = values[start];
- }
-
- if (baseValue == 0) {
- System.arraycopy(values, start, result, 0, limit-start);
- }
- else {
- for (int j=0; j < result.length; j++) {
- result[j] = values[j+start] - baseValue;
- }
- }
-
- return result;
- }
- else {
- return computeContiguousOrder(values, start, limit);
- }
- }
- else {
- return values;
- }
- }
-
- return null;
- }
- public abstract int[] getGlyphCodes();
- }
-