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

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

/*
* 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.process;

import org.pentaho.reporting.engine.classic.core.layout.model.Border;
import org.pentaho.reporting.engine.classic.core.layout.model.LayoutNodeTypes;
import org.pentaho.reporting.engine.classic.core.layout.model.LogicalPageBox;
import org.pentaho.reporting.engine.classic.core.layout.model.ParagraphRenderBox;
import org.pentaho.reporting.engine.classic.core.layout.model.RenderBox;
import org.pentaho.reporting.engine.classic.core.layout.model.RenderLength;
import org.pentaho.reporting.engine.classic.core.layout.model.RenderNode;
import org.pentaho.reporting.engine.classic.core.layout.model.context.BoxDefinition;
import org.pentaho.reporting.engine.classic.core.layout.model.context.StaticBoxLayoutProperties;
import org.pentaho.reporting.engine.classic.core.layout.output.OutputProcessorFeature;
import org.pentaho.reporting.engine.classic.core.layout.output.OutputProcessorMetaData;
import org.pentaho.reporting.engine.classic.core.layout.text.ExtendedBaselineInfo;
import org.pentaho.reporting.engine.classic.core.style.BandStyleKeys;
import org.pentaho.reporting.engine.classic.core.style.ElementStyleKeys;
import org.pentaho.reporting.engine.classic.core.style.StyleSheet;
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.geom.StrictGeomUtility;

/**
* Computes the width for all elements. This uses the CSS alogorithm, percentages are resolved against the parent's
* already known width.
*
* @author Thomas Morgner
*/
public final class ComputeStaticPropertiesProcessStep extends IterateVisualProcessStep
{
  // Definitions:
  //
  // BCW: Block context width = the size against which percentages are resolved
  // CW: Computed Width = the computed size of the box. This is a rough estaminate of how the box will be sized later.
  //
  //Canvas in Block :  cw  = bcw of parent
  //                   bcw = cw - insets
  //Inline in Block :  cw  = bcw of parent
  //                   bcw = 0
  //Row in Block :     cw  = bcw of parent
  //                   bcw = cw - insets
  //Block in Block  :  cw  = bcw of parent
  //                   bcw = cw - insets
  //---------------------------------------------
  //Canvas in Inline : cw  = specified width resolved against bcw
  //                   bcw = 0
  //Inline in Inline : cw  = specified width resolved against bcw
  //                   bcw = 0
  //Row in Inline   :  cw  = specified width resolved against bcw
  //                   bcw = 0
  //Block in Inline :  cw  = specified width resolved against bcw
  //                   bcw = 0
  //---------------------------------------------
  //Canvas in Canvas : cw  = specified width resolved against bcw
  //                   bcw = cw - insets
  //Inline in Canvas : cw  = specified width resolved against bcw
  //                   bcw = 0
  //Row in Canvas    : cw  = specified width resolved against bcw
  //                   bcw = cw - insets
  //Block in Canvas  : cw  = specified width resolved against bcw
  //                   bcw = cw - insets
  //----------------------------------------------
  //Canvas in row    : cw  = specified width resolved against bcw
  //                   bcw = cw - insets
  //Inline in row    : cw  = specified width resolved against bcw
  //                   bcw = 0
  //Row in row       : cw  = specified width resolved against bcw
  //                   bcw = cw - insets
  //Block in row     : cw  = specified width resolved against bcw
  //                   bcw = cw - insets
  //


  // Set the maximum height to an incredibly high value. This is now 2^43 micropoints or more than
  // 3000 kilometers. Please call me directly at any time if you need more space for printing.
  public static final long MAX_AUTO = StrictGeomUtility.toInternalValue(0x80000000000L);

  private OutputProcessorMetaData metaData;
  private boolean overflowXSupported;
  private boolean overflowYSupported;

  public ComputeStaticPropertiesProcessStep(final OutputProcessorMetaData metaData)
  {
    this.metaData = metaData;
    overflowXSupported = metaData.isFeatureSupported(OutputProcessorFeature.ASSUME_OVERFLOW_X);
    overflowYSupported = metaData.isFeatureSupported(OutputProcessorFeature.ASSUME_OVERFLOW_Y);
  }

  public void compute(final LogicalPageBox root)
  {
    startProcessing(root);
  }

  protected void processParagraphChilds(final ParagraphRenderBox box)
  {
    final ExtendedBaselineInfo extendedBaselineInfo = box.getStaticBoxLayoutProperties().getNominalBaselineInfo();
    if (extendedBaselineInfo == null)
    {
      throw new IllegalStateException("Baseline info must not be null at this point");
    }
    final StyleSheet styleSheet = box.getNodeLayoutProperties().getStyleSheet();
    final double value = styleSheet.getDoubleStyleProperty(TextStyleKeys.LINEHEIGHT, 0);
    final long afterEdge = extendedBaselineInfo.getBaseline(ExtendedBaselineInfo.AFTER_EDGE);
    if (value <= 0)
    {
      box.getPool().setLineHeight(afterEdge);
    }
    else
    {
      box.getPool().setLineHeight(RenderLength.resolveLength(afterEdge, value));
    }

    startProcessing(box.getEffectiveLineboxContainer());
  }


  private void computeBreakIndicator(final RenderBox box)
  {

    final StyleSheet styleSheet = box.getStyleSheet();
    final RenderBox parent = box.getParent();
    if (parent != null)
    {
      final boolean breakBefore = styleSheet.getBooleanStyleProperty(BandStyleKeys.PAGEBREAK_BEFORE);
      final boolean breakAfter = box.isBreakAfter();
      if ((breakBefore) && (parent.getNodeType() != LayoutNodeTypes.TYPE_BOX_PARAGRAPH))
      {
        box.setManualBreakIndicator(RenderBox.DIRECT_MANUAL_BREAK);
        applyIndirectManualBreakIndicator(parent);
        return;
      }
      if (breakAfter && (parent.getNodeType() != LayoutNodeTypes.TYPE_BOX_PARAGRAPH))
      {
        applyIndirectManualBreakIndicator(parent);
      }
    }

    final boolean fixedPosition = RenderLength.AUTO.equals
        (styleSheet.getStyleProperty(BandStyleKeys.FIXED_POSITION, RenderLength.AUTO)) == false;
    if (fixedPosition)
    {
      applyIndirectManualBreakIndicator(box);
    }
    else
    {
      box.setManualBreakIndicator(RenderBox.NO_MANUAL_BREAK);
    }
  }

  private void applyIndirectManualBreakIndicator(RenderBox node)
  {
    while (node != null)
    {
      if (node.getManualBreakIndicator() != RenderBox.NO_MANUAL_BREAK)
      {
        return;
      }
      node.setManualBreakIndicator(RenderBox.INDIRECT_MANUAL_BREAK);
      node = node.getParent();
    }
  }

  /**
   * Collects and possibly computes the static properties according to the CSS layouting model. The classic JFreeReport
   * layout model does not know anything about margins or borders, so in that case resolving against the CSS model is
   * ok.
   *
   * @param box the box that should be processed.
   * @return true if the box is new, false otherwise
   */
  private boolean updateStaticProperties(final RenderBox box)
  {
    final BoxDefinition boxDefinition = box.getBoxDefinition();
    final StaticBoxLayoutProperties sblp = box.getStaticBoxLayoutProperties();
    if (sblp.getNominalBaselineInfo() != null)
    {
      // mark box as seen ..
      box.setStaticBoxPropertiesAge(box.getChangeTracker());
      return false;
    }

    final long parentWidth = ProcessUtility.computeBlockContextWidth(box);
    sblp.setMarginTop(boxDefinition.getMarginTop().resolve(parentWidth));
    sblp.setMarginLeft(boxDefinition.getMarginLeft().resolve(parentWidth));
    sblp.setMarginBottom(boxDefinition.getMarginBottom().resolve(parentWidth));
    sblp.setMarginRight(boxDefinition.getMarginRight().resolve(parentWidth));

    final Border border = boxDefinition.getBorder();
    sblp.setBorderTop(border.getTop().getWidth());
    sblp.setBorderLeft(border.getLeft().getWidth());
    sblp.setBorderBottom(border.getBottom().getWidth());
    sblp.setBorderRight(border.getRight().getWidth());

    final StyleSheet style = box.getStyleSheet();
    if (box.getNodeType() == LayoutNodeTypes.TYPE_BOX_LINEBOX)
    {
      sblp.setAvoidPagebreakInside(true);
    }
    else
    {
      sblp.setAvoidPagebreakInside(style.getBooleanStyleProperty(ElementStyleKeys.AVOID_PAGEBREAK_INSIDE, false));
    }

    sblp.setDominantBaseline(-1);
    sblp.setOrphans(style.getIntStyleProperty(ElementStyleKeys.ORPHANS, 0));
    sblp.setWidows(style.getIntStyleProperty(ElementStyleKeys.WIDOWS, 0));

    final ExtendedBaselineInfo baselineInfo = metaData.getBaselineInfo('x', style);
    if (baselineInfo == null)
    {
      throw new IllegalStateException();
    }
    sblp.setNominalBaselineInfo(baselineInfo);
    sblp.setFontFamily(metaData.getNormalizedFontFamilyName((String) style.getStyleProperty(TextStyleKeys.FONT)));

    final Object collapse = style.getStyleProperty(TextStyleKeys.WHITE_SPACE_COLLAPSE);
    sblp.setPreserveSpace(WhitespaceCollapse.PRESERVE.equals(collapse));
    sblp.setOverflowX(style.getBooleanStyleProperty(ElementStyleKeys.OVERFLOW_X, overflowXSupported));
    sblp.setOverflowY(style.getBooleanStyleProperty(ElementStyleKeys.OVERFLOW_Y, overflowYSupported));
    sblp.setInvisibleConsumesSpace(style.getBooleanStyleProperty
        (ElementStyleKeys.INVISIBLE_CONSUMES_SPACE, box.getNodeType() == LayoutNodeTypes.TYPE_BOX_ROWBOX));
    sblp.setVisible(style.getBooleanStyleProperty(ElementStyleKeys.VISIBLE));
    box.setStaticBoxPropertiesAge(box.getChangeTracker());
    computeBreakIndicator(box);
    return true;
  }

  protected boolean startBlockLevelBox(final RenderBox box)
  {
    final long changeTracker = box.getChangeTracker();
    final long age = box.getStaticBoxPropertiesAge();
    if (changeTracker == age)
    {
      return false;
    }

    if (updateStaticProperties(box))
    {
      final long bcw = ProcessUtility.computeBlockContextWidth(box);
      final long computedWidth = resolveComputedWidth(box);
      final long insets = box.getInsets();
      box.setComputedWidth(Math.max(computedWidth, bcw));

      if ((box.getNodeType() & LayoutNodeTypes.MASK_BOX_INLINE) == LayoutNodeTypes.MASK_BOX_INLINE)
      {
        box.getStaticBoxLayoutProperties().setBlockContextWidth(0);
      }
      else
      {
        final long newBcw = Math.max(bcw - insets, computedWidth - insets);
        box.getStaticBoxLayoutProperties().setBlockContextWidth(Math.max(0, newBcw));
      }
    }
    return true;
  }

  protected boolean startInlineLevelBox(final RenderBox box)
  {
    final long changeTracker = box.getChangeTracker();
    final long age = box.getStaticBoxPropertiesAge();
    if (changeTracker == age)
    {
      return false;
    }

    if (updateStaticProperties(box))
    {
      box.setComputedWidth(box.getInsets());
      box.getStaticBoxLayoutProperties().setBlockContextWidth(0);
    }
    return true;
  }

  private long resolveComputedWidth(final RenderBox box)
  {
    final long bcw = ProcessUtility.computeBlockContextWidth(box);
    final BoxDefinition boxDef = box.getBoxDefinition();
    final RenderLength minLength = boxDef.getMinimumWidth();
    final RenderLength prefLength = boxDef.getPreferredWidth();
    final RenderLength maxLength = boxDef.getMaximumWidth();

    final long min = minLength.resolve(bcw, 0);
    final long pref = prefLength.resolve(bcw, 0);
    final long max = maxLength.resolve(bcw, ComputeStaticPropertiesProcessStep.MAX_AUTO);
    return ProcessUtility.computeLength(min, max, pref);
  }


  protected boolean startCanvasLevelBox(final RenderBox box)
  {
    final long changeTracker = box.getChangeTracker();
    final long age = box.getStaticBoxPropertiesAge();
    if (changeTracker == age)
    {
      return false;
    }

    if (updateStaticProperties(box))
    {
      final long computedWidth = resolveComputedWidth(box);
      box.setComputedWidth(computedWidth);

      if ((box.getNodeType() & LayoutNodeTypes.MASK_BOX_INLINE) == LayoutNodeTypes.MASK_BOX_INLINE)
      {
        box.getStaticBoxLayoutProperties().setBlockContextWidth(0);
      }
      else
      {
        box.getStaticBoxLayoutProperties().setBlockContextWidth(Math.max(0, computedWidth - box.getInsets()));
      }
    }

    return true;
  }

  protected boolean startRowLevelBox(final RenderBox box)
  {
    final long changeTracker = box.getChangeTracker();
    final long age = box.getStaticBoxPropertiesAge();
    if (changeTracker == age)
    {
      return false;
    }

    if (updateStaticProperties(box))
    {
      final long computedWidth = resolveComputedWidth(box);
      box.setComputedWidth(computedWidth);

      if ((box.getNodeType() & LayoutNodeTypes.MASK_BOX_INLINE) == LayoutNodeTypes.MASK_BOX_INLINE)
      {
        box.getStaticBoxLayoutProperties().setBlockContextWidth(0);
      }
      else
      {
        final BoxDefinition boxDefinition = box.getBoxDefinition();
        final StaticBoxLayoutProperties sblp = box.getStaticBoxLayoutProperties();
        final long insets = sblp.getBorderLeft() + sblp.getBorderRight() +
            boxDefinition.getPaddingLeft() + boxDefinition.getPaddingRight();
        box.getStaticBoxLayoutProperties().setBlockContextWidth(Math.max(0, computedWidth - insets));
      }
    }

    return true;
  }

  protected void finishInlineLevelBox(final RenderBox box)
  {
    updateMinimumChunkWidth(box);
  }

  protected void finishCanvasLevelBox(final RenderBox box)
  {
    updateMinimumChunkWidth(box);
  }

  protected void finishBlockLevelBox(final RenderBox box)
  {
    updateMinimumChunkWidth(box);
  }

  protected void finishRowLevelBox(final RenderBox box)
  {
    updateMinimumChunkWidth(box);
  }

  protected void updateMinimumChunkWidth(final RenderBox box)
  {
    if ((box.getNodeType() & LayoutNodeTypes.TYPE_BOX_PARAGRAPH) == LayoutNodeTypes.TYPE_BOX_PARAGRAPH)
    {
      updateParagraphChunkWidth(box);
      return;
    }

    long chunkWidth = 0;
    RenderNode node = box.getFirstChild();
    while (node != null)
    {
      final long minimumChunkWidth = node.getMinimumChunkWidth();
      if (chunkWidth < minimumChunkWidth)
      {
        chunkWidth = minimumChunkWidth;
      }
      node = node.getNext();
    }

    if ((box.getNodeType() & LayoutNodeTypes.MASK_BOX_INLINE) == LayoutNodeTypes.MASK_BOX_INLINE)
    {
      box.setMinimumChunkWidth(chunkWidth);
    }
    else
    {
      box.setMinimumChunkWidth(Math.max(chunkWidth, box.getComputedWidth()));
    }
  }

  protected void updateParagraphChunkWidth(final RenderBox box)
  {
    final ParagraphRenderBox paragraphRenderBox = (ParagraphRenderBox) box;
    final RenderBox chunkBox;
    final RenderBox lineboxContainer = paragraphRenderBox.getLineboxContainer();
    if (lineboxContainer == null)
    {
      // use pool ..
      chunkBox = paragraphRenderBox.getPool();
    }
    else
    {
      chunkBox = lineboxContainer;
    }

    long chunkWidth = 0;
    RenderNode node = chunkBox.getFirstChild();
    while (node != null)
    {
      final long minimumChunkWidth = node.getMinimumChunkWidth();
      if (chunkWidth < minimumChunkWidth)
      {
        chunkWidth = minimumChunkWidth;
      }
      node = node.getNext();
    }
    box.setMinimumChunkWidth(Math.max(chunkWidth, box.getComputedWidth()));
    if (box.getStyleSheet().getBooleanStyleProperty(ElementStyleKeys.USE_MIN_CHUNKWIDTH))
    {
      box.setComputedWidth(Math.max(box.getComputedWidth(), chunkWidth + box.getInsets()));
    }
  }


}
TOP

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

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.