/* * 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.process.linebreak; import org.pentaho.reporting.engine.classic.core.layout.model.InlineRenderBox; import org.pentaho.reporting.engine.classic.core.layout.model.LayoutNodeTypes; 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.RenderNode; import org.pentaho.reporting.libraries.base.util.FastStack; /** * Creation-Date: 25.04.2007, 13:44:48 * * @author Thomas Morgner */ public final class FullLinebreaker implements ParagraphLinebreaker { private RenderBox insertationPoint; private ParagraphRenderBox paragraphRenderBox; private Object suspendItem; private boolean breakRequested; public FullLinebreaker( final ParagraphRenderBox paragraphRenderBox ) { this.paragraphRenderBox = paragraphRenderBox; final RenderBox pool = (RenderBox) paragraphRenderBox.getPool().deriveFrozen( false ); final RenderBox lineboxContainer = this.paragraphRenderBox.createLineboxContainer(); lineboxContainer.clear(); lineboxContainer.addGeneratedChild( pool ); this.paragraphRenderBox.setLineBoxAge( 0 ); this.insertationPoint = pool; } public boolean isWritable() { return true; } public void startBlockBox( final RenderBox child ) { final RenderBox derived = (RenderBox) child.deriveFrozen( false ); insertationPoint.addGeneratedChild( derived ); insertationPoint = derived; if ( suspendItem != null ) { suspendItem = derived.getInstanceId(); } } public void finishBlockBox( final RenderBox box ) { insertationPoint = insertationPoint.getParent(); if ( suspendItem == box.getInstanceId() ) { suspendItem = null; } } public ParagraphLinebreaker startParagraphBox( final ParagraphRenderBox box ) { startBlockBox( box ); return new FullLinebreaker( (ParagraphRenderBox) insertationPoint ); } public void finishParagraphBox( final ParagraphRenderBox box ) { finishBlockBox( box ); } public boolean isSuspended() { return suspendItem != null; } public FullLinebreaker startComplexLayout() { return this; } public void finish() { paragraphRenderBox.setLineBoxAge( paragraphRenderBox.getPool().getChangeTracker() ); } public void startInlineBox( final InlineRenderBox box ) { final RenderBox child = (RenderBox) box.deriveFrozen( false ); insertationPoint.addGeneratedChild( child ); insertationPoint = child; } public void finishInlineBox( final InlineRenderBox box ) { insertationPoint = insertationPoint.getParent(); } public void addNode( final RenderNode node ) { insertationPoint.addGeneratedChild( node.deriveFrozen( true ) ); } public void performBreak() { // If we come that far, it means, we have a forced linebreak and we // are a node in the middle of the tree .. final FastStack<RenderBox> contexts = new FastStack<RenderBox>(); // perform a simple split // as long as the splitted element is at the end of it's box, it is not // needed to split the box at all. Just let it end naturally is enough for // them to look good. // As the real context (from the break-State) is currently being built, // we have to use the original pool to query the 'is-end-of-line' flag. RenderBox context = insertationPoint; final RenderBox lines = paragraphRenderBox.getLineboxContainer(); while ( context != lines ) { // save the context .. if ( ( context.getLayoutNodeType() & LayoutNodeTypes.MASK_BOX_INLINE ) != LayoutNodeTypes.MASK_BOX_INLINE ) { throw new IllegalStateException( "Confused: I expect InlineBoxes .." ); } final InlineRenderBox inline = (InlineRenderBox) context; contexts.push( inline.split( RenderNode.HORIZONTAL_AXIS ) ); context = context.getParent(); } // reset to a known state and add all saved contexts .. insertationPoint = lines; while ( contexts.isEmpty() == false ) { final RenderBox box = contexts.pop(); insertationPoint.addGeneratedChild( box ); insertationPoint = box; } breakRequested = false; } public boolean isBreakRequested() { return breakRequested; } public void setBreakRequested( final boolean breakRequested ) { this.breakRequested = breakRequested; } }