home *** CD-ROM | disk | FTP | other *** search
/ Java 1.2 How-To / JavaHowTo.iso / 3rdParty / jbuilder / unsupported / JDK1.2beta3 / SOURCE / SRC.ZIP / java / awt / font / GlyphSet.java < prev    next >
Encoding:
Java Source  |  1998-03-20  |  19.9 KB  |  555 lines

  1. /*
  2.  * @(#)GlyphSet.java    1.26 98/03/18
  3.  *
  4.  * Copyright 1997, 1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. /*
  16.  * (C) Copyright Taligent, Inc. 1996 - 1997, All Rights Reserved
  17.  * (C) Copyright IBM Corp. 1996 - 1998, All Rights Reserved
  18.  *
  19.  * The original version of this source code and documentation is
  20.  * copyrighted and owned by Taligent, Inc., a wholly-owned subsidiary
  21.  * of IBM. These materials are provided under terms of a License
  22.  * Agreement between Taligent and Sun. This technology is protected
  23.  * by multiple US and International patents.
  24.  *
  25.  * This notice and attribution to Taligent may not be removed.
  26.  * Taligent is a registered trademark of Taligent, Inc.
  27.  *
  28.  */
  29.  
  30. package java.awt.font;
  31.  
  32. import java.text.AttributedCharacterIterator;
  33. import java.awt.Graphics2D;
  34. import java.awt.Font;
  35. import java.awt.geom.Rectangle2D;
  36.  
  37. /**
  38.  * GlyphSet is a graphical representation of text with bidirectional ordering.
  39.  * Instances of GlyphSet are
  40.  * produced by Font (or subclasses of Font) and contain a sequence of integer
  41.  * glyph codes, used by the Font to represent text graphically.  The glyph codes
  42.  * are not characters;  they are meaningful only
  43.  * to the Font which produced them.  GlyphSets may be displayed on a graphics
  44.  * device.  Metrics for the entire GlyphSet or for individual glyphs may be
  45.  * queried.  Additionally, new GlyphSets may be produced from old ones for
  46.  * operations such as taking a subset of a glyphset, justification, changing
  47.  * a single character in the source text, and setting the direction of the
  48.  * glyphs in a GlyphSet.
  49.  * <p>
  50.  * GlyphSets are immutable;  once created, their state never changes.  In particular,
  51.  * changes to the text from which they were created do not affect existing GlyphSets.
  52.  * <p>
  53.  * The glyphs in a GlyphSet are stored in <em>logical order</em>;  that is, they
  54.  * are stored in the same order as the characters from which they were generated.
  55.  * GlyphSets also maintain a <em>visual order</em> for their glyphs.  The visual
  56.  * order is the order, from left to right, in which the glyphs will be displayed.
  57.  * For text with right-to-left or bidirectional ordering, the logical order will
  58.  * not be the same as the visual order.  Glyphs are available in logical order
  59.  * directly from the GlyphSet.  Additionally, <code>visualToLogicalIndex</code>
  60.  * will convert a visual position to a logical position.
  61.  * <p>
  62.  * A GlyphSet may contain more glyphs
  63.  * than the number of characters in the sequence it represents (but never less).
  64.  * Methods on GlyphSet which return information on glyphs require a glyph index.  Other
  65.  * methods on GlyphSet are commonly associated with text editing (such as inserting or
  66.  * deleting a character, or taking a subset).  These operations used character indices.
  67.  * <p>
  68.  * <strong>Example</strong>:
  69.  * <p>
  70.  * Examine glyphs in visual order
  71.  * <blockquote><pre>
  72.  * GlyphSet glyphSet = ...;
  73.  * for (int i=0; i < getNumGlyphs(); i++) {
  74.  *     int logIndex = glyphSet.visualToLogicalIndex(i);
  75.  *     int glyphCode = glyphSet.getGlyphCode(logIndex);
  76.  *     // do something with glyphCode...
  77.  * }
  78.  * </blockquote></pre>
  79.  * @see Font
  80.  * @see GlyphMetrics
  81.  * @see TextLayout
  82.  */
  83.  
  84. public abstract class GlyphSet implements Cloneable {
  85.     /**
  86.      * Return the advance of the glyphset.
  87.      */
  88.     public abstract float getAdvance();
  89.  
  90.     /**
  91.      * Return the ascent of the glyphset relative to the baseline.
  92.      *
  93.      * This is the distance above (to the right of) the baseline.  
  94.      * The ascent is always positive or zero.
  95.      * @see #getBaseline
  96.      */
  97.     public abstract float getAscent();
  98.  
  99.     /**
  100.      * return the descent of the glyphset relative to the baseline.
  101.      *
  102.      * This is the distance below (to the left of) the baseline.  
  103.      * The descent is always positive or zero.
  104.      * @see #getBaseline
  105.      */
  106.     public abstract float getDescent();
  107.  
  108.     /**
  109.      * Return the font that created this glyphset.
  110.      */
  111.     public abstract Font getFont();
  112.  
  113.     /**
  114.      * Return the number of glyphs in this glyphset.
  115.      */
  116.     public abstract int getNumGlyphs();
  117.  
  118.     /**
  119.      * Return the number of characters represented by this glyphset.
  120.      *
  121.      * Some fonts may use several glyphs to represent a single 
  122.      * character.  There are never fewer glyphs than characters.  
  123.      * Glyphs representing more than one character are always followed 
  124.      * (logically) by an invisible combining glyph for each additional
  125.      * character.
  126.      */
  127.     public abstract int getNumCharacters();
  128.  
  129.     /**
  130.      * Return the glyphcode at the given logical position in this glyphset.
  131.      *
  132.      * @see #getNumGlyphs
  133.      */
  134.     public abstract int getGlyphCode(int index);
  135.  
  136.     /**
  137.      * Return the baseline used by this glyphset.  All glyphs in a single
  138.      * glyphset align to the same baseline.
  139.      * @see Font#getBaselineFor
  140.      */
  141.     public abstract byte getBaseline();
  142.  
  143.     /**
  144.      * Return the x position of the first visual glyph in the glyphset.
  145.      *
  146.      * The first visual glyph in the glyphset is offset by x, y from the
  147.      * origin of the glyphset.  This supports attributes like superscript.
  148.      * @see #getYAdjust
  149.      */
  150.     public abstract float getXAdjust();
  151.  
  152.     /**
  153.      * Return the x-direction advance of the glyph at the given logical
  154.      * position.
  155.      * @see #getGlyphYAdvance
  156.      * @see #getNumGlyphs
  157.      */
  158.     public abstract float getGlyphXAdvance(int index);
  159.  
  160.     /**
  161.      * Return the y position of the first visual glyph in the glyphset.
  162.      *
  163.      * The first visual glyph in the glyphset is offset by x, y from the
  164.      * origin of the glyphset.  This supports attributes like superscript.
  165.      * @see #getXAdjust
  166.      */
  167.     public abstract float getYAdjust();
  168.  
  169.     /**
  170.      * Return the y-direction advance of the glyph at the given logical
  171.      * position.
  172.      * @see #getGlyphXAdvance
  173.      * @see #getNumGlyphs
  174.      */
  175.     public abstract float getGlyphYAdvance(int index);
  176.  
  177.     /**
  178.      * Return the advance for the glyph at the given logical position.  
  179.      * The X-advance is returned on a horizontal line;  the Y-advance is 
  180.      * returned on a vertical line.
  181.      */
  182.     public abstract float getGlyphAdvance(int index);
  183.  
  184.     /**
  185.      * Map from visual position to logical position.
  186.      *
  187.      * For example, visualToLogicalIndex(0) = 5 means that the first 
  188.      * glyph drawn is at position five in the glyphCodes, levels, and 
  189.      * advances arrays.
  190.      * @see #getNumGlyphs
  191.      */
  192.     public abstract int visualToLogicalIndex(int index);
  193.  
  194.     /**
  195.      * Return the bidirection level of the glyph at the given logical position.
  196.      *
  197.      * Glyphs whose level is even are left to right (top to bottom), 
  198.      * glyphs whose level is odd are right to left (bottom to top).
  199.      * @see #getNumGlyphs
  200.      */
  201.     public abstract byte getLevel(int index);
  202.  
  203.     /**
  204.      * Return true if every glyph in the glyphset is left-to-right, and
  205.      * the glyphs all run from left to right.
  206.      * @see #getLevel
  207.      */
  208.     public abstract boolean isCompletelyLTR();
  209.  
  210.     /**
  211.      * Return a justified copy of this glyphset.
  212.      * @param deltas an array of amounts by which to change the left
  213.      * and right sides of each glyph, in visual order.  The array has 
  214.      * at least twice as many entries as there are glyphs in the glyphset.
  215.      *  For example, deltas[index] is the delta for the left side of
  216.      * the visually leftmost glyph, deltas[index+1] is for the right side 
  217.      * of the visually leftmost glyph, deltas[index+2] is for the left side
  218.      * of the visually second leftmost glyph, and so on.
  219.      * @param index the starting position in the deltas array. It 
  220.      * corresponds to the left side of the leftmost glyph.
  221.      * @param shouldRejustify an array containing a single input/output 
  222.      * boolean value.  On entry, it indicates whether the returned glyphset
  223.      * is allowed to cause rejustification, for example, if a ligature can
  224.      * be formed or broken.  On exit, it indicates whether the returned
  225.      * glyphset will require rejustification (for example, due to the 
  226.      * formation or removal of a ligature).
  227.      */
  228.     public abstract GlyphSet applyJustification(float[] deltas, 
  229.         int index, boolean[] flags);
  230.  
  231.     /**
  232.      * Return the sum of the advances for the glyphs corresponding to 
  233.      * characters in logical positions from start up to limit.  Note these
  234.      * are character indices, not glyph indices.  They will be mapped
  235.      * internally to glyph indices.
  236.      *
  237.      * @param start the character index at which to start measuring
  238.      * @param limit the character index at which to stop measuring
  239.      */
  240.     public abstract float getAdvanceBetween(int start, int limit);
  241.  
  242.     /**
  243.      * Return the logical position of a possible break.  This adds up 
  244.      * advances of glyphs in logical order starting from the glyph for the
  245.      * character at start, stopping before the first spacing glyph whose
  246.      * advance would cause hitAdvance to be exceeded.  The character 
  247.      * position of that glyph is returned.  If no glyph would reach the 
  248.      * hitAdvance, the number of characters in the set is returned.
  249.      * This will not break between combining or component glyphs and their 
  250.      * base glyph.
  251.      */
  252.     public abstract int getLineBreakIndex(int start, float hitAdvance);
  253.  
  254.     /**
  255.      * Generate a GlyphSet that contains the subset of this from logical 
  256.      * start up to limit.  The new glyphset shares the same baseline, 
  257.      * xAdjust, and yAdjust as the previous one.
  258.      * @param start the character index where the subset will begin
  259.      * @param limit the character index immediately after the end of 
  260.      * the subset
  261.      */
  262.     public abstract GlyphSet subset(int start, int limit);
  263.  
  264.     /**
  265.      * Return a new GlyphSet which is an incremental modification of this 
  266.      * one.
  267.      *
  268.      * This glyphset must have been generated from text identical to
  269.      * newText, with exactly one difference: an inserted character at 
  270.      * insertPos at newText.
  271.      *
  272.      * @param newText the text for the new glyphset.  This represents
  273.      * the text after the insertion occurred.  The new glyphset will
  274.      * represent the text beginning at start, up to (but not including) 
  275.      * limit.
  276.      * @param start the start of the subrange in newText for the glyphset
  277.      * @param limit the limit of the subrange in newText for the glyphset, 
  278.      * including the inserted character.
  279.      * @param insertPos the character position in the glyphset at which 
  280.      * the single character was inserted.
  281.      * @param order the logical-to-visual mapping array for newText.  
  282.      * If null, left-to-right is assumed.
  283.      * @param levels the bidirection level of each character in newText.
  284.      * If null, all levels are assumed to be 0.
  285.      * @return a new GlyphSet representing newText.
  286.      */
  287.     public abstract GlyphSet insertChar(AttributedCharacterIterator newText,
  288.         int start, int limit, int insertPos, int[] order, byte[] levels);
  289.  
  290.     /**
  291.      * Return a new GlyphSet which is an incremental modification of this
  292.      * one.
  293.      *
  294.      * This glyphset must have been generated from text identical to newText,
  295.      * with exactly one difference: a deleted character at deletePos at 
  296.      * newText.
  297.      *
  298.      * @param newText the text for the new glyphset.  This represents the
  299.      * text after the deletion occurred.  The new glyphset will represent 
  300.      * the text beginning at start, up to (but not including) limit.
  301.      * @param start the start of the subrange in newText for the glyphset.
  302.      * @param limit the limit of the subrange in newText for the glyphset,
  303.      * not including the deleted character.
  304.      * @param deletePos the character position in the glyphset at which the 
  305.      * single character was deleted.
  306.      * @param order the logical-to-visual mapping array for newText.  
  307.      * If null, left-to-right is assumed.
  308.      * @param levels the bidirection level of each character in newText.
  309.      * If null, all levels are assumed to be 0.
  310.      * @return a new GlyphSet representing newText.
  311.      */
  312.     public abstract GlyphSet deleteChar(AttributedCharacterIterator newText,
  313.         int start, int limit, int deletePos, int[] order, byte[] levels);
  314.  
  315.     /**
  316.      * Reshape a glyph set after a change to neighboring text.
  317.      *
  318.      * If this GlyphSet's font does context-sensitive glyph shaping, then 
  319.      * a change in a character can affect the glyphs before and after it.
  320.      * This method allows the Font to inspect the new text and (possibly) 
  321.      * return a new glyphset with different shaping.  This method is used
  322.      * in conjunction with insertChar and deleteChar.
  323.      * @param newText styled text represented by this GlyphSet over the
  324.      * range start, limit.
  325.      * @param start the start of the range in newText represented by this
  326.      * GlyphSet.
  327.      * @param limit the limit of the range in newText represented by this 
  328.      * GlyphSet.
  329.      * @param changePos the position in newText that has changed since this
  330.      * GlyphSet was created.  This parameter must be either start-1 or limit.
  331.      * @param order the logical-to-visual mapping array for newText.  
  332.      * If null, left-to-right is assumed.
  333.      * @param levels the bidirection level of each character in newText.
  334.      * If null, all levels are assumed to be 0.
  335.      * @return a GlyphSet representing newText over the range start, limit, 
  336.      * with updated glyph shaping (if any).
  337.      * @see #insertChar
  338.      * @see #deleteChar
  339.      */
  340.     public abstract GlyphSet reshape(AttributedCharacterIterator newText,
  341.         int start, int limit, int changePos, int[] order, byte[] levels);
  342.  
  343.     /**
  344.      * Draw this glyphset at the provided position.
  345.      */
  346.     public abstract void draw(Graphics2D graphics, float x, float y);
  347.  
  348.     /**
  349.      * Return the bounds in which contains all of the bits drawn by
  350.      * this GlyphSet.
  351.      */
  352.     public abstract Rectangle2D getBounds();
  353.  
  354.     /**
  355.      * An argument to setDirection indicating LEFT_TO_RIGHT glyphs.
  356.      * @see #setDirection
  357.      */
  358.     public static final boolean LEFT_TO_RIGHT = true;
  359.  
  360.     /**
  361.      * An argument to setDirection indicating RIGHT_TO_LEFT glyphs.
  362.      * @see #setDirection
  363.      */
  364.     public static final boolean RIGHT_TO_LEFT = false;
  365.  
  366.     /**
  367.      * Return a GlyphSet identical to this one, except with all glyphs
  368.      * going in the same direction.
  369.      * @see #LEFT_TO_RIGHT
  370.      * @see #RIGHT_TO_LEFT
  371.      */
  372.     public abstract GlyphSet setDirection(boolean leftToRight);
  373.  
  374.     /**
  375.      * Return a hashCode for this glyphset.
  376.      */
  377.     public abstract int hashCode();
  378.  
  379.     /**
  380.      * Test for full equality.  Font, glyphs, baseline, advances, adjusts, 
  381.      * order, levels, count must all match.
  382.      */
  383.     public abstract boolean equals(GlyphSet set);
  384.  
  385.     /**
  386.      * Return the inverse array, source array must map 1-1
  387.      *
  388.      * i.e. if values[i] = j, then inverse[j] = i.
  389.      */
  390.     public static int[] getInverseOrder(int[] values) {
  391.         if (values == null) {
  392.             return null;
  393.         }
  394.  
  395.         int[] result = new int[values.length];
  396.         for (int i = 0; i < values.length; i++) {
  397.             result[values[i]] = i;
  398.         }
  399.  
  400.         return result;
  401.     }
  402.  
  403.     /**
  404.      * Compute a contiguous order for the range start, limit.
  405.      */
  406.     private static int[] computeContiguousOrder(int[] values, int start, 
  407.         int limit) {
  408.  
  409.         int[] result = new int[limit-start];
  410.         for (int i=0; i < result.length; i++) {
  411.             result[i] = i + start;
  412.         }
  413.  
  414.         // now we'll sort result[], with the following comparison:
  415.         // result[i] lessthan result[j] iff values[result[i]] < values[result[j]]
  416.  
  417.         // selection sort for now;  use more elaborate sorts if desired
  418.         for (int i=0; i < result.length-1; i++) {
  419.             int minIndex = i;
  420.             int currentValue = values[result[minIndex]];
  421.             for (int j=i; j < result.length; j++) {
  422.                 if (values[result[j]] < currentValue) {
  423.                     minIndex = j;
  424.                     currentValue = values[result[minIndex]];
  425.                 }
  426.             }
  427.             int temp = result[i];
  428.             result[i] = result[minIndex];
  429.             result[minIndex] = temp;
  430.         }
  431.  
  432.         // shift result by start:
  433.         if (start != 0) {
  434.             for (int i=0; i < result.length; i++) {
  435.                 result[i] -= start;
  436.             }
  437.         }
  438.  
  439.         // next, check for canonical order:
  440.         int k;
  441.         for (k=0; k < result.length; k++) {
  442.             if (result[k] != k) {
  443.                 break;
  444.             }
  445.         }
  446.  
  447.         if (k == result.length) {
  448.             return null;
  449.         }
  450.  
  451.         // now return inverse of result:
  452.         return getInverseOrder(result);
  453.     }
  454.  
  455.     /**
  456.      * Return an array containing contiguous values from 0 to length 
  457.      * having the same ordering as the source array. If this would be
  458.      * a canonical ltr ordering, return null.  values[] is NOT
  459.      * required to be a permutation.
  460.      */
  461.     public static int[] getContiguousOrder(int[] values) {
  462.         if (values != null) {
  463.             return computeContiguousOrder(values, 0, values.length);
  464.         }
  465.  
  466.         return null;
  467.     }
  468.  
  469.     /**
  470.      * Return an array containing the values from start up to limit, 
  471.      * normalized to fall within the range from 0 up to limit - start.  
  472.      * If this would be a canonical ltr ordering, return null.
  473.      * NOTE: This method assumes that values[] is a permutation 
  474.      * generated from levels[].
  475.      */
  476.     public static int[] getNormalizedOrder(int[] values, byte[] levels, 
  477.         int start, int limit) {
  478.  
  479.     if (values != null) {
  480.         if (start != 0 || limit != values.length) {
  481.             // levels optimization
  482.             boolean copyRange, canonical;
  483.             byte primaryLevel;
  484.  
  485.                 if (levels == null) {
  486.                     primaryLevel = (byte) 0x0;
  487.                     copyRange = true;
  488.                     canonical = true;
  489.                 }
  490.                 else {
  491.                 if (levels[start] == levels[limit-1]) {
  492.                     primaryLevel = levels[start];
  493.                     canonical = (primaryLevel & (byte)0x1) == 0;
  494.  
  495.                     // scan for levels below primary
  496.                     int i;
  497.                     for (i=start; i < limit; i++) {
  498.                         if (levels[i] < primaryLevel) {
  499.                             break;
  500.                         }
  501.                         if (canonical) {
  502.                             canonical = levels[i] == primaryLevel;
  503.                         }
  504.                     }
  505.  
  506.                     copyRange = (i == limit);
  507.                 }
  508.                 else {
  509.                     copyRange = false;
  510.  
  511.                     // these don't matter;  but the compiler cares:
  512.                     primaryLevel = (byte) 0x0;
  513.                     canonical = false;
  514.                 }
  515.             }
  516.  
  517.             if (copyRange) {
  518.                 if (canonical) {
  519.                     return null;
  520.                 }
  521.  
  522.                 int[] result = new int[limit-start];
  523.                 int baseValue;
  524.  
  525.                 if ((primaryLevel & (byte)0x1) != 0) {
  526.                     baseValue = values[limit-1];
  527.                 } else {
  528.                     baseValue = values[start];
  529.                 }
  530.  
  531.                 if (baseValue == 0) {
  532.                     System.arraycopy(values, start, result, 0, limit-start);
  533.                 }
  534.                 else {
  535.                     for (int j=0; j < result.length; j++) {
  536.                         result[j] = values[j+start] - baseValue;
  537.                     }
  538.                 }
  539.  
  540.                 return result;
  541.             }
  542.                 else {
  543.                    return computeContiguousOrder(values, start, limit);
  544.                 }
  545.             }
  546.         else {
  547.         return values;
  548.             }
  549.     }
  550.  
  551.         return null;
  552.     }
  553.     public abstract int[] getGlyphCodes();
  554. }
  555.