public void processContent( final ReportElement element, final Object computedValue, final Object rawValue) { if (computedValue == null) { final StyleSheet resolvedStyle = element.getComputedStyle(); final RenderBox parentRenderBox = this.context.getRenderBox(); if (parentRenderBox.isEmptyNodesHaveSignificance() || metaData.isExtraContentElement(resolvedStyle, element.getAttributes())) { ensureEmptyChildIsAdded(parentRenderBox, element); this.context.setEmpty(false); } return; } if (String.class.equals(computedValue.getClass())) { processText(element, (String) computedValue, rawValue); } else if (computedValue instanceof Shape) { final StyleSheet resolvedStyle = element.getComputedStyle(); final Shape shape = (Shape) computedValue; final ReportDrawable reportDrawable = new ShapeDrawable( shape, resolvedStyle.getBooleanStyleProperty(ElementStyleKeys.KEEP_ASPECT_RATIO)); processReportDrawable(element, reportDrawable, rawValue); } else if (computedValue instanceof ReportDrawable) { processReportDrawable(element, (ReportDrawable) computedValue, rawValue); } else if (computedValue instanceof ImageContainer || computedValue instanceof DrawableWrapper) { processReplacedContent(element, computedValue, rawValue); } else if (DrawableWrapper.isDrawable(computedValue)) { processReplacedContent(element, new DrawableWrapper(computedValue), rawValue); } else { processText(element, String.valueOf(computedValue), rawValue); } }
public void initialize( final ProcessingContext processingContext, final RenderBox parentBox, final RenderNodeFactory renderNodeFactory) { if (parentBox == null) { throw new NullPointerException(); } if (processingContext == null) { throw new NullPointerException(); } if (this.processingContext != processingContext) { this.processingContext = processingContext; this.metaData = processingContext.getOutputProcessorMetaData(); this.strictLegacyMode = metaData.isFeatureSupported(OutputProcessorFeature.STRICT_COMPATIBILITY); this.designtime = metaData.isFeatureSupported(OutputProcessorFeature.DESIGNTIME); this.renderNodeFactory = renderNodeFactory; this.textProducer = createTextProducer(); } this.context = new DefaultLayoutModelBuilderContext(null, parentBox); }
public void startSection(final ReportElement element, final int sectionSize) { final StyleSheet resolverStyleSheet = element.getComputedStyle(); final String layoutMode; final boolean legacyMode = metaData.isFeatureSupported(OutputProcessorFeature.STRICT_COMPATIBILITY); if (legacyMode) { layoutMode = BandStyleKeys.LAYOUT_BLOCK; } else { String layout = (String) resolverStyleSheet.getStyleProperty(BandStyleKeys.LAYOUT, BandStyleKeys.LAYOUT_AUTO); if (BandStyleKeys.LAYOUT_INLINE.equals(layout) && !this.context.getRenderBox().isAcceptInlineBoxes()) { layoutMode = BandStyleKeys.LAYOUT_BLOCK; } else { layoutMode = layout; } } final GroupSection groupSection = new GroupSection( renderNodeFactory.produceRenderBox(element, resolverStyleSheet, layoutMode, null), renderNodeFactory.createAutoGeneratedSectionStyleSheet(resolverStyleSheet), sectionSize, legacyMode); this.context = new SectionLayoutModelBuilderContext(this.context, groupSection, legacyMode); this.context.setEmpty(true); if (element instanceof GroupBody || element instanceof Group) { // PRD-3154 - do we need to set placeholder to true? // todo: PRD-3154: This is black magic, placeholder box true is evil. // Need to evaluate side-effects of this beast. Is it safe for keep-together boxes? this.context .getRenderBox() .getStaticBoxLayoutProperties() .setPlaceholderBox(StaticBoxLayoutProperties.PlaceholderType.SECTION); } this.textProducer.startText(); }
public void startSection() { final String layoutMode; if (metaData.isFeatureSupported(OutputProcessorFeature.STRICT_COMPATIBILITY)) { layoutMode = BandStyleKeys.LAYOUT_BLOCK; } else { layoutMode = BandStyleKeys.LAYOUT_AUTO; } final RenderBox renderBox = renderNodeFactory.produceSectionBox(layoutMode, null); if (isAllowMergeSection()) { this.context = new BandSectionLayoutModelBuilderContext(this.metaData, this.context, renderBox); } else { this.context = new DefaultLayoutModelBuilderContext(this.context, renderBox); } this.context.setEmpty(true); if (legacySectionName != null) { this.context.getRenderBox().setName(legacySectionName); } this.textProducer.startText(); }
public void startSubFlow(final ReportElement element) { final StyleSheet resolverStyleSheet = element.getComputedStyle(); final RenderBox box; if (metaData.isFeatureSupported(OutputProcessorFeature.STRICT_COMPATIBILITY)) { final StyleSheet styleSheet = new SubReportStyleSheet( resolverStyleSheet.getBooleanStyleProperty(BandStyleKeys.PAGEBREAK_BEFORE), (resolverStyleSheet.getBooleanStyleProperty(BandStyleKeys.PAGEBREAK_AFTER))); final SimpleStyleSheet reportStyle = new SimpleStyleSheet(styleSheet); final BoxDefinition boxDefinition = renderNodeFactory.getBoxDefinition(reportStyle); box = new BlockRenderBox( reportStyle, element.getObjectID(), boxDefinition, SubReportType.INSTANCE, element.getAttributes(), null); } else { box = renderNodeFactory.produceRenderBox( element, resolverStyleSheet, BandStyleKeys.LAYOUT_BLOCK, stateKey); } box.getStaticBoxLayoutProperties() .setPlaceholderBox(StaticBoxLayoutProperties.PlaceholderType.SECTION); if (element.getName() != null) { box.setName("Banded-SubReport-Section" + ": name=" + element.getName()); } else { box.setName("Banded-SubReport-Section"); } pushBoxToContext(box, false); }
protected void drawText(final RenderableText renderableText, final long contentX2) { if (renderableText.getLength() == 0) { return; } final long posX = renderableText.getX(); final long posY = renderableText.getY(); final float x1 = (float) (StrictGeomUtility.toExternalValue(posX)); final PdfContentByte cb; PdfTextSpec textSpec = (PdfTextSpec) getTextSpec(); if (textSpec == null) { final StyleSheet layoutContext = renderableText.getStyleSheet(); // The code below may be weird, but at least it is predictable weird. final String fontName = getMetaData() .getNormalizedFontFamilyName( (String) layoutContext.getStyleProperty(TextStyleKeys.FONT)); final String encoding = (String) layoutContext.getStyleProperty(TextStyleKeys.FONTENCODING); final float fontSize = (float) layoutContext.getDoubleStyleProperty(TextStyleKeys.FONTSIZE, 10); final boolean embed = globalEmbed || layoutContext.getBooleanStyleProperty(TextStyleKeys.EMBEDDED_FONT); final boolean bold = layoutContext.getBooleanStyleProperty(TextStyleKeys.BOLD); final boolean italics = layoutContext.getBooleanStyleProperty(TextStyleKeys.ITALIC); final BaseFontFontMetrics fontMetrics = getMetaData() .getBaseFontFontMetrics(fontName, fontSize, bold, italics, encoding, embed, false); final PdfGraphics2D g2 = (PdfGraphics2D) getGraphics(); final Color cssColor = (Color) layoutContext.getStyleProperty(ElementStyleKeys.PAINT); g2.setPaint(cssColor); g2.setFillPaint(); g2.setStrokePaint(); // final float translateY = (float) affineTransform.getTranslateY(); cb = g2.getRawContentByte(); textSpec = new PdfTextSpec(layoutContext, getMetaData(), g2, fontMetrics, cb); setTextSpec(textSpec); cb.beginText(); cb.setFontAndSize(fontMetrics.getBaseFont(), fontSize); } else { cb = textSpec.getContentByte(); } final BaseFontFontMetrics baseFontRecord = textSpec.getFontMetrics(); final BaseFont baseFont = baseFontRecord.getBaseFont(); final float ascent = baseFont.getFontDescriptor(BaseFont.BBOXURY, textSpec.getFontSize()); final float y2 = (float) (StrictGeomUtility.toExternalValue(posY) + ascent); final float y = globalHeight - y2; final AffineTransform affineTransform = textSpec.getGraphics().getTransform(); final float translateX = (float) affineTransform.getTranslateX(); final FontNativeContext nativeContext = baseFontRecord.getNativeContext(); if (baseFontRecord.isTrueTypeFont() && textSpec.isBold() && nativeContext.isNativeBold() == false) { final float strokeWidth = textSpec.getFontSize() / 30.0f; // right from iText ... if (strokeWidth == 1) { cb.setTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_FILL); } else { cb.setTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE); cb.setLineWidth(strokeWidth); } } else { cb.setTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_FILL); } // if the font does not declare to be italics already, emulate it .. if (baseFontRecord.isTrueTypeFont() && textSpec.isItalics() && nativeContext.isNativeItalics() == false) { final float italicAngle = baseFont.getFontDescriptor(BaseFont.ITALICANGLE, textSpec.getFontSize()); if (italicAngle == 0) { // italics requested, but the font itself does not supply italics gylphs. cb.setTextMatrix(1, 0, PdfLogicalPageDrawable.ITALIC_ANGLE, 1, x1 + translateX, y); } else { cb.setTextMatrix(x1 + translateX, y); } } else { cb.setTextMatrix(x1 + translateX, y); } final OutputProcessorMetaData metaData = getMetaData(); final GlyphList gs = renderableText.getGlyphs(); final int offset = renderableText.getOffset(); final CodePointBuffer codePointBuffer = getCodePointBuffer(); if (metaData.isFeatureSupported(OutputProcessorFeature.FAST_FONTRENDERING) && isNormalTextSpacing(renderableText)) { final int maxLength = renderableText.computeMaximumTextSize(contentX2); final String text = gs.getText(renderableText.getOffset(), maxLength, codePointBuffer); cb.showText(text); } else { final PdfTextArray textArray = new PdfTextArray(); final StringBuilder buffer = new StringBuilder(gs.getSize()); final int maxPos = offset + renderableText.computeMaximumTextSize(contentX2); for (int i = offset; i < maxPos; i++) { final Glyph g = gs.getGlyph(i); final Spacing spacing = g.getSpacing(); if (i != offset) { final float optimum = (float) StrictGeomUtility.toFontMetricsValue(spacing.getMinimum()); if (optimum != 0) { textArray.add(buffer.toString()); textArray.add(-optimum / textSpec.getFontSize()); buffer.setLength(0); } } final String text = gs.getGlyphAsString(i, codePointBuffer); buffer.append(text); } if (buffer.length() > 0) { textArray.add(buffer.toString()); } cb.showText(textArray); } }
private static boolean isEmptyElement( final ReportElement band, final StyleSheet style, final OutputProcessorMetaData metaData) { if (isControlBand(style)) { return false; } if (metaData.isFeatureSupported(OutputProcessorFeature.STRICT_COMPATIBILITY)) { if (band instanceof Band) { final Band b = (Band) band; if (b.getElementCount() > 0) { return false; } } } if (BandStyleKeys.LAYOUT_AUTO.equals(style.getStyleProperty(BandStyleKeys.LAYOUT))) { // A auto-band is considered empty. return true; } // A band is not empty, if it has a defined minimum or preferred height if (isLengthDefined(ElementStyleKeys.HEIGHT, style)) { return false; } if (isLengthDefined(ElementStyleKeys.WIDTH, style)) { return false; } if (isLengthDefined(ElementStyleKeys.POS_Y, style)) { return false; } if (isLengthDefined(ElementStyleKeys.POS_X, style)) { return false; } if (isLengthDefined(ElementStyleKeys.MIN_HEIGHT, style)) { return false; } if (isLengthDefined(ElementStyleKeys.MIN_WIDTH, style)) { return false; } if (isLengthDefined(ElementStyleKeys.PADDING_TOP, style)) { return false; } if (isLengthDefined(ElementStyleKeys.PADDING_LEFT, style)) { return false; } if (isLengthDefined(ElementStyleKeys.PADDING_BOTTOM, style)) { return false; } if (isLengthDefined(ElementStyleKeys.PADDING_RIGHT, style)) { return false; } if (BorderStyle.NONE.equals( style.getStyleProperty(ElementStyleKeys.BORDER_BOTTOM_STYLE, BorderStyle.NONE)) == false) { return false; } if (BorderStyle.NONE.equals( style.getStyleProperty(ElementStyleKeys.BORDER_TOP_STYLE, BorderStyle.NONE)) == false) { return false; } if (BorderStyle.NONE.equals( style.getStyleProperty(ElementStyleKeys.BORDER_LEFT_STYLE, BorderStyle.NONE)) == false) { return false; } if (BorderStyle.NONE.equals( style.getStyleProperty(ElementStyleKeys.BORDER_RIGHT_STYLE, BorderStyle.NONE)) == false) { return false; } if (style.getStyleProperty(ElementStyleKeys.BACKGROUND_COLOR) != null) { return false; } if (metaData.isExtraContentElement(band.getStyle(), band.getAttributes())) { return false; } return true; }
private InstanceID startBox( final ReportElement element, final StyleSheet styleSheet, final String layout, final boolean auto) { closeAutoGeneratedPostfixBoxes(); if (BandStyleKeys.LAYOUT_AUTO.equals(layout)) { this.context = new DefaultLayoutModelBuilderContext( this.context, renderNodeFactory.produceRenderBox(element, styleSheet, layout, stateKey)); } else if (BandStyleKeys.LAYOUT_INLINE.equals(layout)) { if (this.context.getRenderBox().isAcceptInlineBoxes() == false) { // parent context is not a inline-inside context. // So we need to create a auto-paragraph wrapper to open a inline-context this.context = new DefaultLayoutModelBuilderContext( this.context, renderNodeFactory.createAutoParagraph(element, styleSheet, stateKey)); // PRD-3750 - A empty inline-band that creates a auto-paragraph reserves space on the // vertical axis. if (metaData.isFeatureSupported(OutputProcessorFeature.STRICT_COMPATIBILITY) || metaData.isFeatureSupported(OutputProcessorFeature.PRD_3750)) { this.context.setAutoGeneratedWrapperBox(true); this.context = new DefaultLayoutModelBuilderContext( this.context, renderNodeFactory.produceRenderBox( element, styleSheet, DefaultRenderNodeFactory.LAYOUT_PARAGRAPH_LINEBOX, stateKey)); } } else { this.context = new DefaultLayoutModelBuilderContext( this.context, renderNodeFactory.produceRenderBox(element, styleSheet, layout, stateKey)); } } else if (this.context.getRenderBox().isAcceptInlineBoxes()) { // inline elements only accept inline element childs this.context = new DefaultLayoutModelBuilderContext( this.context, renderNodeFactory.produceRenderBox( element, styleSheet, BandStyleKeys.LAYOUT_INLINE, stateKey)); } else if (BandStyleKeys.LAYOUT_TABLE_CELL.equals(layout)) { // a table body always needs a table parent .. if (LayoutNodeTypes.TYPE_BOX_TABLE_ROW != this.context.getRenderBox().getLayoutNodeType()) { startBox( element, renderNodeFactory.createAutoGeneratedSectionStyleSheet(styleSheet), BandStyleKeys.LAYOUT_TABLE_ROW, true); } this.context = new DefaultLayoutModelBuilderContext( this.context, renderNodeFactory.produceRenderBox(element, styleSheet, layout, stateKey)); } else if (BandStyleKeys.LAYOUT_TABLE_ROW.equals(layout)) { // a table body always needs a table parent .. if (LayoutNodeTypes.TYPE_BOX_TABLE_SECTION != this.context.getRenderBox().getLayoutNodeType()) { startBox( element, renderNodeFactory.createAutoGeneratedSectionStyleSheet(styleSheet), BandStyleKeys.LAYOUT_TABLE_BODY, true); } this.context = new DefaultLayoutModelBuilderContext( this.context, renderNodeFactory.produceRenderBox(element, styleSheet, layout, stateKey)); } else if (BandStyleKeys.LAYOUT_TABLE_BODY.equals(layout) || BandStyleKeys.LAYOUT_TABLE_FOOTER.equals(layout) || BandStyleKeys.LAYOUT_TABLE_HEADER.equals(layout)) { // a table body always needs a table parent .. if (LayoutNodeTypes.TYPE_BOX_TABLE != this.context.getRenderBox().getLayoutNodeType()) { startBox( element, renderNodeFactory.createAutoGeneratedSectionStyleSheet(styleSheet), BandStyleKeys.LAYOUT_TABLE, true); } this.context = new DefaultLayoutModelBuilderContext( this.context, renderNodeFactory.produceRenderBox(element, styleSheet, layout, stateKey)); } else { // handle ordinary elements, block, canvas, row .. this.context = new DefaultLayoutModelBuilderContext( this.context, renderNodeFactory.produceRenderBox(element, styleSheet, layout, stateKey)); } this.context.setAutoGeneratedWrapperBox(auto); this.context.setEmpty(isEmptyElement(element, styleSheet, metaData)); if (!auto) { if (isControlBand(styleSheet)) { this.context .getRenderBox() .getStaticBoxLayoutProperties() .setPlaceholderBox(StaticBoxLayoutProperties.PlaceholderType.SECTION); } else { this.context .getRenderBox() .getStaticBoxLayoutProperties() .setPlaceholderBox(StaticBoxLayoutProperties.PlaceholderType.NONE); } } this.textProducer.startText(); return this.context.getRenderBox().getInstanceId(); }