/*
 * Copyright 1998-2005 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */
/*
 *
 * (C) Copyright IBM Corp. 1998-2003 - All Rights Reserved
 */

package sun.font;

import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;

import java.awt.font.FontRenderContext;
import java.awt.font.GlyphJustificationInfo;
import java.awt.font.GlyphMetrics;
import java.awt.font.LineMetrics;
import java.awt.font.TextAttribute;

import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;

import java.util.Map;

/**
 * Default implementation of ExtendedTextLabel.
 */

// {jbr} I made this class package-private to keep the
// Decoration.Label API package-private.

/* public */
class ExtendedTextSourceLabel extends ExtendedTextLabel implements Decoration.Label {

  TextSource source;
  private Decoration decorator;

  // caches
  private Font font;
  private AffineTransform baseTX;
  private CoreMetrics cm;

  Rectangle2D lb;
  Rectangle2D ab;
  Rectangle2D vb;
  Rectangle2D ib;
  StandardGlyphVector gv;
  float[] charinfo;

  /**
   * Create from a TextSource.
   */
  public ExtendedTextSourceLabel(TextSource source, Decoration decorator) {
    this.source = source;
    this.decorator = decorator;
    finishInit();
  }

  /**
   * Create from a TextSource, optionally using cached data from oldLabel starting at the offset.
   * If present oldLabel must have been created from a run of text that includes the text used in
   * the new label.  Start in source corresponds to logical character offset in oldLabel.
   */
  public ExtendedTextSourceLabel(TextSource source, ExtendedTextSourceLabel oldLabel, int offset) {
    // currently no optimization.
    this.source = source;
    this.decorator = oldLabel.decorator;
    finishInit();
  }

  private void finishInit() {
    font = source.getFont();

    Map<TextAttribute, ?> atts = font.getAttributes();
    baseTX = AttributeValues.getBaselineTransform(atts);
    if (baseTX == null){
        cm = source.getCoreMetrics();
    } else {
      AffineTransform charTX = AttributeValues.getCharTransform(atts);
      if (charTX == null) {
          charTX = new AffineTransform();
      }
      font = font.deriveFont(charTX);

      LineMetrics lm = font.getLineMetrics(source.getChars(), source.getStart(),
          source.getStart() + source.getLength(), source.getFRC());
      cm = CoreMetrics.get(lm);
    }
  }


  // TextLabel API

  public Rectangle2D getLogicalBounds() {
    return getLogicalBounds(0, 0);
  }

  public Rectangle2D getLogicalBounds(float x, float y) {
    if (lb == null) {
      lb = createLogicalBounds();
    }
    return new Rectangle2D.Float((float)(lb.getX() + x),
                                 (float)(lb.getY() + y),
                                 (float)lb.getWidth(),
                                 (float)lb.getHeight());
  }

    public float getAdvance() {
        if (lb == null) {
            lb = createLogicalBounds();
        }
        return (float)lb.getWidth();
    }

  public Rectangle2D getVisualBounds(float x, float y) {
    if (vb == null) {
      vb = decorator.getVisualBounds(this);
    }
    return new Rectangle2D.Float((float)(vb.getX() + x),
                                 (float)(vb.getY() + y),
                                 (float)vb.getWidth(),
                                 (float)vb.getHeight());
  }

  public Rectangle2D getAlignBounds(float x, float y) {
    if (ab == null) {
      ab = createAlignBounds();
    }
    return new Rectangle2D.Float((float)(ab.getX() + x),
                                 (float)(ab.getY() + y),
                                 (float)ab.getWidth(),
                                 (float)ab.getHeight());

  }

  public Rectangle2D getItalicBounds(float x, float y) {
    if (ib == null) {
      ib = createItalicBounds();
    }
    return new Rectangle2D.Float((float)(ib.getX() + x),
                                 (float)(ib.getY() + y),
                                 (float)ib.getWidth(),
                                 (float)ib.getHeight());

  }

  public Rectangle getPixelBounds(FontRenderContext frc, float x, float y) {
      return getGV().getPixelBounds(frc, x, y);
  }

  public boolean isSimple() {
      return decorator == Decoration.getPlainDecoration() &&
             baseTX == null;
  }

  public AffineTransform getBaselineTransform() {
      return baseTX; // passing internal object, caller must not modify!
  }

  public Shape handleGetOutline(float x, float y) {
    return getGV().getOutline(x, y);
  }

  public Shape getOutline(float x, float y) {
    return decorator.getOutline(this, x, y);
  }

  public void handleDraw(Graphics2D g, float x, float y) {
    g.drawGlyphVector(getGV(), x, y);
  }

  public void draw(Graphics2D g, float x, float y) {
    decorator.drawTextAndDecorations(this, g, x, y);
  }

  /**
   * The logical bounds extends from the origin of the glyphvector to the
   * position at which a following glyphvector's origin should be placed.
   * We always assume glyph vectors are rendered from left to right, so
   * the origin is always to the left.
   * <p> On a left-to-right run, combining marks and 'ligatured away'
   * characters are to the right of their base characters.  The charinfo
   * array will record the character positions for these 'missing' characters
   * as being at the origin+advance of the base glyph, with zero advance.
   * (This is not necessarily the same as the glyph position, for example,
   * an umlaut glyph may have a position to the left of this point, it depends
   * on whether the font was designed so that such glyphs overhang to the left
   * of their origin, or whether it presumes some kind of kerning to position
   * the glyphs).  Anyway, the left of the bounds is the origin of the first
   * logical (leftmost) character, and the right is the origin + advance of the
   * last logical (rightmost) character.
   * <p> On a right-to-left run, these special characters are to the left
   * of their base characters.  Again, since 'glyph position' has been abstracted
   * away, we can use the origin of the leftmost character, and the origin +
   * advance of the rightmost character.
   * <p> On a mixed run (hindi) we can't rely on the first logical character
   * being the leftmost character.  However we can again rely on the leftmost
   * character origin and the rightmost character + advance.
   */
  protected Rectangle2D createLogicalBounds() {
    return getGV().getLogicalBounds();
  }

  public Rectangle2D handleGetVisualBounds() {
    return getGV().getVisualBounds();
  }

  /**
   * Like createLogicalBounds except ignore leading and logically trailing white space.
   * this assumes logically trailing whitespace is also visually trailing.
   * Whitespace is anything that has a zero visual width, regardless of its advance.
   * <p> We make the same simplifying assumptions as in createLogicalBounds, namely
   * that we can rely on the charinfo to shield us from any glyph positioning oddities
   * in the font that place the glyph for a character at other than the pos + advance
   * of the character to its left.  So we no longer need to skip chars with zero
   * advance, as their bounds (right and left) are already correct.
   */
  protected Rectangle2D createAlignBounds() {
    float[] info = getCharinfo();

    float al = 0f;
    float at = -cm.ascent;
    float aw = 0f;
    float ah = cm.ascent + cm.descent;

    boolean lineIsLTR = (source.getLayoutFlags() & 0x8) == 0;
    int rn = info.length - numvals;
    if (lineIsLTR) {
      while (rn > 0 && info[rn+visw] == 0) {
        rn -= numvals;
      }
    }

    if (rn >= 0) {
      int ln = 0;
      while (ln < rn && ((info[ln+advx] == 0) || (!lineIsLTR && info[ln+visw] == 0))) {
        ln += numvals;
      }

      al = Math.max(0f, info[ln+posx]);
      aw = info[rn+posx] + info[rn+advx] - al;
    }

    /*
      boolean lineIsLTR = source.lineIsLTR();
      int rn = info.length - numvals;
      while (rn > 0 && ((info[rn+advx] == 0) || (lineIsLTR && info[rn+visw] == 0))) {
      rn -= numvals;
      }

      if (rn >= 0) {
      int ln = 0;
      while (ln < rn && ((info[ln+advx] == 0) || (!lineIsLTR && info[ln+visw] == 0))) {
      ln += numvals;
      }

      al = Math.max(0f, info[ln+posx]);
      aw = info[rn+posx] + info[rn+advx] - al;
      }
      */

    return new Rectangle2D.Float(al, at, aw, ah);
  }

  public Rectangle2D createItalicBounds() {
    float ia = cm.italicAngle;

    Rectangle2D lb = getLogicalBounds();
    float l = (float)lb.getMinX();
    float t = -cm.ascent;
    float r = (float)lb.getMaxX();
    float b = cm.descent;
    if (ia != 0) {
        if (ia > 0) {
            l -= ia * (b - cm.ssOffset);
            r -= ia * (t - cm.ssOffset);
        } else {
            l -= ia * (t - cm.ssOffset);
            r -= ia * (b - cm.ssOffset);
        }
    }
    return new Rectangle2D.Float(l, t, r - l, b - t);
  }

  private final StandardGlyphVector getGV() {
    if (gv == null) {
      gv = createGV();
    }

    return gv;
  }

  protected StandardGlyphVector createGV() {
    FontRenderContext frc = source.getFRC();
    int flags = source.getLayoutFlags();
    char[] context = source.getChars();
    int start = source.getStart();
    int length = source.getLength();

    GlyphLayout gl = GlyphLayout.get(null); // !!! no custom layout engines
    gv = gl.layout(font, frc, context, start, length, flags, null); // ??? use textsource
    GlyphLayout.done(gl);

    return gv;
  }

  // ExtendedTextLabel API

  private static final int posx = 0,
    posy = 1,
    advx = 2,
    advy = 3,
    visx = 4,
    visy = 5,
    visw = 6,
    vish = 7;
  private static final int numvals = 8;

  public int getNumCharacters() {
    return source.getLength();
  }

  public CoreMetrics getCoreMetrics() {
    return cm;
  }

  public float getCharX(int index) {
    validate(index);
    return getCharinfo()[l2v(index) * numvals + posx];
  }

  public float getCharY(int index) {
    validate(index);
    return getCharinfo()[l2v(index) * numvals + posy];
  }

  public float getCharAdvance(int index) {
    validate(index);
    return getCharinfo()[l2v(index) * numvals + advx];
  }

  public Rectangle2D handleGetCharVisualBounds(int index) {
    validate(index);
    float[] charinfo = getCharinfo();
    index = l2v(index) * numvals;
    return new Rectangle2D.Float(
                                 charinfo[index + visx],
                                 charinfo[index + visy],
                                 charinfo[index + visw],
                                 charinfo[index + vish]);
  }

  public Rectangle2D getCharVisualBounds(int index, float x, float y) {

    Rectangle2D bounds = decorator.getCharVisualBounds(this, index);
    if (x != 0 || y != 0) {
        bounds.setRect(bounds.getX()+x,
                       bounds.getY()+y,
                       bounds.getWidth(),
                       bounds.getHeight());
    }
    return bounds;
  }

  private void validate(int index) {
    if (index < 0) {
      throw new IllegalArgumentException("index " + index + " < 0");
    } else if (index >= source.getLength()) {
      throw new IllegalArgumentException("index " + index + " < " + source.getLength());
    }
  }

  /*
    public int hitTestChar(float x, float y) {
    // !!! return index of char hit, for swing
    // result is negative for trailing-edge hits
    // no italics so no problem at margins.
    // for now, ignore y since we assume horizontal text

    // find non-combining char origin to right of x
    float[] charinfo = getCharinfo();

    int n = 0;
    int e = source.getLength();
    while (n < e && charinfo[n + advx] != 0 && charinfo[n + posx] > x) {
    n += numvals;
    }
    float rightx = n < e ? charinfo[n+posx] : charinfo[e - numvals + posx] + charinfo[e - numvals + advx];

    // find non-combining char to left of that char
    n -= numvals;
    while (n >= 0 && charinfo[n+advx] == 0) {
    n -= numvals;
    }
    float leftx = n >= 0 ? charinfo[n+posx] : 0;
    float lefta = n >= 0 ? charinfo[n+advx] : 0;

    n /= numvals;

    boolean left = true;
    if (x < leftx + lefta / 2f) {
    // left of prev char
    } else if (x < (leftx + lefta + rightx) / 2f) {
    // right of prev char
    left = false;
    } else {
    // left of follow char
    n += 1;
    }

    if ((source.getLayoutFlags() & 0x1) != 0) {
    n = getNumCharacters() - 1 - n;
    left = !left;
    }

    return left ? n : -n;
    }
    */

  public int logicalToVisual(int logicalIndex) {
    validate(logicalIndex);
    return l2v(logicalIndex);
  }

  public int visualToLogical(int visualIndex) {
    validate(visualIndex);
    return v2l(visualIndex);
  }

  public int getLineBreakIndex(int start, float width) {
    float[] charinfo = getCharinfo();
    int length = source.getLength();
    --start;
    while (width >= 0 && ++start < length) {
      float adv = charinfo[l2v(start) * numvals + advx];
      width -= adv;
    }

    return start;
  }

  public float getAdvanceBetween(int start, int limit) {
    float a = 0f;

    float[] charinfo = getCharinfo();
    --start;
    while (++start < limit) {
      a += charinfo[l2v(start) * numvals + advx];
    }

    return a;
  }

  public boolean caretAtOffsetIsValid(int offset) {
      // REMIND: improve this implementation

      // Ligature formation can either be done in logical order,
      // with the ligature glyph logically preceding the null
      // chars;  or in visual order, with the ligature glyph to
      // the left of the null chars.  This method's implementation
      // must reflect which strategy is used.

      if (offset == 0 || offset == source.getLength()) {
          return true;
      }
      char c = source.getChars()[source.getStart() + offset];
      if (c == '\t' || c == '\n' || c == '\r') { // hack
          return true;
      }
      int v = l2v(offset);

      // If ligatures are always to the left, do this stuff:
      //if (!(source.getLayoutFlags() & 0x1) == 0) {
      //    v += 1;
      //    if (v == source.getLength()) {
      //        return true;
      //    }
      //}

      return getCharinfo()[v * numvals + advx] != 0;
  }

  private final float[] getCharinfo() {
    if (charinfo == null) {
      charinfo = createCharinfo();
    }
    return charinfo;
  }

/*
* This takes the glyph info record obtained from the glyph vector and converts it into a similar record
* adjusted to represent character data instead.  For economy we don't use glyph info records in this processing.
*
* Here are some constraints:
* - there can be more glyphs than characters (glyph insertion, perhaps based on normalization, has taken place)
* - there can not be fewer glyphs than characters (0xffff glyphs are inserted for characters ligaturized away)
* - each glyph maps to a single character, when multiple glyphs exist for a character they all map to it, but
*   no two characters map to the same glyph
* - multiple glyphs mapping to the same character need not be in sequence (thai, tamil have split characters)
* - glyphs may be arbitrarily reordered (Indic reorders glyphs)
* - all glyphs share the same bidi level
* - all glyphs share the same horizontal (or vertical) baseline
* - combining marks visually follow their base character in the glyph array-- i.e. in an rtl gv they are
*   to the left of their base character-- and have zero advance.
*
* The output maps this to character positions, and therefore caret positions, via the following assumptions:
* - zero-advance glyphs do not contribute to the advance of their character (i.e. position is ignored), conversely
*   if a glyph is to contribute to the advance of its character it must have a non-zero (float) advance
* - no carets can appear between a zero width character and its preceeding character, where 'preceeding' is
*   defined logically.
* - no carets can appear within a split character
* - no carets can appear within a local reordering (i.e. Indic reordering, or non-adjacent split characters)
* - all characters lie on the same baseline, and it is either horizontal or vertical
* - the charinfo is in uniform ltr or rtl order (visual order), since local reorderings and split characters are removed
*
* The algorithm works in the following way:
* 1) we scan the glyphs ltr or rtl based on the bidi run direction
* 2) we can work in place, since we always consume a glyph for each char we write
*    a) if the line is ltr, we start writing at position 0 until we finish, there may be leftver space
*    b) if the line is rtl and 1-1, we start writing at position numChars/glyphs - 1 until we finish at 0
*    c) otherwise if we don't finish at 0, we have to copy the data down
* 3) we consume clusters in the following way:
*    a) the first element is always consumed
*    b) subsequent elements are consumed if:
*       i) their advance is zero
*       ii) their character index <= the character index of any character seen in this cluster
*       iii) the minimum character index seen in this cluster isn't adjacent to the previous cluster
*    c) character data is written as follows for horizontal lines (x/y and w/h are exchanged on vertical lines)
*       i) the x position is the position of the leftmost glyph whose advance is not zero
*       ii)the y position is the baseline
*       iii) the x advance is the distance to the maximum x + adv of all glyphs whose advance is not zero
*       iv) the y advance is the baseline
*       v) vis x,y,w,h tightly encloses the vis x,y,w,h of all the glyphs with nonzero w and h
* 4) we can make some simple optimizations if we know some things:
*    a) if the mapping is 1-1, unidirectional, and there are no zero-adv glyphs, we just return the glyphinfo
*    b) if the mapping is 1-1, unidirectional, we just adjust the remaining glyphs to originate at right/left of the base
*    c) if the mapping is 1-1, we compute the base position and advance as we go, then go back to adjust the remaining glyphs
*    d) otherwise we keep separate track of the write position as we do (c) since no glyph in the cluster may be in the
*    position we are writing.
*    e) most clusters are simply the single base glyph in the same position as its character, so we try to avoid
*    copying its data unnecessarily.
* 5) the glyph vector ought to provide access to these 'global' attributes to enable these optimizations.  A single
*    int with flags set is probably ok, we could also provide accessors for each attribute.  This doesn't map to
*    the GlyphMetrics flags very well, so I won't attempt to keep them similar.  It might be useful to add those
*    in addition to these.
*    int FLAG_HAS_ZERO_ADVANCE_GLYPHS = 1; // set if there are zero-advance glyphs
*    int FLAG_HAS_NONUNIFORM_ORDER = 2; // set if some glyphs are rearranged out of character visual order
*    int FLAG_HAS_SPLIT_CHARACTERS = 4; // set if multiple glyphs per character
*    int getDescriptionFlags(); // return an int containing the above flags
*    boolean hasZeroAdvanceGlyphs();
*    boolean hasNonuniformOrder();
*    boolean hasSplitCharacters();
*    The optimized cases in (4) correspond to values 0, 1, 3, and 7 returned by getDescriptionFlags().
*/
  protected float[] createCharinfo() {
    StandardGlyphVector gv = getGV();
    float[] glyphinfo = null;
    try {
        glyphinfo = gv.getGlyphInfo();
    }
    catch (Exception e) {
        System.out.println(source);
    }

    /*
    if ((gv.getDescriptionFlags() & 0x7) == 0) {
        return glyphinfo;
    }
    */

    int numGlyphs = gv.getNumGlyphs();
    int[] indices = gv.getGlyphCharIndices(0, numGlyphs, null);

    boolean DEBUG = false;
    if (DEBUG) {
      System.err.println("number of glyphs: " + numGlyphs);
      for (int i = 0; i < numGlyphs; ++i) {
        System.err.println("g: " + i +
            ", x: " + glyphinfo[i*numvals+posx] +
            ", a: " + glyphinfo[i*numvals+advx] +
            ", n: " + indices[i]);
      }
    }

    int minIndex = indices[0];  // smallest index seen this cluster
    int maxIndex = minIndex;    // largest index seen this cluster
    int nextMin = 0;            // expected smallest index for this cluster
    int cp = 0;                 // character position
    int cx = 0;                 // character index (logical)
    int gp = 0;                 // glyph position
    int gx = 0;                 // glyph index (visual)
    int gxlimit = numGlyphs;    // limit of gx, when we reach this we're done
    int pdelta = numvals;       // delta for incrementing positions
    int xdelta = 1;             // delta for incrementing indices

    boolean ltr = (source.getLayoutFlags() & 0x1) == 0;
    if (!ltr) {
        minIndex = indices[numGlyphs - 1];
        maxIndex = minIndex;
        nextMin  = 0; // still logical
        cp = glyphinfo.length - numvals;
        cx = 0; // still logical
        gp = glyphinfo.length - numvals;
        gx = numGlyphs - 1;
        gxlimit = -1;
        pdelta = -numvals;
        xdelta = -1;
    }

    /*
    // to support vertical, use 'ixxxx' indices and swap horiz and vertical components
    if (source.isVertical()) {
        iposx = posy;
        iposy = posx;
        iadvx = advy;
        iadvy = advx;
        ivisx = visy;
        ivisy = visx;
        ivish = visw;
        ivisw = vish;
    } else {
        // use standard values
    }
    */

    // use intermediates to reduce array access when we need to
    float cposl = 0, cposr = 0, cvisl = 0, cvist = 0, cvisr = 0, cvisb = 0;
    float baseline = 0;

    // record if we have to copy data even when no cluster
    boolean mustCopy = false;

    while (gx != gxlimit) {
        // start of new cluster
        boolean haveCopy = false;
        int clusterExtraGlyphs = 0;

        minIndex = indices[gx];
        maxIndex = minIndex;

        // advance to next glyph
        gx += xdelta;
        gp += pdelta;

 /*
        while (gx != gxlimit && (glyphinfo[gp + advx] == 0 ||
                           minIndex != nextMin || indices[gx] <= maxIndex)) {
  */
        while (gx != gxlimit &&
               ((glyphinfo[gp + advx] == 0) ||
               (minIndex != nextMin) ||
               (indices[gx] <= maxIndex) ||
               (maxIndex - minIndex > clusterExtraGlyphs))) {
            // initialize base data first time through, using base glyph
            if (!haveCopy) {
                int gps = gp - pdelta;

                cposl = glyphinfo[gps + posx];
                cposr = cposl + glyphinfo[gps + advx];
                cvisl = glyphinfo[gps + visx];
                cvist = glyphinfo[gps + visy];
                cvisr = cvisl + glyphinfo[gps + visw];
                cvisb = cvist + glyphinfo[gps + vish];

                haveCopy = true;
            }

            // have an extra glyph in this cluster
            ++clusterExtraGlyphs;

            // adjust advance only if new glyph has non-zero advance
            float radvx = glyphinfo[gp + advx];
            if (radvx != 0) {
                float rposx = glyphinfo[gp + posx];
                cposl = Math.min(cposl, rposx);
                cposr = Math.max(cposr, rposx + radvx);
            }

            // adjust visible bounds only if new glyph has non-empty bounds
            float rvisw = glyphinfo[gp + visw];
            if (rvisw != 0) {
                float rvisx = glyphinfo[gp + visx];
                float rvisy = glyphinfo[gp + visy];
                cvisl = Math.min(cvisl, rvisx);
                cvist = Math.min(cvist, rvisy);
                cvisr = Math.max(cvisr, rvisx + rvisw);
                cvisb = Math.max(cvisb, rvisy + glyphinfo[gp + vish]);
            }

            // adjust min, max index
            minIndex = Math.min(minIndex, indices[gx]);
            maxIndex = Math.max(maxIndex, indices[gx]);

            // get ready to examine next glyph
            gx += xdelta;
            gp += pdelta;
        }
        // done with cluster, gx and gp are set for next glyph

        if (DEBUG) {
            System.out.println("minIndex = " + minIndex + ", maxIndex = " + maxIndex);
        }

        nextMin = maxIndex + 1;

        // do common character adjustments
        glyphinfo[cp + posy] = baseline;
        glyphinfo[cp + advy] = 0;

        if (haveCopy) {
            // save adjustments to the base character
            glyphinfo[cp + posx] = cposl;
            glyphinfo[cp + advx] = cposr - cposl;
            glyphinfo[cp + visx] = cvisl;
            glyphinfo[cp + visy] = cvist;
            glyphinfo[cp + visw] = cvisr - cvisl;
            glyphinfo[cp + vish] = cvisb - cvist;

            // compare number of chars read with number of glyphs read.
            // if more glyphs than chars, set mustCopy to true, as we'll always have
            // to copy the data from here on out.
            if (maxIndex - minIndex < clusterExtraGlyphs) {
                mustCopy = true;
            }

            // Fix the characters that follow the base character.
            // New values are all the same.  Note we fix the number of characters
            // we saw, not the number of glyphs we saw.
            if (minIndex < maxIndex) {
                if (!ltr) {
                    // if rtl, characters to left of base, else to right.  reuse cposr.
                    cposr = cposl;
                }
                cvisr -= cvisl; // reuse, convert to deltas.
                cvisb -= cvist;

                int iMinIndex = minIndex, icp = cp / 8;

                while (minIndex < maxIndex) {
                    ++minIndex;
                    cx += xdelta;
                    cp += pdelta;

                    if (cp < 0 || cp >= glyphinfo.length) {
                        if (DEBUG) System.out.println("minIndex = " + iMinIndex + ", maxIndex = " + maxIndex + ", cp = " + icp);
                    }

                    glyphinfo[cp + posx] = cposr;
                    glyphinfo[cp + posy] = baseline;
                    glyphinfo[cp + advx] = 0;
                    glyphinfo[cp + advy] = 0;
                    glyphinfo[cp + visx] = cvisl;
                    glyphinfo[cp + visy] = cvist;
                    glyphinfo[cp + visw] = cvisr;
                    glyphinfo[cp + vish] = cvisb;
                }
            }

            // no longer using this copy
            haveCopy = false;
        } else if (mustCopy) {
            // out of synch, so we have to copy all the time now
            int gpr = gp - pdelta;

            glyphinfo[cp + posx] = glyphinfo[gpr + posx];
            glyphinfo[cp + advx] = glyphinfo[gpr + advx];
            glyphinfo[cp + visx] = glyphinfo[gpr + visx];
            glyphinfo[cp + visy] = glyphinfo[gpr + visy];
            glyphinfo[cp + visw] = glyphinfo[gpr + visw];
            glyphinfo[cp + vish] = glyphinfo[gpr + vish];
        }
        // else glyphinfo is already at the correct character position, and is unchanged, so just leave it

        // reset for new cluster
        cp += pdelta;
        cx += xdelta;
    }

    if (mustCopy && !ltr) {
        // data written to wrong end of array, need to shift down

        cp -= pdelta; // undo last increment, get start of valid character data in array
        System.arraycopy(glyphinfo, cp, glyphinfo, 0, glyphinfo.length - cp);
    }

    if (DEBUG) {
      char[] chars = source.getChars();
      int start = source.getStart();
      int length = source.getLength();
      System.out.println("char info for " + length + " characters");
      for(int i = 0; i < length * numvals;) {
        System.out.println(" ch: " + Integer.toHexString(chars[start + v2l(i / numvals)]) +
                           " x: " + glyphinfo[i++] +
                           " y: " + glyphinfo[i++] +
                           " xa: " + glyphinfo[i++] +
                           " ya: " + glyphinfo[i++] +
                           " l: " + glyphinfo[i++] +
                           " t: " + glyphinfo[i++] +
                           " w: " + glyphinfo[i++] +
                           " h: " + glyphinfo[i++]);
      }
    }

    return glyphinfo;
  }

  /**
   * Map logical character index to visual character index.
   * <p>
   * This ignores hindi reordering.  @see createCharinfo
   */
  protected int l2v(int index) {
    return (source.getLayoutFlags() & 0x1) == 0 ? index : source.getLength() - 1 - index;
  }

  /**
   * Map visual character index to logical character index.
   * <p>
   * This ignores hindi reordering.  @see createCharinfo
   */
  protected int v2l(int index) {
    return (source.getLayoutFlags() & 0x1) == 0 ? index : source.getLength() - 1 - index;
  }

  public TextLineComponent getSubset(int start, int limit, int dir) {
    return new ExtendedTextSourceLabel(source.getSubSource(start, limit-start, dir), decorator);
  }

  public String toString() {
    if (true) {
        return source.toString(source.WITHOUT_CONTEXT);
    }
    StringBuffer buf = new StringBuffer();
    buf.append(super.toString());
    buf.append("[source:");
    buf.append(source.toString(source.WITHOUT_CONTEXT));
    buf.append(", lb:");
    buf.append(lb);
    buf.append(", ab:");
    buf.append(ab);
    buf.append(", vb:");
    buf.append(vb);
    buf.append(", gv:");
    buf.append(gv);
    buf.append(", ci: ");
    if (charinfo == null) {
      buf.append("null");
    } else {
      buf.append(charinfo[0]);
      for (int i = 1; i < charinfo.length;) {
        buf.append(i % numvals == 0 ? "; " : ", ");
        buf.append(charinfo[i]);
      }
    }
    buf.append("]");

    return buf.toString();
  }

  //public static ExtendedTextLabel create(TextSource source) {
  //  return new ExtendedTextSourceLabel(source);
  //}

  public int getNumJustificationInfos() {
    return getGV().getNumGlyphs();
  }


  public void getJustificationInfos(GlyphJustificationInfo[] infos, int infoStart, int charStart, int charLimit) {
    // This simple implementation only uses spaces for justification.
    // Since regular characters aren't justified, we don't need to deal with
    // special infos for combining marks or ligature substitution glyphs.
    // added character justification for kanjii only 2/22/98

    StandardGlyphVector gv = getGV();

    float[] charinfo = getCharinfo();

    float size = gv.getFont().getSize2D();

    GlyphJustificationInfo nullInfo =
      new GlyphJustificationInfo(0,
                                 false, GlyphJustificationInfo.PRIORITY_NONE, 0, 0,
                                 false, GlyphJustificationInfo.PRIORITY_NONE, 0, 0);

    GlyphJustificationInfo spaceInfo =
      new GlyphJustificationInfo(size,
                                 true, GlyphJustificationInfo.PRIORITY_WHITESPACE, 0, size,
                                 true, GlyphJustificationInfo.PRIORITY_WHITESPACE, 0, size / 4f);

    GlyphJustificationInfo kanjiInfo =
      new GlyphJustificationInfo(size,
                                 true, GlyphJustificationInfo.PRIORITY_INTERCHAR, size, size,
                                 false, GlyphJustificationInfo.PRIORITY_NONE, 0, 0);

    char[] chars = source.getChars();
    int offset = source.getStart();

    // assume data is 1-1 and either all rtl or all ltr, for now

    int numGlyphs = gv.getNumGlyphs();
    int minGlyph = 0;
    int maxGlyph = numGlyphs;
    boolean ltr = (source.getLayoutFlags() & 0x1) == 0;
    if (charStart != 0 || charLimit != source.getLength()) {
      if (ltr) {
        minGlyph = charStart;
        maxGlyph = charLimit;
      } else {
        minGlyph = numGlyphs - charLimit;
        maxGlyph = numGlyphs - charStart;
      }
    }

    for (int i = 0; i < numGlyphs; ++i) {
      GlyphJustificationInfo info = null;
      if (i >= minGlyph && i < maxGlyph) {
        if (charinfo[i * numvals + advx] == 0) { // combining marks don't justify
          info = nullInfo;
        } else {
          int ci = v2l(i); // 1-1 assumption again
          char c = chars[offset + ci];
          if (Character.isWhitespace(c)) {
            info = spaceInfo;
            // CJK, Hangul, CJK Compatibility areas
          } else if (c >= 0x4e00 &&
                     (c < 0xa000) ||
                     (c >= 0xac00 && c < 0xd7b0) ||
                     (c >= 0xf900 && c < 0xfb00)) {
            info = kanjiInfo;
          } else {
            info = nullInfo;
          }
        }
      }
      infos[infoStart + i] = info;
    }
  }

  public TextLineComponent applyJustificationDeltas(float[] deltas, int deltaStart, boolean[] flags) {

    // when we justify, we need to adjust the charinfo since spaces
    // change their advances.  preserve the existing charinfo.

    float[] newCharinfo = (float[])getCharinfo().clone();

    // we only push spaces, so never need to rejustify
    flags[0] = false;

    // preserve the existing gv.

    StandardGlyphVector newgv = (StandardGlyphVector)getGV().clone();
    float[] newPositions = newgv.getGlyphPositions(null);
    int numGlyphs = newgv.getNumGlyphs();

    /*
    System.out.println("oldgv: " + getGV() + ", newgv: " + newgv);
    System.out.println("newpositions: " + newPositions);
    for (int i = 0; i < newPositions.length; i += 2) {
      System.out.println("[" + (i/2) + "] " + newPositions[i] + ", " + newPositions[i+1]);
    }

    System.out.println("deltas: " + deltas + " start: " + deltaStart);
    for (int i = deltaStart; i < deltaStart + numGlyphs; i += 2) {
      System.out.println("[" + (i/2) + "] " + deltas[i] + ", " + deltas[i+1]);
    }
    */

    char[] chars = source.getChars();
    int offset = source.getStart();

    // accumulate the deltas to adjust positions and advances.
    // handle whitespace by modifying advance,
    // handle everything else by modifying position before and after

    float deltaPos = 0;
    for (int i = 0; i < numGlyphs; ++i) {
      if (Character.isWhitespace(chars[offset + v2l(i)])) {
        newPositions[i*2] += deltaPos;

        float deltaAdv = deltas[deltaStart + i*2] + deltas[deltaStart + i*2 + 1];

        newCharinfo[i * numvals + posx] += deltaPos;
        newCharinfo[i * numvals + visx] += deltaPos;
        newCharinfo[i * numvals + advx] += deltaAdv;

        deltaPos += deltaAdv;
      } else {
        deltaPos += deltas[deltaStart + i*2];

        newPositions[i*2] += deltaPos;
        newCharinfo[i * numvals + posx] += deltaPos;
        newCharinfo[i * numvals + visx] += deltaPos;

        deltaPos += deltas[deltaStart + i*2 + 1];
      }
    }
    newPositions[numGlyphs * 2] += deltaPos;

    newgv.setGlyphPositions(newPositions);

    /*
    newPositions = newgv.getGlyphPositions(null);
    System.out.println(">> newpositions: " + newPositions);
    for (int i = 0; i < newPositions.length; i += 2) {
      System.out.println("[" + (i/2) + "] " + newPositions[i] + ", " + newPositions[i+1]);
    }
    */

    ExtendedTextSourceLabel result = new ExtendedTextSourceLabel(source, decorator);
    result.gv = newgv;
    result.charinfo = newCharinfo;

    return result;
  }
}
