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

Source Code of org.pentaho.reporting.engine.classic.core.layout.model.RenderableText

/*
* 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 - 2013 Object Refinery Ltd, Pentaho Corporation and Contributors..  All rights reserved.
*/

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

import org.pentaho.reporting.engine.classic.core.ReportAttributeMap;
import org.pentaho.reporting.engine.classic.core.layout.model.context.NodeLayoutProperties;
import org.pentaho.reporting.engine.classic.core.layout.text.ExtendedBaselineInfo;
import org.pentaho.reporting.engine.classic.core.layout.text.Glyph;
import org.pentaho.reporting.engine.classic.core.layout.text.GlyphList;
import org.pentaho.reporting.engine.classic.core.metadata.ElementType;
import org.pentaho.reporting.engine.classic.core.style.StyleSheet;
import org.pentaho.reporting.engine.classic.core.util.InstanceID;
import org.pentaho.reporting.engine.classic.core.util.geom.StrictGeomUtility;
import org.pentaho.reporting.libraries.fonts.encoding.CodePointBuffer;
import org.pentaho.reporting.libraries.fonts.text.Spacing;
import org.pentaho.reporting.libraries.fonts.text.breaks.BreakOpportunityProducer;
import org.pentaho.reporting.libraries.fonts.tools.FontStrictGeomUtility;


/**
* The renderable text is a text chunk, enriched with layouting information, such as break opportunities, character
* sizes, kerning information and spacing information.
* <p/>
* Text is given as codepoints. Break opportunities are given as integer values, where zero forbids breaking, and higher
* values denote better breaks. Spacing and glyph sizes and kerning is given in micro-points; Spacing is the 'added'
* space between codepoints if text-justification is enabled.
* <p/>
* The text is computed as grapheme clusters; this means that several unicode codepoints may result in a single
* /virtual/ glyph/codepoint/character. (Example: 'A' + accent symbols). If the font supports Lithurges, these lithurges
* may also be represented as a single grapheme cluster (and thus behave unbreakable).
* <p/>
* Grapheme clusters with more than one unicode char have the size of that char added to the first codepoint, all
* subsequence codepoints of the same cluster have a size/kerning/etc of zero and are unbreakable.
* <p/>
* This text chunk is perfectly suitable for horizontal text, going either from left-to-right or right-to-left.
* (Breaking mixed text is up to the textfactory).
*
* @author Thomas Morgner
*/
public final class RenderableText extends RenderNode
{
  private static long conversionFactor;

  static
  {
    final long value = StrictGeomUtility.toInternalValue(1);
    conversionFactor = value / FontStrictGeomUtility.toInternalValue(1);
  }
 
  private GlyphList glyphs;
  private int offset;
  private int length;
  private int script;

  private long minimumWidth;
  private long preferredWidth;
  private boolean forceLinebreak;
  private ExtendedBaselineInfo baselineInfo;
  private boolean normalTextSpacing;

  public RenderableText(final StyleSheet layoutContext,
                        final ElementType elementType,
                        final InstanceID instanceID,
                        final ReportAttributeMap<Object> attributes,
                        final ExtendedBaselineInfo baselineInfo,
                        final GlyphList glyphs,
                        final int offset,
                        final int length,
                        final int script,
                        final boolean forceLinebreak)
  {
    super(new NodeLayoutProperties(layoutContext, attributes, instanceID, elementType));
    initialize(glyphs, offset, length, baselineInfo, script, forceLinebreak);
  }

  protected void initialize(final GlyphList glyphs,
                            final int offset,
                            final int length,
                            final ExtendedBaselineInfo baselineInfo,
                            final int script, final boolean forceLinebreak)
  {
    if (glyphs == null)
    {
      throw new NullPointerException();
    }
    if (forceLinebreak == false && length == 0)
    {
      throw new IllegalArgumentException("Do not create zero-length renderable text!");
    }
    if (glyphs.getSize() < (offset + length))
    {
      throw new IllegalArgumentException();
    }

    this.baselineInfo = baselineInfo;
    this.script = script;

    this.glyphs = glyphs;
    this.offset = offset;
    this.length = length;
    this.forceLinebreak = forceLinebreak;

    normalTextSpacing = true;
    long wordMinChunkWidth = 0;

//    long heightAbove = 0;
//    long heightBelow = 0;
    long minimumChunkWidth = 0;

    long realCharTotal = 0;
    long spacerMin = 0;
    long spacerMax = 0;
    long spacerOpt = 0;

    final int lastPos = Math.min(glyphs.getSize(), offset + length);
    for (int i = offset; i < lastPos; i++)
    {
      final Glyph glyph = glyphs.getGlyph(i);
      //      heightAbove = Math.max(glyph.getBaseLine(), heightAbove);
      //      heightBelow = Math.max(glyph.getHeight() - glyph.getBaseLine(), heightBelow);
      final int kerning = glyph.getKerning();
      final int width = glyph.getWidth();
      final long realCharSpace = convert(width - kerning);
      realCharTotal += realCharSpace;
      wordMinChunkWidth += realCharSpace;
      if (i != (lastPos - 1))
      {
        final Spacing spacing = glyph.getSpacing();
        spacerMax += spacing.getMaximum();
        spacerMin += spacing.getMinimum();
        spacerOpt += spacing.getOptimum();
        if (normalTextSpacing == true &&
            Spacing.EMPTY_SPACING.equals(spacing) == false)
        {
          normalTextSpacing = false;
        }

        wordMinChunkWidth += spacing.getMinimum();
      }

      if (glyph.getBreakWeight() > BreakOpportunityProducer.BREAK_CHAR)
      {
        minimumChunkWidth = Math.max(minimumChunkWidth, wordMinChunkWidth);
        wordMinChunkWidth = 0;

        // Paranoid sanity checks: The word- and linebreaks should have been
        // replaced by other definitions in the text factory.
        if (glyph.getBreakWeight() == BreakOpportunityProducer.BREAK_LINE)
        {
          throw new IllegalStateException("A renderable text cannot and must " +
              "not contain linebreaks.");
        }
      }
    }

    final long wordMinWidth = spacerMin + realCharTotal;
    final long wordPrefWidth = spacerOpt + realCharTotal;
    final long wordMaxWidth = spacerMax + realCharTotal;

    minimumChunkWidth = Math.max(minimumChunkWidth, wordMinChunkWidth);
    minimumWidth = wordMinWidth;
    preferredWidth = wordPrefWidth;

    setMaximumBoxWidth(wordMaxWidth);
    setMinimumChunkWidth(minimumChunkWidth);
  }

  public int getNodeType()
  {
    return LayoutNodeTypes.TYPE_NODE_TEXT;
  }

  public boolean isNormalTextSpacing()
  {
    return normalTextSpacing;
  }

  public boolean isForceLinebreak()
  {
    return forceLinebreak;
  }

  public GlyphList getGlyphs()
  {
    return glyphs;
  }

  public int getOffset()
  {
    return offset;
  }

  public int getLength()
  {
    return length;
  }

  public String getRawText()
  {
    final GlyphList gs = getGlyphs();
    return gs.getText(offset, length, new CodePointBuffer(length));
  }

  public boolean isEmpty()
  {
    return length == 0 && forceLinebreak == false;
  }

  public boolean isDiscardable()
  {
    if (forceLinebreak)
    {
      return false;
    }

    return glyphs.getSize() == 0;
  }

  /**
   * Returns the baseline info for the given node. This can be null, if the node does not have any baseline info.
   *
   * @return
   */
  public ExtendedBaselineInfo getBaselineInfo()
  {
    return baselineInfo;
  }

  public int getScript()
  {
    return script;
  }

  public long getMinimumWidth()
  {
    return minimumWidth;
  }

  public long getPreferredWidth()
  {
    return preferredWidth;
  }

  public String toString()
  {
    return "RenderableText={glyphs=" + glyphs + "'}";
  }

  public static long convert (final long fontMetricsValue)
  {
    return fontMetricsValue * conversionFactor;
  }

  public int computeMaximumTextSize(final long contentX2)
  {
    final int length = getLength();
    final long x = getX();
    if (contentX2 >= (x + getWidth()))
    {
      return length;
    }

    final GlyphList gs = getGlyphs();
    long runningPos = x;
    final int offset = getOffset();
    final int maxPos = offset + length;

    for (int i = offset; i < maxPos; i++)
    {
      final Glyph g = gs.getGlyph(i);
      runningPos += RenderableText.convert(g.getWidth());
      if (i != offset)
      {
        runningPos += g.getSpacing().getMinimum();
      }
      if (runningPos > contentX2)
      {
        return Math.max(0, i - offset);
      }
    }
    return length;
  }
}
TOP

Related Classes of org.pentaho.reporting.engine.classic.core.layout.model.RenderableText

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.