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

Source Code of org.pentaho.reporting.engine.classic.core.layout.process.text.RichTextSpecProducer

/*
*
*  * 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) 2006 - 2009 Pentaho Corporation..  All rights reserved.
*
*/

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

import java.awt.Image;
import java.awt.font.GraphicAttribute;
import java.awt.font.ImageGraphicAttribute;
import java.awt.font.TextAttribute;
import java.text.AttributedCharacterIterator.Attribute;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.pentaho.reporting.engine.classic.core.ReportAttributeMap;
import org.pentaho.reporting.engine.classic.core.layout.model.LayoutNodeTypes;
import org.pentaho.reporting.engine.classic.core.layout.model.RenderBox;
import org.pentaho.reporting.engine.classic.core.layout.model.RenderNode;
import org.pentaho.reporting.engine.classic.core.layout.model.RenderableComplexText;
import org.pentaho.reporting.engine.classic.core.layout.model.RenderableReplacedContentBox;
import org.pentaho.reporting.engine.classic.core.layout.output.OutputProcessorMetaData;
import org.pentaho.reporting.engine.classic.core.layout.process.util.ReplacedContentUtil;
import org.pentaho.reporting.engine.classic.core.style.StyleSheet;
import org.pentaho.reporting.engine.classic.core.style.TextDirection;
import org.pentaho.reporting.engine.classic.core.style.TextStyleKeys;
import org.pentaho.reporting.engine.classic.core.style.WhitespaceCollapse;
import org.pentaho.reporting.engine.classic.core.util.InstanceID;
import org.pentaho.reporting.libraries.base.util.ArgumentNullException;
import org.pentaho.reporting.libraries.resourceloader.ResourceManager;

public class RichTextSpecProducer
{
  private static class AttributedStringChunk
  {
    private String text;
    private Map<Attribute, Object> attributes;
    private ReportAttributeMap<Object> originalAttributes;
    private StyleSheet styleSheet;
    private InstanceID instanceID;
    private RenderNode node;

    private AttributedStringChunk(final String text,
                                  final Map<Attribute, Object> attributes,
                                  final ReportAttributeMap<Object> originalAttributes,
                                  final StyleSheet styleSheet, final InstanceID instanceID,
                                  final RenderNode node)
    {
      ArgumentNullException.validate("text", text);
      ArgumentNullException.validate("attributes", attributes);
      ArgumentNullException.validate("node", node);
      ArgumentNullException.validate("originalAttributes", originalAttributes);
      ArgumentNullException.validate("styleSheet", styleSheet);
      ArgumentNullException.validate("instanceID", instanceID);

      if (text.length() == 0)
      {
        this.text = "\u0200";
      }
      else
      {
        this.text = text;
      }
      this.instanceID = instanceID;
      this.node = node;
      this.attributes = attributes;
      this.originalAttributes = originalAttributes;
      this.styleSheet = styleSheet;
    }

    public String getText()
    {
      return text;
    }

    public Map<Attribute, Object> getAttributes()
    {
      return attributes;
    }

    public ReportAttributeMap<Object> getOriginalAttributes()
    {
      return originalAttributes;
    }

    public StyleSheet getStyleSheet()
    {
      return styleSheet;
    }

    public InstanceID getInstanceID()
    {
      return instanceID;
    }

    public RenderNode getNode()
    {
      return node;
    }
  }

  public static RichTextSpec compute(final RenderBox lineBoxContainer,
                                     final OutputProcessorMetaData metaData,
                                     final ResourceManager resourceManager)
  {
    return new RichTextSpecProducer(metaData, resourceManager).computeText(lineBoxContainer);
  }

  private RichTextImageProducer imageProducer;
  private OutputProcessorMetaData metaData;

  public RichTextSpecProducer(final OutputProcessorMetaData metaData,
                              final ResourceManager resourceManager)
  {
    ArgumentNullException.validate("metaData", metaData);
    ArgumentNullException.validate("resourceManager", resourceManager);

    this.metaData = metaData;
    imageProducer = new RichTextImageProducer(metaData, resourceManager);
  }

  private RichTextSpec computeText(final RenderBox lineBoxContainer)
  {
    List<AttributedStringChunk> attr = new ArrayList<AttributedStringChunk>();
    computeText(lineBoxContainer, attr);
    if (attr.isEmpty())
    {
      attr.add(new AttributedStringChunk("", computeStyle(lineBoxContainer.getStyleSheet()),
          lineBoxContainer.getAttributes(), lineBoxContainer.getStyleSheet(), new InstanceID(), lineBoxContainer));
    }

    attr = processWhitespaceRules(lineBoxContainer, attr);

    StringBuilder text = new StringBuilder();
    for (final AttributedStringChunk chunk : attr)
    {
      text.append(chunk.getText());
    }

    TextDirection direction = (TextDirection)
        lineBoxContainer.getStyleSheet().getStyleProperty(TextStyleKeys.DIRECTION, TextDirection.LTR);
    return new RichTextSpec(text.toString(), direction, convertNodes(attr));
  }

  public RichTextSpec computeText(final RenderableComplexText textNode,
                                  final String textChunk)
  {
    List<AttributedStringChunk> attr = new ArrayList<AttributedStringChunk>();
    attr.add(new AttributedStringChunk(textChunk,
        computeStyle(textNode.getStyleSheet()), textNode.getAttributes(),
        textNode.getStyleSheet(), textNode.getInstanceId(), textNode));

    StringBuilder text = new StringBuilder();
    for (final AttributedStringChunk chunk : attr)
    {
      text.append(chunk.getText());
    }

    TextDirection direction = (TextDirection)
        textNode.getStyleSheet().getStyleProperty(TextStyleKeys.DIRECTION, TextDirection.LTR);
    return new RichTextSpec(text.toString(), direction, convertNodes(attr));
  }

  private List<RichTextSpec.StyledChunk> convertNodes(final List<AttributedStringChunk> chunks)
  {
    ArrayList<RichTextSpec.StyledChunk> result = new ArrayList<RichTextSpec.StyledChunk>(chunks.size());
    int startPosition = 0;
    for (final AttributedStringChunk chunk : chunks)
    {
      int length = chunk.getText().length();
      int endIndex = startPosition + length;
      result.add(new RichTextSpec.StyledChunk(startPosition, endIndex, chunk.getNode(), chunk.getAttributes(),
          chunk.getOriginalAttributes(), chunk.getStyleSheet(), chunk.getInstanceID(), chunk.getText()));
      startPosition = endIndex;
    }
    return result;
  }

  private List<AttributedStringChunk> processWhitespaceRules(final RenderBox lineBoxContainer,
                                                             final List<AttributedStringChunk> attrs)
  {
    // todo
    Object ws = lineBoxContainer.getStyleSheet().getStyleProperty(TextStyleKeys.WHITE_SPACE_COLLAPSE);
    if (WhitespaceCollapse.PRESERVE_BREAKS.equals(ws))
    {
      // linebreaks disabled

    }
    else if (WhitespaceCollapse.COLLAPSE.equals(ws))
    {
      // normal linebreaks, but duplicate spaces removed
    }
    else if (WhitespaceCollapse.DISCARD.equals(ws))
    {
      // all whitespaces removed
    }
    return attrs;
  }

  private void computeText(final RenderBox box, final List<AttributedStringChunk> chunks)
  {
    RenderNode node = box.getFirstChild();
    while (node != null)
    {
      if (node.getNodeType() == LayoutNodeTypes.TYPE_NODE_COMPLEX_TEXT)
      {
        final RenderableComplexText complexNode = (RenderableComplexText) node;
        chunks.add(new AttributedStringChunk(complexNode.getRawText(), computeStyle(node.getStyleSheet()),
            node.getAttributes(), node.getStyleSheet(), node.getInstanceId(), node));
      }
      else if (node.getNodeType() == LayoutNodeTypes.TYPE_BOX_CONTENT)
      {
        final RenderableReplacedContentBox contentBox = (RenderableReplacedContentBox) node;
        final long width = ReplacedContentUtil.computeWidth(contentBox);
        final long height = ReplacedContentUtil.computeHeight(contentBox, 0, width);
        contentBox.setCachedWidth(width);
        contentBox.setCachedHeight(height);
        contentBox.setWidth(width);
        contentBox.setHeight(height);

        chunks.add(new AttributedStringChunk("@", computeImageStyle(node.getStyleSheet(), contentBox),
            node.getAttributes(), node.getStyleSheet(), node.getInstanceId(), node));
      }
      else if (node instanceof RenderBox)
      {
        computeText((RenderBox) node, chunks);
      }
      node = node.getNext();
    }
  }

  private Map<Attribute, Object> computeImageStyle(final StyleSheet layoutContext,
                                                   final RenderableReplacedContentBox content)
  {
    final Image image = imageProducer.createImagePlaceholder(content);
    ImageGraphicAttribute iga =
        new ImageGraphicAttribute(image, GraphicAttribute.BOTTOM_ALIGNMENT);

    Map<Attribute, Object> attrs = computeStyle(layoutContext);
    attrs.put(TextAttribute.CHAR_REPLACEMENT, iga);
    return attrs;
  }

  private Map<Attribute, Object> computeStyle(final StyleSheet layoutContext)
  {
    Map<Attribute, Object> result = new HashMap<Attribute, Object>();
    // Determine font style
    if (layoutContext.getBooleanStyleProperty(TextStyleKeys.ITALIC))
    {
      result.put(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE);
    }
    else
    {
      result.put(TextAttribute.POSTURE, TextAttribute.POSTURE_REGULAR);
    }
    if (layoutContext.getBooleanStyleProperty(TextStyleKeys.BOLD))
    {
      result.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD);
    }
    else
    {
      result.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_REGULAR);
    }

    final String fontNameRaw = (String) layoutContext.getStyleProperty(TextStyleKeys.FONT);
    final String fontName = metaData.getNormalizedFontFamilyName(fontNameRaw);
    result.put(TextAttribute.FAMILY, fontName);
    result.put(TextAttribute.SIZE, layoutContext.getIntStyleProperty(TextStyleKeys.FONTSIZE, 12));
    if (layoutContext.getBooleanStyleProperty(TextStyleKeys.UNDERLINED))
    {
      result.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON);
    }
    if (layoutContext.getBooleanStyleProperty(TextStyleKeys.STRIKETHROUGH))
    {
      result.put(TextAttribute.STRIKETHROUGH, TextAttribute.STRIKETHROUGH_ON);
    }

    // character spacing
    result.put(TextAttribute.TRACKING, layoutContext.getDoubleStyleProperty(TextStyleKeys.X_MIN_LETTER_SPACING, 0) / 10);

    return result;
  }
}
TOP

Related Classes of org.pentaho.reporting.engine.classic.core.layout.process.text.RichTextSpecProducer

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.