/* * @(#)GlyphVector.java 1.32 03/12/19 * * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ /* * @author Charlton Innovations, Inc. */ package java.awt.font; import java.awt.Graphics2D; import java.awt.Font; import java.awt.Polygon; // remind - need a floating point version import java.awt.Rectangle; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.awt.geom.AffineTransform; import java.awt.Shape; import java.awt.font.GlyphMetrics; import java.awt.font.GlyphJustificationInfo; /** * A GlyphVector object is a collection of glyphs * containing geometric information for the placement of each glyph * in a transformed coordinate space which corresponds to the * device on which the GlyphVector is ultimately * displayed. *

* The GlyphVector does not attempt any interpretation of * the sequence of glyphs it contains. Relationships between adjacent * glyphs in sequence are solely used to determine the placement of * the glyphs in the visual coordinate space. *

* Instances of GlyphVector are created by a {@link Font}. *

* In a text processing application that can cache intermediate * representations of text, creation and subsequent caching of a * GlyphVector for use during rendering is the fastest * method to present the visual representation of characters to a user. *

* A GlyphVector is associated with exactly one * Font, and can provide data useful only in relation to * this Font. In addition, metrics obtained from a * GlyphVector are not generally geometrically scaleable * since the pixelization and spacing are dependent on grid-fitting * algorithms within a Font. To facilitate accurate * measurement of a GlyphVector and its component * glyphs, you must specify a scaling transform, anti-alias mode, and * fractional metrics mode when creating the GlyphVector. * These characteristics can be derived from the destination device. *

* For each glyph in the GlyphVector, you can obtain: *

*

* Altering the data used to create the GlyphVector does not * alter the state of the GlyphVector. *

* Methods are provided to adjust the positions of the glyphs * within the GlyphVector. These methods are most * appropriate for applications that are performing justification * operations for the presentation of the glyphs. *

* Methods are provided to transform individual glyphs within the * GlyphVector. These methods are primarily useful for * special effects. *

* Methods are provided to return both the visual, logical, and pixel bounds * of the entire GlyphVector or of individual glyphs within * the GlyphVector. *

* Methods are provided to return a {@link Shape} for the * GlyphVector, and for individual glyphs within the * GlyphVector. * @see Font * @see GlyphMetrics * @see TextLayout * @version 19 Mar 1998 * @author Charlton Innovations, Inc. */ public abstract class GlyphVector implements Cloneable { // // methods associated with creation-time state // /** * Returns the Font associated with this * GlyphVector. * @return Font used to create this * GlyphVector. * @see Font */ public abstract Font getFont(); /** * Returns the {@link FontRenderContext} associated with this * GlyphVector. * @return FontRenderContext used to create this * GlyphVector. * @see FontRenderContext * @see Font */ public abstract FontRenderContext getFontRenderContext(); // // methods associated with the GlyphVector as a whole // /** * Assigns default positions to each glyph in this * GlyphVector. This can destroy information * generated during initial layout of this GlyphVector. */ public abstract void performDefaultLayout(); /** * Returns the number of glyphs in this GlyphVector. * @return number of glyphs in this GlyphVector. */ public abstract int getNumGlyphs(); /** * Returns the glyphcode of the specified glyph. * This return value is meaningless to anything other * than the Font object that created this * GlyphVector. * @param glyphIndex the index into this GlyphVector * that corresponds to the glyph from which to retrieve the * glyphcode. * @return the glyphcode of the glyph at the specified * glyphIndex. * @throws IndexOutOfBoundsException if glyphIndex * is less than 0 or greater than or equal to the * number of glyphs in this GlyphVector */ public abstract int getGlyphCode(int glyphIndex); /** * Returns an array of glyphcodes for the specified glyphs. * The contents of this return value are meaningless to anything other * than the Font used to create this * GlyphVector. This method is used * for convenience and performance when processing glyphcodes. * If no array is passed in, a new array is created. * @param beginGlyphIndex the index into this * GlyphVector at which to start retrieving glyphcodes * @param numEntries the number of glyphcodes to retrieve * @param codeReturn the array that receives the glyphcodes and is * then returned * @return an array of glyphcodes for the specified glyphs. * @throws IllegalArgumentException if numEntries is * less than 0 * @throws IndexOutOfBoundsException if beginGlyphIndex * is less than 0 * @throws IndexOutOfBoundsException if the sum of * beginGlyphIndex and numEntries is * greater than the number of glyphs in this * GlyphVector */ public abstract int[] getGlyphCodes(int beginGlyphIndex, int numEntries, int[] codeReturn); /** * Returns the character index of the specified glyph. * The character index is the index of the first logical * character represented by the glyph. The default * implementation assumes a one-to-one, left-to-right mapping * of glyphs to characters. * @param glyphIndex the index of the glyph * @return the index of the first character represented by the glyph * @since 1.4 */ public int getGlyphCharIndex(int glyphIndex) { return glyphIndex; } /** * Returns the character indices of the specified glyphs. * The character index is the index of the first logical * character represented by the glyph. Indices are returned * in glyph order. The default implementation invokes * getGlyphCharIndex for each glyph, and subclassers will probably * want to override this implementation for performance reasons. * Use this method for convenience and performance * in processing of glyphcodes. If no array is passed in, * a new array is created. * @param beginGlyphIndex the index of the first glyph * @param numEntries the number of glyph indices * @param codeReturn the array into which to return the character indices * @return an array of character indices, one per glyph. * @since 1.4 */ public int[] getGlyphCharIndices(int beginGlyphIndex, int numEntries, int[] codeReturn) { if (codeReturn == null) { codeReturn = new int[numEntries]; } for (int i = 0, j = beginGlyphIndex; i < numEntries; ++i, ++j) { codeReturn[i] = getGlyphCharIndex(j); } return codeReturn; } /** * Returns the logical bounds of this GlyphVector. * This method is used when positioning this GlyphVector * in relation to visually adjacent GlyphVector objects. * @return a {@link Rectangle2D} that is the logical bounds of this * GlyphVector. */ public abstract Rectangle2D getLogicalBounds(); /** * Returns the visual bounds of this GlyphVector * The visual bounds is the bounding box of the outline of this * GlyphVector. Because of rasterization and * alignment of pixels, it is possible that this box does not * enclose all pixels affected by rendering this GlyphVector. * @return a Rectangle2D that is the bounding box * of this GlyphVector. */ public abstract Rectangle2D getVisualBounds(); /** * Returns the pixel bounds of this GlyphVector when * rendered in a graphics with the given * FontRenderContext at the given location. The * renderFRC need not be the same as the * FontRenderContext of this * GlyphVector, and can be null. If it is null, the * FontRenderContext of this GlyphVector * is used. The default implementation returns the visual bounds, * offset to x, y and rounded out to the next integer value (i.e. returns an * integer rectangle which encloses the visual bounds) and * ignores the FRC. Subclassers should override this method. * @param renderFRC the FontRenderContext of the Graphics. * @param x the x-coordinate at which to render this GlyphVector. * @param y the y-coordinate at which to render this GlyphVector. * @return a Rectangle bounding the pixels that would be affected. * @since 1.4 */ public Rectangle getPixelBounds(FontRenderContext renderFRC, float x, float y) { Rectangle2D rect = getVisualBounds(); int l = (int)Math.floor(rect.getX() + x); int t = (int)Math.floor(rect.getY() + y); int r = (int)Math.ceil(rect.getMaxX() + x); int b = (int)Math.ceil(rect.getMaxY() + y); return new Rectangle(l, t, r - l, b - t); } /** * Returns a Shape whose interior corresponds to the * visual representation of this GlyphVector. * @return a Shape that is the outline of this * GlyphVector. */ public abstract Shape getOutline(); /** * Returns a Shape whose interior corresponds to the * visual representation of this GlyphVector when * rendered at x, y. * @param x, y the coordinates of this GlyphVector. * @return a Shape that is the outline of this * GlyphVector when rendered at the specified * coordinates. */ public abstract Shape getOutline(float x, float y); /** * Returns a Shape whose interior corresponds to the * visual representation of the specified glyph * within this GlyphVector. * The outline returned by this method is positioned around the * origin of each individual glyph. * @param glyphIndex the index into this GlyphVector * @return a Shape that is the outline of the glyph * at the specified glyphIndex of this * GlyphVector. * @throws IndexOutOfBoundsException if glyphIndex * is less than 0 or greater than or equal to the number * of glyphs in this GlyphVector */ public abstract Shape getGlyphOutline(int glyphIndex); /** * Returns a Shape whose interior corresponds to the * visual representation of the specified glyph * within this GlyphVector, offset to x, y. * The outline returned by this method is positioned around the * origin of each individual glyph. * @param glyphIndex the index into this GlyphVector * @param x, y the coordinates of the location of this * GlyphVector. * @return a Shape that is the outline of the glyph * at the specified glyphIndex of this * GlyphVector when rendered at the specified * coordinates. * @throws IndexOutOfBoundsException if glyphIndex * is less than 0 or greater than or equal to the number * of glyphs in this GlyphVector * @since 1.4 */ public Shape getGlyphOutline(int glyphIndex, float x, float y) { Shape s = getGlyphOutline(glyphIndex); AffineTransform at = AffineTransform.getTranslateInstance(x,y); return at.createTransformedShape(s); } /** * Returns the position of the specified glyph relative to the * origin of this GlyphVector. * If glyphIndex equals the number of of glyphs in * this GlyphVector, this method returns the position after * the last glyph. This position is used to define the advance of * the entire GlyphVector. * @param glyphIndex the index into this GlyphVector * @return a {@link Point2D} object that is the position of the glyph * at the specified glyphIndex. * @throws IndexOutOfBoundsException if glyphIndex * is less than 0 or greater than the number of glyphs * in this GlyphVector * @see #setGlyphPosition */ public abstract Point2D getGlyphPosition(int glyphIndex); /** * Sets the position of the specified glyph within this * GlyphVector. * If glyphIndex equals the number of of glyphs in * this GlyphVector, this method sets the position after * the last glyph. This position is used to define the advance of * the entire GlyphVector. * @param glyphIndex the index into this GlyphVector * @param newPos the Point2D at which to position the * glyph at the specified glyphIndex * @throws IndexOutOfBoundsException if glyphIndex * is less than 0 or greater than the number of glyphs * in this GlyphVector * @see #getGlyphPosition */ public abstract void setGlyphPosition(int glyphIndex, Point2D newPos); /** * Returns the transform of the specified glyph within this * GlyphVector. The transform is relative to the * glyph position. If no special transform has been applied, * null can be returned. A null return indicates * an identity transform. * @param glyphIndex the index into this GlyphVector * @return an {@link AffineTransform} that is the transform of * the glyph at the specified glyphIndex. * @throws IndexOutOfBoundsException if glyphIndex * is less than 0 or greater than or equal to the number * of glyphs in this GlyphVector * @see #setGlyphTransform */ public abstract AffineTransform getGlyphTransform(int glyphIndex); /** * Sets the transform of the specified glyph within this * GlyphVector. The transform is relative to the glyph * position. A null argument for newTX * indicates that no special transform is applied for the specified * glyph. * This method can be used to rotate, mirror, translate and scale the * glyph. Adding a transform can result in signifant performance changes. * @param glyphIndex the index into this GlyphVector * @param newTX the new transform of the glyph at glyphIndex * @throws IndexOutOfBoundsException if glyphIndex * is less than 0 or greater than or equal to the number * of glyphs in this GlyphVector * @see #getGlyphTransform */ public abstract void setGlyphTransform(int glyphIndex, AffineTransform newTX); /** * Returns flags describing the global state of the GlyphVector. * Flags not described below are reserved. The default * implementation returns 0 (meaning false) for the position adjustments, * transforms, rtl, and complex flags. * Subclassers should override this method, and make sure * it correctly describes the GlyphVector and corresponds * to the results of related calls. * @return an int containing the flags describing the state * @see #FLAG_HAS_POSITION_ADJUSTMENTS * @see #FLAG_HAS_TRANSFORMS * @see #FLAG_RUN_RTL * @see #FLAG_COMPLEX_GLYPHS * @see #FLAG_MASK * @since 1.4 */ public int getLayoutFlags() { return 0; } /** * A flag used with getLayoutFlags that indicates that this GlyphVector has * per-glyph transforms. * @since 1.4 */ public static final int FLAG_HAS_TRANSFORMS = 1; /** * A flag used with getLayoutFlags that indicates that this GlyphVector has * position adjustments. When this is true, the glyph positions don't match the * accumulated default advances of the glyphs (for example, if kerning has been done). * @since 1.4 */ public static final int FLAG_HAS_POSITION_ADJUSTMENTS = 2; /** * A flag used with getLayoutFlags that indicates that this GlyphVector has * a right-to-left run direction. This refers to the glyph-to-char mapping and does * not imply that the visual locations of the glyphs are necessarily in this order, * although generally they will be. * @since 1.4 */ public static final int FLAG_RUN_RTL = 4; /** * A flag used with getLayoutFlags that indicates that this GlyphVector has * a complex glyph-to-char mapping (one that does not map glyphs to chars one-to-one in * strictly ascending or descending order matching the run direction). * @since 1.4 */ public static final int FLAG_COMPLEX_GLYPHS = 8; /** * A mask for supported flags from getLayoutFlags. Only bits covered by the mask * should be tested. * @since 1.4 */ public static final int FLAG_MASK = FLAG_HAS_TRANSFORMS | FLAG_HAS_POSITION_ADJUSTMENTS | FLAG_RUN_RTL | FLAG_COMPLEX_GLYPHS; /** * Returns an array of glyph positions for the specified glyphs. * This method is used for convenience and performance when * processing glyph positions. * If no array is passed in, a new array is created. * Even numbered array entries beginning with position zero are the X * coordinates of the glyph numbered beginGlyphIndex + position/2. * Odd numbered array entries beginning with position one are the Y * coordinates of the glyph numbered beginGlyphIndex + (position-1)/2. * If beginGlyphIndex equals the number of of glyphs in * this GlyphVector, this method gets the position after * the last glyph and this position is used to define the advance of * the entire GlyphVector. * @param beginGlyphIndex the index at which to begin retrieving * glyph positions * @param numEntries the number of glyphs to retrieve * @param positionReturn the array that receives the glyph positions * and is then returned. * @return an array of glyph positions specified by * beginGlyphIndex and numEntries. * @throws IllegalArgumentException if numEntries is * less than 0 * @throws IndexOutOfBoundsException if beginGlyphIndex * is less than 0 * @throws IndexOutOfBoundsException if the sum of * beginGlyphIndex and numEntries * is greater than the number of glyphs in this * GlyphVector plus one */ public abstract float[] getGlyphPositions(int beginGlyphIndex, int numEntries, float[] positionReturn); /** * Returns the logical bounds of the specified glyph within this * GlyphVector. * These logical bounds have a total of four edges, with two edges * parallel to the baseline under the glyph's transform and the other two * edges are shared with adjacent glyphs if they are present. This * method is useful for hit-testing of the specified glyph, * positioning of a caret at the leading or trailing edge of a glyph, * and for drawing a highlight region around the specified glyph. * @param glyphIndex the index into this GlyphVector * that corresponds to the glyph from which to retrieve its logical * bounds * @return a Shape that is the logical bounds of the * glyph at the specified glyphIndex. * @throws IndexOutOfBoundsException if glyphIndex * is less than 0 or greater than or equal to the number * of glyphs in this GlyphVector * @see #getGlyphVisualBounds */ public abstract Shape getGlyphLogicalBounds(int glyphIndex); /** * Returns the visual bounds of the specified glyph within the * GlyphVector. * The bounds returned by this method is positioned around the * origin of each individual glyph. * @param glyphIndex the index into this GlyphVector * that corresponds to the glyph from which to retrieve its visual * bounds * @return a Shape that is the visual bounds of the * glyph at the specified glyphIndex. * @throws IndexOutOfBoundsException if glyphIndex * is less than 0 or greater than or equal to the number * of glyphs in this GlyphVector * @see #getGlyphLogicalBounds */ public abstract Shape getGlyphVisualBounds(int glyphIndex); /** * Returns the pixel bounds of the glyph at index when this * GlyphVector is rendered in a Graphics with the * given FontRenderContext at the given location. The * renderFRC need not be the same as the * FontRenderContext of this * GlyphVector, and can be null. If it is null, the * FontRenderContext of this GlyphVector * is used. The default implementation returns the visual bounds of the glyph, * offset to x, y and rounded out to the next integer value, and * ignores the FRC. Subclassers should override this method. * @param index the index of the glyph. * @param renderFRC the FontRenderContext of the Graphics. * @param x, y the position at which to render this GlyphVector. * @return a Rectangle bounding the pixels that would be affected. * @since 1.4 */ public Rectangle getGlyphPixelBounds(int index, FontRenderContext renderFRC, float x, float y) { Rectangle2D rect = getGlyphVisualBounds(index).getBounds2D(); int l = (int)Math.floor(rect.getX() + x); int t = (int)Math.floor(rect.getY() + y); int r = (int)Math.ceil(rect.getMaxX() + x); int b = (int)Math.ceil(rect.getMaxY() + y); return new Rectangle(l, t, r - l, b - t); } /** * Returns the metrics of the glyph at the specified index into * this GlyphVector. * @param glyphIndex the index into this GlyphVector * that corresponds to the glyph from which to retrieve its metrics * @return a {@link GlyphMetrics} object that represents the * metrics of the glyph at the specified glyphIndex * into this GlyphVector. * @throws IndexOutOfBoundsException if glyphIndex * is less than 0 or greater than or equal to the number * of glyphs in this GlyphVector */ public abstract GlyphMetrics getGlyphMetrics(int glyphIndex); /** * Returns the justification information for the glyph at * the specified index into this GlyphVector. * @param glyphIndex the index into this GlyphVector * that corresponds to the glyph from which to retrieve its * justification properties * @return a {@link GlyphJustificationInfo} object that * represents the justification properties of the glyph at the * specified glyphIndex into this * GlyphVector. * @throws IndexOutOfBoundsException if glyphIndex * is less than 0 or greater than or equal to the number * of glyphs in this GlyphVector */ public abstract GlyphJustificationInfo getGlyphJustificationInfo(int glyphIndex); // // general utility methods // /** * Tests if the specified GlyphVector exactly * equals this GlyphVector. * @param set the specified GlyphVector to test * @return true if the specified * GlyphVector equals this GlyphVector; * false otherwise. */ public abstract boolean equals(GlyphVector set); }