/* * 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.bugs; import com.lowagie.text.Document; import com.lowagie.text.DocumentException; import com.lowagie.text.Image; import com.lowagie.text.pdf.PdfWriter; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.pentaho.reporting.engine.classic.core.AttributeNames; import org.pentaho.reporting.engine.classic.core.ClassicEngineBoot; import org.pentaho.reporting.engine.classic.core.ClassicEngineCoreModule; import org.pentaho.reporting.engine.classic.core.Element; import org.pentaho.reporting.engine.classic.core.MasterReport; import org.pentaho.reporting.engine.classic.core.filter.types.LabelType; import org.pentaho.reporting.engine.classic.core.layout.ModelPrinter; 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.RenderNode; import org.pentaho.reporting.engine.classic.core.layout.model.RenderableComplexText; import org.pentaho.reporting.engine.classic.core.layout.model.RenderableText; import org.pentaho.reporting.engine.classic.core.modules.output.pageable.pdf.internal.PdfGraphics2D; import org.pentaho.reporting.engine.classic.core.modules.output.pageable.pdf.internal.PdfLogicalPageDrawable; import org.pentaho.reporting.engine.classic.core.modules.output.pageable.pdf.internal.PdfOutputProcessorMetaData; import org.pentaho.reporting.engine.classic.core.modules.output.support.itext.BaseFontModule; import org.pentaho.reporting.engine.classic.core.style.ElementStyleKeys; import org.pentaho.reporting.engine.classic.core.style.TextStyleKeys; import org.pentaho.reporting.engine.classic.core.testsupport.DebugReportRunner; import org.pentaho.reporting.engine.classic.core.testsupport.selector.MatchFactory; import org.pentaho.reporting.engine.classic.core.util.geom.StrictGeomUtility; import org.pentaho.reporting.libraries.base.util.LFUMap; import org.pentaho.reporting.libraries.base.util.NullOutputStream; import org.pentaho.reporting.libraries.fonts.itext.ITextFontStorage; import org.pentaho.reporting.libraries.resourceloader.ResourceKey; import org.pentaho.reporting.libraries.resourceloader.ResourceManager; import java.awt.Graphics2D; import java.awt.geom.Rectangle2D; import java.net.URL; public class Prd5321IT { private static class TestPdfLogicalPageDrawable extends PdfLogicalPageDrawable { private final Graphics2D g; private int textRendering; private TestPdfLogicalPageDrawable( final PdfWriter writer, final LFUMap<ResourceKey, Image> imageCache, final char version, final Graphics2D g ) { super( writer, imageCache, version ); this.g = g; } public int getTextRendering() { return textRendering; } public void draw() { draw( g, new Rectangle2D.Double( 0, 0, 700, 500 ) ); } protected void drawText( final RenderableText renderableText, final long contentX2 ) { textRendering += 1; super.drawText( renderableText, contentX2 ); } protected void drawComplexText( final RenderableComplexText node, final Graphics2D g2 ) { textRendering += 1; super.drawComplexText( node, g2 ); } } public Prd5321IT() { } @Before public void setUp() throws Exception { ClassicEngineBoot.getInstance().start(); } /** * In 5.0 and later, elements are dynamic by default - if they only define a minimum height, and no max-height then * that element can grow as if dynamic=true has been set. To limit the element growth, use the max-height property. * <p/> * This test validates that growth happens unless explicitly restricted, and if restricted, that the first line is * printed. * * @throws Exception */ @Test public void testTextLimitedInHeight() throws Exception { Element l = new Element(); l.setElementType( LabelType.INSTANCE ); l.getStyle().setStyleProperty( ElementStyleKeys.MIN_HEIGHT, 10f ); l.getStyle().setStyleProperty( ElementStyleKeys.MIN_WIDTH, 100f ); l.getStyle().setStyleProperty( TextStyleKeys.FONTSIZE, 50 ); l.setAttribute( AttributeNames.Core.NAMESPACE, AttributeNames.Core.VALUE, "Label" ); l.setName( "Label" ); Element l2 = new Element(); l2.setElementType( LabelType.INSTANCE ); l2.getStyle().setStyleProperty( ElementStyleKeys.POS_X, 100f ); l.getStyle().setStyleProperty( ElementStyleKeys.MIN_WIDTH, 100f ); l2.getStyle().setStyleProperty( ElementStyleKeys.MIN_HEIGHT, 10f ); l2.getStyle().setStyleProperty( ElementStyleKeys.MAX_HEIGHT, 10f ); l2.getStyle().setStyleProperty( TextStyleKeys.FONTSIZE, 50 ); l2.setAttribute( AttributeNames.Core.NAMESPACE, AttributeNames.Core.VALUE, "Label" ); l2.setName( "Label2" ); MasterReport r = new MasterReport(); r.getReportHeader().addElement( l ); r.getReportFooter().addElement( l2 ); LogicalPageBox logicalPageBox = DebugReportRunner.layoutPage( r, 0 ); ModelPrinter.INSTANCE.print( logicalPageBox ); RenderNode label = MatchFactory.findElementByName( logicalPageBox, "Label" ); // PRD-2736 note: the label is split into two parts now, since it does not fit the line width anymore: // Lab // el_ Assert.assertEquals( StrictGeomUtility.toInternalValue( 100 ), label.getCachedHeight() ); RenderNode label2 = MatchFactory.findElementByName( logicalPageBox, "Label2" ); Assert.assertEquals( StrictGeomUtility.toInternalValue( 10 ), label2.getCachedHeight() ); } /** * Tests the sample report in modern mode by setting the compatibility flag to "5.0". As none of the elements defines * a max-height, the elements will expect into multi-line elements. * * @throws Exception */ @Test public void testModernMode() throws Exception { URL resource = getClass().getResource( "Prd-5321-2.prpt" ); ResourceManager mgr = new ResourceManager(); MasterReport report = (MasterReport) mgr.createDirectly( resource, MasterReport.class ).getResource(); report.getReportConfiguration().setConfigProperty( ClassicEngineCoreModule.COMPLEX_TEXT_CONFIG_OVERRIDE_KEY, "false" ); report.setCompatibilityLevel( ClassicEngineBoot.computeVersionId( 5, 0, 0 ) ); LogicalPageBox logicalPageBox = DebugReportRunner.layoutPage( report, 0 ); ModelPrinter.INSTANCE.print( logicalPageBox ); RenderNode[] paragraphs = MatchFactory.findElementsByNodeType( logicalPageBox, LayoutNodeTypes.TYPE_BOX_PARAGRAPH ); Assert.assertEquals( 4, paragraphs.length ); for ( RenderNode paragraph : paragraphs ) { ParagraphRenderBox pb = (ParagraphRenderBox) paragraph; Assert.assertNotNull( pb.getFirstChild() ); } } /** * Tests the rendering of text in compatibility mode. In this mode elements that do not define an explicit height can * be limited in growth to their defined minimum height. This auto-limit only takes place outside of crosstabs (which * were not available in pre-5.0 releases) and if the element is contained in a parent band that uses an canvas-layout * for its child elements. * * @throws Exception */ @Test public void testCompatibilityMode() throws Exception { URL resource = getClass().getResource( "Prd-5321-2.prpt" ); ResourceManager mgr = new ResourceManager(); MasterReport report = (MasterReport) mgr.createDirectly( resource, MasterReport.class ).getResource(); report.getReportConfiguration().setConfigProperty( ClassicEngineCoreModule.COMPLEX_TEXT_CONFIG_OVERRIDE_KEY, "false" ); report.setCompatibilityLevel( ClassicEngineBoot.VERSION_3_8 ); LogicalPageBox logicalPageBox = DebugReportRunner.layoutPage( report, 0 ); RenderNode[] paragraphs = MatchFactory.findElementsByNodeType( logicalPageBox, LayoutNodeTypes.TYPE_BOX_PARAGRAPH ); Assert.assertEquals( 4, paragraphs.length ); for ( RenderNode paragraph : paragraphs ) { ParagraphRenderBox pb = (ParagraphRenderBox) paragraph; Assert.assertNotNull( pb.getFirstChild() ); Assert.assertSame( pb.getFirstChild(), pb.getLastChild() ); } } @Test public void testTextRendering() throws Exception { URL resource = getClass().getResource( "Prd-5321.prpt" ); ResourceManager mgr = new ResourceManager(); MasterReport report = (MasterReport) mgr.createDirectly( resource, MasterReport.class ).getResource(); report.getReportConfiguration().setConfigProperty( ClassicEngineCoreModule.COMPLEX_TEXT_CONFIG_OVERRIDE_KEY, "false" ); LogicalPageBox logicalPageBox = DebugReportRunner.layoutPage( report, 0 ); ModelPrinter.INSTANCE.print( logicalPageBox ); Assert.assertEquals( 6, MatchFactory.findElementsByNodeType( logicalPageBox, LayoutNodeTypes.TYPE_BOX_PARAGRAPH ).length ); Assert.assertEquals( 13, MatchFactory.findElementsByNodeType( logicalPageBox, LayoutNodeTypes.TYPE_NODE_TEXT ).length ); TestPdfLogicalPageDrawable pdf = createDrawableForTest( report, logicalPageBox ); pdf.draw(); Assert.assertEquals( 13, pdf.textRendering ); } @Test public void testTextRenderingComplex() throws Exception { if ( !DebugReportRunner.isSafeToTestComplexText() ) { return; } Assert.assertTrue( DebugReportRunner.isSafeToTestComplexText() ); URL resource = getClass().getResource( "Prd-5321.prpt" ); ResourceManager mgr = new ResourceManager(); MasterReport report = (MasterReport) mgr.createDirectly( resource, MasterReport.class ).getResource(); report.getReportConfiguration() .setConfigProperty( ClassicEngineCoreModule.COMPLEX_TEXT_CONFIG_OVERRIDE_KEY, "true" ); LogicalPageBox logicalPageBox = DebugReportRunner.layoutPage( report, 0 ); Assert.assertEquals( 6, MatchFactory.findElementsByNodeType( logicalPageBox, LayoutNodeTypes.TYPE_BOX_PARAGRAPH ).length ); Assert.assertEquals( 8, MatchFactory .findElementsByNodeType( logicalPageBox, LayoutNodeTypes.TYPE_NODE_COMPLEX_TEXT ).length ); TestPdfLogicalPageDrawable pdf = createDrawableForTest( report, logicalPageBox ); pdf.draw(); Assert.assertEquals( 8, pdf.textRendering ); } protected TestPdfLogicalPageDrawable createDrawableForTest( final MasterReport report, final LogicalPageBox logicalPageBox ) throws DocumentException { Document document = new Document(); PdfWriter writer = PdfWriter.getInstance( document, new NullOutputStream() ); writer.setLinearPageMode(); writer.open(); document.setPageSize( new com.lowagie.text.Rectangle( 700, 500 ) ); document.setMargins( 10, 10, 10, 10 ); document.open(); PdfOutputProcessorMetaData metaData = new PdfOutputProcessorMetaData( new ITextFontStorage( BaseFontModule.getFontRegistry() ) ); metaData.initialize( report.getConfiguration() ); final Graphics2D graphics = new PdfGraphics2D( writer.getDirectContent(), 700, 500, metaData ); TestPdfLogicalPageDrawable pdf = new TestPdfLogicalPageDrawable( writer, new LFUMap<ResourceKey, Image>( 10 ), '5', graphics ); pdf.init( logicalPageBox, metaData, report.getResourceManager(), logicalPageBox.getPageGrid().getPage( 0, 0 ) ); return pdf; } }