Package org.pentaho.reporting.engine.classic.core.layout.text

Source Code of org.pentaho.reporting.engine.classic.core.layout.text.GlyphList$VirtualGlyph

/*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program 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 Lesser General Public License for more details.
*
* Copyright (c) 2001 - 2009 Object Refinery Ltd, Pentaho Corporation and Contributors..  All rights reserved.
*/

package org.pentaho.reporting.engine.classic.core.layout.text;

import org.pentaho.reporting.libraries.fonts.encoding.CodePointBuffer;
import org.pentaho.reporting.libraries.fonts.encoding.CodePointStream;
import org.pentaho.reporting.libraries.fonts.encoding.manual.Utf16LE;
import org.pentaho.reporting.libraries.fonts.text.Spacing;

/**
* Todo: Document Me
*
* @author Thomas Morgner
*/
public final class GlyphList
{
  protected static final int EXTRA_GLYPH_INFO = 7;

  private static class VirtualGlyph implements Glyph
  {
    private int index;
    private int spacingIndex;
    private int extraGlyphCount;
    private int[] glyphData;
    private GlyphList parent;

    private VirtualGlyph(final GlyphList parent)
    {
      this.parent = parent;
    }

    public void update(final int glyphDataIndex,
                       final int spacingIndex)
    {
      this.index = glyphDataIndex;
      this.spacingIndex = spacingIndex;
      this.glyphData = parent.getGlyphSequenceData();
      this.extraGlyphCount = glyphData[index];
    }

    public int getClassification()
    {
      return glyphData[index + 2];
    }

    public int[] getExtraChars()
    {
      if (extraGlyphCount == 0)
      {
        return GlyphList.EMPTY_INTS;
      }
      final int[] retal = new int[extraGlyphCount];
      System.arraycopy(glyphData, index + GlyphList.EXTRA_GLYPH_INFO + 1, retal, 0, extraGlyphCount);
      return retal;
    }

    public int getBaseLine()
    {
      return glyphData[index + 5];
    }

    public int getCodepoint()
    {
      return glyphData[index + GlyphList.EXTRA_GLYPH_INFO];
    }

    public int getBreakWeight()
    {
      return glyphData[index + 1];
    }

    public Spacing getSpacing()
    {
      final Spacing[] spacings1 = parent.getSpacings();
      return spacings1[spacingIndex];
    }

    public int getWidth()
    {
      return glyphData[index + 3];
    }

    public int getHeight()
    {
      return glyphData[index + 4];
    }

    public int getKerning()
    {
      return glyphData[index + 6];
    }
  }

  protected static final int[] EMPTY_INTS = new int[0];

  private int[] glyphSequenceData;
  private Spacing[] spacings;
  private int[] glyphIndices;
  private int glyphSequenceFill;
  private int glyphIncrement;
  private int size;
  private int spacerIncrement;
  private VirtualGlyph virtualGlyph;
  private boolean locked;

  private GlyphList()
  {
    this.virtualGlyph = new VirtualGlyph(this);
  }

  public GlyphList(final int spacerIncrement)
  {
    // this is a good enough default for all common unicode languages.
    this(spacerIncrement * (GlyphList.EXTRA_GLYPH_INFO + 1), spacerIncrement);
  }

  public GlyphList(final int glyphIncrement, final int spacerIncrement)
  {
    this.glyphIncrement = glyphIncrement;
    this.spacerIncrement = spacerIncrement;
    this.virtualGlyph = new VirtualGlyph(this);

    this.glyphIndices = new int[spacerIncrement];
    this.spacings = new Spacing[spacerIncrement];
    this.glyphSequenceData = new int[glyphIncrement];
  }

  protected int[] getGlyphSequenceData()
  {
    return glyphSequenceData;
  }

  protected Spacing[] getSpacings()
  {
    return spacings;
  }

  /**
   * Ensures, that the list backend can store at least <code>c</code> elements. This method does nothing, if the new
   * capacity is less than the current capacity.
   *
   * @param capacity the new capacity of the list.
   */
  private void ensureGlyphCapacity(final int capacity)
  {
    if (glyphSequenceData.length <= capacity)
    {
      final int[] newData = new int[Math.max(glyphSequenceData.length + glyphIncrement, capacity + 1)];
      System.arraycopy(glyphSequenceData, 0, newData, 0, glyphSequenceFill);
      glyphSequenceData = newData;
    }
  }

  private void ensureSpacerCapacity(final int capacity)
  {
    if (spacings.length <= capacity)
    {
      final Spacing[] newData = new Spacing[Math.max(spacings.length + spacerIncrement, capacity + 1)];
      System.arraycopy(spacings, 0, newData, 0, size);
      spacings = newData;

      final int[] newIndexData = new int[Math.max(glyphIndices.length + spacerIncrement, capacity + 1)];
      System.arraycopy(glyphIndices, 0, newIndexData, 0, size);
      glyphIndices = newIndexData;
    }
  }

  public void addGlyphData(final int[] rawCodepoints,
                           final int rawCodePointOffset,
                           final int rawCodePointLength,
                           final int breakWeight,
                           final int classification,
                           final Spacing spacing,
                           final int width,
                           final int height,
                           final int baseLine,
                           final int kerning)
  {
    if (locked)
    {
      throw new IllegalStateException();
    }
    ensureGlyphCapacity(glyphSequenceFill + rawCodePointLength + GlyphList.EXTRA_GLYPH_INFO);
    ensureSpacerCapacity(size + 1);

    final int glyphSequenceFill = this.glyphSequenceFill;
    glyphSequenceData[glyphSequenceFill] = rawCodePointLength - 1;
    glyphSequenceData[glyphSequenceFill + 1] = breakWeight;
    glyphSequenceData[glyphSequenceFill + 2] = classification;
    glyphSequenceData[glyphSequenceFill + 3] = width;
    glyphSequenceData[glyphSequenceFill + 4] = height;
    glyphSequenceData[glyphSequenceFill + 5] = baseLine;
    glyphSequenceData[glyphSequenceFill + 6] = kerning;
    if (rawCodePointLength == 1)
    {
      glyphSequenceData[glyphSequenceFill + GlyphList.EXTRA_GLYPH_INFO] = rawCodepoints[rawCodePointOffset];
    }
    else
    {
      System.arraycopy(rawCodepoints, rawCodePointOffset, glyphSequenceData,
          glyphSequenceFill + GlyphList.EXTRA_GLYPH_INFO, rawCodePointLength);
    }
    this.glyphSequenceFill = glyphSequenceFill + GlyphList.EXTRA_GLYPH_INFO + rawCodePointLength;
    glyphIndices[size] = glyphSequenceFill;
    spacings[size] = spacing;
    size += 1;
  }

  public Glyph getGlyph(final int index)
  {
    if (index >= size)
    {
      throw new IndexOutOfBoundsException();
    }
    if (index < 0)
    {
      throw new IndexOutOfBoundsException();
    }
    virtualGlyph.update(glyphIndices[index], index);
    return virtualGlyph;
  }

  public int getSize()
  {
    return size;
  }

  public GlyphList lock()
  {
    final GlyphList retval = new GlyphList();
    retval.spacerIncrement = 0;
    retval.glyphIncrement = 0;
    retval.locked = true;
    retval.glyphSequenceFill = glyphSequenceFill;
    retval.glyphSequenceData = new int[glyphSequenceFill];
    System.arraycopy(glyphSequenceData, 0, retval.glyphSequenceData, 0, glyphSequenceFill);

    retval.size = size;
    retval.spacings = new Spacing[size];
    retval.glyphIndices = new int[size];
    System.arraycopy(spacings, 0, retval.spacings, 0, size);
    System.arraycopy(glyphIndices, 0, retval.glyphIndices, 0, size);
    return retval;
  }

  public void clear()
  {
    size = 0;
    glyphSequenceFill = 0;
  }

  public void ensureSize(final int size)
  {
    ensureSpacerCapacity(size);
    ensureGlyphCapacity(size * 8);
  }

  public boolean isEmpty()
  {
    return size == 0;
  }

  public String getText(final int offset, final int length, final CodePointBuffer codePointBuffer)
  {
    if (length == 0)
    {
      return "";
    }

    codePointBuffer.setCursor(0);

    final CodePointStream cps = new CodePointStream(codePointBuffer, length);
    final int maxPos = offset + length;
    for (int i = offset; i < maxPos; i++)
    {
      final int glyphIndex = glyphIndices[i];
      final int glyphDataStart = glyphIndex + GlyphList.EXTRA_GLYPH_INFO;
      final int glyphDataEnd = glyphDataStart + glyphSequenceData[glyphIndex] + 1;
      for (int g = glyphDataStart; g < glyphDataEnd; g++)
      {
        cps.put(glyphSequenceData[g]);
      }
    }
    cps.close();
    return Utf16LE.getInstance().encodeString(codePointBuffer);
  }

  public String getGlyphAsString(final int index, final CodePointBuffer codePointBuffer)
  {
    codePointBuffer.setCursor(0);

    final CodePointStream cps = new CodePointStream(codePointBuffer, 5);
    final int glyphIndex = glyphIndices[index];
    final int glyphDataStart = glyphIndex + GlyphList.EXTRA_GLYPH_INFO;
    final int glyphDataEnd = glyphDataStart + glyphSequenceData[glyphIndex] + 1;
    for (int g = glyphDataStart; g < glyphDataEnd; g++)
    {
      cps.put(glyphSequenceData[g]);
    }
    cps.close();
    return Utf16LE.getInstance().encodeString(codePointBuffer);
  }

  public String toString()
  {
    return "GlyphList={text='" + getText(0, size, new CodePointBuffer(size)) + "'}";
  }
}
TOP

Related Classes of org.pentaho.reporting.engine.classic.core.layout.text.GlyphList$VirtualGlyph

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.