protected void processRowLevelNode(final RenderNode node) { assert (node instanceof FinishedRenderNode); node.setCachedX(computeRowPosition(node)); node.setCachedWidth(node.getMaximumBoxWidth()); nodeContext.updateParentX2(node.getCachedX2()); }
private void assertPageValid(final List<LogicalPageBox> pages, final int page, final long offset) throws Exception { final LogicalPageBox pageBox = pages.get(page); final long pageOffset = pageBox.getPageOffset(); // ModelPrinter.INSTANCE.print(pageBox); final RenderNode[] elementsByNodeType = MatchFactory.findElementsByNodeType(pageBox, LayoutNodeTypes.TYPE_BOX_TABLE_SECTION); Assert.assertEquals(2, elementsByNodeType.length); final TableSectionRenderBox header = (TableSectionRenderBox) elementsByNodeType[0]; Assert.assertEquals(TableSectionRenderBox.Role.HEADER, header.getDisplayRole()); final TableSectionRenderBox body = (TableSectionRenderBox) elementsByNodeType[1]; Assert.assertEquals(TableSectionRenderBox.Role.BODY, body.getDisplayRole()); final RenderNode[] rows = MatchFactory.findElementsByNodeType(body, LayoutNodeTypes.TYPE_BOX_TABLE_ROW); Assert.assertTrue("Have rows on page " + page, rows.length > 0); Assert.assertEquals("Header starts at top of page " + page, pageOffset + offset, header.getY()); Assert.assertEquals( "Row starts after the header on page " + page, header.getY() + header.getHeight(), rows[0].getY()); final RenderNode[] table = MatchFactory.findElementsByNodeType(pageBox, LayoutNodeTypes.TYPE_BOX_TABLE); Assert.assertEquals(1, table.length); final RenderBox box = (RenderBox) table[0]; final RenderNode lastChild = box.getLastChild(); Assert.assertEquals( "Table height extends correctly on page " + page, box.getY() + box.getHeight(), lastChild.getY() + lastChild.getHeight()); }
protected void processInlineLevelNode(final RenderNode node) { if (lineBreakState.isInsideParagraph() == false) { throw new InvalidReportStateException( "A inline-level box outside of a paragraph box is not allowed."); } final int nodeType = node.getNodeType(); if (nodeType == LayoutNodeTypes.TYPE_NODE_FINISHEDNODE) { final FinishedRenderNode finNode = (FinishedRenderNode) node; node.setCachedWidth(finNode.getLayoutedWidth()); return; } if (nodeType == LayoutNodeTypes.TYPE_NODE_TEXT) { lineBreakState.add(TextSequenceElement.INSTANCE, node); } else if (nodeType == LayoutNodeTypes.TYPE_NODE_SPACER) { final StyleSheet styleSheet = node.getStyleSheet(); if (WhitespaceCollapse.PRESERVE.equals( styleSheet.getStyleProperty(TextStyleKeys.WHITE_SPACE_COLLAPSE)) && styleSheet.getBooleanStyleProperty(TextStyleKeys.TRIM_TEXT_CONTENT) == false) { // bug-alert: This condition could indicate a workaround for a logic-flaw in the // text-processor lineBreakState.add(SpacerSequenceElement.INSTANCE, node); } else if (lineBreakState.isContainsContent()) { lineBreakState.add(SpacerSequenceElement.INSTANCE, node); } } else { lineBreakState.add(InlineNodeSequenceElement.INSTANCE, node); } }
private boolean isValidDrawTarget(RenderNode node) { while (node != null) { if (ids.contains(node.getInstanceId())) { return true; } node = node.getParent(); } return false; }
private boolean isTableContext(RenderNode node) { while (node != null) { if ((node.getLayoutNodeType() & LayoutNodeTypes.MASK_BOX_TABLE) == LayoutNodeTypes.MASK_BOX_TABLE) { return true; } node = node.getParent(); } return false; }
public void testOrphan4() throws Exception { final MasterReport masterReport = DebugReportRunner.parseGoldenSampleReport("Prd-2087-Orphan-4.prpt"); final LogicalPageBox box = DebugReportRunner.layoutPage(masterReport, 0); final RenderNode srs[] = MatchFactory.findElementsByElementType(box, SubReportType.INSTANCE); assertEquals(1, srs.length); assertEquals(StrictGeomUtility.toInternalValue(20), srs[0].getY()); final RenderNode elementByName = MatchFactory.findElementByName(box, "outer-group"); assertEquals(StrictGeomUtility.toInternalValue(20), elementByName.getY()); }
/** * Canvas elements do not shift content. Therefore the widow definition is not effective. * * @throws Exception */ public void testOrphan5() throws Exception { final MasterReport masterReport = DebugReportRunner.parseGoldenSampleReport("Prd-2087-Orphan-5.prpt"); // masterReport.setCompatibilityLevel(ClassicEngineBoot.computeVersionId(3, 8, 0)); // DebugReportRunner.createXmlPageable(masterReport); final LogicalPageBox box = DebugReportRunner.layoutPage(masterReport, 0); final RenderNode elementByName = MatchFactory.findElementByName(box, "outer-group"); assertEquals(StrictGeomUtility.toInternalValue(20), elementByName.getY()); // ModelPrinter.INSTANCE.print(box); // DebugReportRunner.showDialog(masterReport); }
private long computeCanvasPosition(final RenderNode node) { final long contentAreaX1 = nodeContext.getParentX1(); final long bcw = nodeContext.getBlockContextWidth(); final double posX = node.getNodeLayoutProperties().getPosX(); final long position = RenderLength.resolveLength(bcw, posX); return (contentAreaX1 + position); }
public void addProgressMarkerBox() { final RenderBox parent = this.context.getRenderBox(); final RenderNode child = parent.getLastChild(); if (isCollapseProgressMarker() && child != null && child.getNodeType() == LayoutNodeTypes.TYPE_BOX_PROGRESS_MARKER) { final ProgressMarkerRenderBox markerRenderBox = (ProgressMarkerRenderBox) child; markerRenderBox.setStateKey(stateKey); } else { final ProgressMarkerRenderBox markerBox = new ProgressMarkerRenderBox(); markerBox.setStateKey(stateKey); this.context.addChild(markerBox); markerBox.close(); } this.context.setEmpty(false); }
protected void processOtherNode(final RenderNode node) { if (isValidDrawTarget(node)) { if (bounds == null) { bounds = new StrictBounds(node.getX(), node.getY(), node.getWidth(), node.getHeight()); } else { bounds.add(node.getX(), node.getY(), node.getWidth(), node.getHeight()); } } }
protected void drawBookmark(final RenderNode box, final String bookmark) { if (box.isNodeVisible(getDrawArea()) == false) { return; } final PdfOutline root = writer.getDirectContent().getRootOutline(); final AffineTransform affineTransform = getGraphics().getTransform(); final float translateX = (float) affineTransform.getTranslateX(); final float upperY = translateX + (float) (globalHeight - StrictGeomUtility.toExternalValue(box.getY())); final float leftX = (float) (StrictGeomUtility.toExternalValue(box.getX())); final PdfDestination dest = new PdfDestination(PdfDestination.FIT, leftX, upperY, 0); new PdfOutline(root, dest, bookmark); // destination will always point to the 'current' page // todo: Make this a hierarchy .. }
protected void drawHyperlink( final RenderNode box, final String target, final String window, final String title) { if (box.isNodeVisible(getDrawArea()) == false) { return; } final PdfAction action = createActionForLink(target); final AffineTransform affineTransform = getGraphics().getTransform(); final float translateX = (float) affineTransform.getTranslateX(); final float leftX = translateX + (float) (StrictGeomUtility.toExternalValue(box.getX())); final float rightX = translateX + (float) (StrictGeomUtility.toExternalValue(box.getX() + box.getWidth())); final float lowerY = (float) (globalHeight - StrictGeomUtility.toExternalValue(box.getY() + box.getHeight())); final float upperY = (float) (globalHeight - StrictGeomUtility.toExternalValue(box.getY())); if (action != null) { final PdfAnnotation annotation = new PdfAnnotation(writer, leftX, lowerY, rightX, upperY, action); writer.addAnnotation(annotation); } else if (StringUtils.isEmpty(title) == false) { final Rectangle rect = new Rectangle(leftX, lowerY, rightX, upperY); final PdfAnnotation commentAnnotation = PdfAnnotation.createText(writer, rect, "Tooltip", title, false, null); commentAnnotation.setAppearance( PdfAnnotation.APPEARANCE_NORMAL, writer.getDirectContent().createAppearance(rect.getWidth(), rect.getHeight())); writer.addAnnotation(commentAnnotation); } }
protected boolean drawPdfScript(final RenderNode box) { final Object attribute = box.getAttributes() .getAttribute(AttributeNames.Pdf.NAMESPACE, AttributeNames.Pdf.SCRIPT_ACTION); if (attribute == null) { return false; } final String attributeText = String.valueOf(attribute); final PdfAction action = PdfAction.javaScript(attributeText, writer, false); final AffineTransform affineTransform = getGraphics().getTransform(); final float translateX = (float) affineTransform.getTranslateX(); final float leftX = translateX + (float) (StrictGeomUtility.toExternalValue(box.getX())); final float rightX = translateX + (float) (StrictGeomUtility.toExternalValue(box.getX() + box.getWidth())); final float lowerY = (float) (globalHeight - StrictGeomUtility.toExternalValue(box.getY() + box.getHeight())); final float upperY = (float) (globalHeight - StrictGeomUtility.toExternalValue(box.getY())); final PdfAnnotation annotation = new PdfAnnotation(writer, leftX, lowerY, rightX, upperY, action); writer.addAnnotation(annotation); return true; }
protected void drawAnchor(final RenderNode content) { if (content.isNodeVisible(getDrawArea()) == false) { return; } final String anchorName = (String) content.getStyleSheet().getStyleProperty(ElementStyleKeys.ANCHOR_NAME); if (anchorName == null) { return; } final AffineTransform affineTransform = getGraphics().getTransform(); final float translateX = (float) affineTransform.getTranslateX(); final float upperY = translateX + (float) (globalHeight - StrictGeomUtility.toExternalValue(content.getY())); final float leftX = (float) (StrictGeomUtility.toExternalValue(content.getX())); final PdfDestination dest = new PdfDestination(PdfDestination.FIT, leftX, upperY, 0); writer.getDirectContent().localDestination(anchorName, dest); }
protected void processParagraphChilds(final ParagraphRenderBox box) { paragraphLayoutWatch.start(); try { final MinorAxisNodeContext nodeContext = getNodeContext(); final MinorAxisParagraphBreakState breakState = getLineBreakState(); if (box.isComplexParagraph()) { final RenderBox lineboxContainer = box.getLineboxContainer(); RenderNode node = lineboxContainer.getFirstChild(); while (node != null) { // all childs of the linebox container must be inline boxes. They // represent the lines in the paragraph. Any other element here is // a error that must be reported if (node.getNodeType() != LayoutNodeTypes.TYPE_BOX_LINEBOX) { throw new IllegalStateException("Expected ParagraphPoolBox elements."); } final ParagraphPoolBox inlineRenderBox = (ParagraphPoolBox) node; if (startLine(inlineRenderBox)) { processBoxChilds(inlineRenderBox); finishLine(inlineRenderBox, nodeContext, breakState); } node = node.getNext(); } } else { final ParagraphPoolBox node = box.getPool(); if (node.getFirstChild() == null) { return; } // all childs of the linebox container must be inline boxes. They // represent the lines in the paragraph. Any other element here is // a error that must be reported if (startLine(node)) { processBoxChilds(node); finishLine(node, nodeContext, breakState); } } } finally { paragraphLayoutWatch.stop(true); } }
public static String computePrintedText(RenderBox renderBox) { StringBuilder b = new StringBuilder(); RenderNode lineChild = renderBox.getFirstChild(); while (lineChild != null) { if (lineChild instanceof RenderableText) { RenderableText text = (RenderableText) lineChild; b.append(text.getRawText()); } else if (lineChild instanceof SpacerRenderNode) { SpacerRenderNode spacer = (SpacerRenderNode) lineChild; for (int i = 0; i < spacer.getSpaceCount(); i += 1) b.append(' '); } else if (lineChild instanceof RenderBox) { b.append(computePrintedText((RenderBox) lineChild)); } lineChild = lineChild.getNext(); } return b.toString(); }
private long computeRowPosition(final RenderNode node) { // The y-position of a box depends on the parent. final RenderBox parent = node.getParent(); // A table row is something special. Although it is a block box, // it layouts its children from left to right if (parent == null) { // there's no parent .. return 0; } final RenderNode prev = node.getPrev(); if (prev != null) { // we have a sibling. Position yourself directly to the right of your sibling .. return prev.getCachedX() + prev.getCachedWidth(); } else { return nodeContext.getParentX1(); } }
protected void drawComplexText(final RenderableComplexText renderableComplexText) { try { if (renderableComplexText.getRichText().isEmpty()) { // This text is empty. return; } if (renderableComplexText.isNodeVisible(getParagraphBounds(), isOverflowX(), isOverflowY()) == false) { return; } // iterate through all inline elements for (final RichTextSpec.StyledChunk styledChunk : renderableComplexText.getRichText().getStyleChunks()) { RenderNode node = styledChunk.getOriginatingTextNode(); InstanceID dummy = node.getInstanceId(); textExtractorHelper.startInlineBox( dummy, styledChunk.getOriginalAttributes(), styledChunk.getStyleSheet(), BoxDefinition.EMPTY); if (node instanceof RenderableReplacedContentBox) { processRenderableContent((RenderableReplacedContentBox) node); result = true; } else { String text = styledChunk.getText(); xmlWriter.writeText(characterEntityParser.encodeEntities(text)); if (text.trim().length() > 0) { result = true; } } textExtractorHelper.finishBox(dummy, styledChunk.getOriginalAttributes()); clearText(); } } catch (final IOException ioe) { throw new InvalidReportStateException("Failed to write text", ioe); } }
protected void processOtherNode(final RenderNode node) { try { final int nodeType = node.getNodeType(); if (nodeType == LayoutNodeTypes.TYPE_NODE_TEXT || nodeType == LayoutNodeTypes.TYPE_NODE_COMPLEX_TEXT) { super.processOtherNode(node); return; } if (node.isVirtualNode()) { return; } if (nodeType == LayoutNodeTypes.TYPE_NODE_SPACER) { final SpacerRenderNode spacer = (SpacerRenderNode) node; final int count = Math.max(1, spacer.getSpaceCount()); for (int i = 0; i < count; i++) { xmlWriter.writeText(" "); } } } catch (final IOException e) { throw new RuntimeException("Failed", e); } }
protected void processLinksAndAnchors(final RenderNode box) { final StyleSheet styleSheet = box.getStyleSheet(); if (drawPdfScript(box) == false) { final String target = (String) styleSheet.getStyleProperty(ElementStyleKeys.HREF_TARGET); final String title = (String) styleSheet.getStyleProperty(ElementStyleKeys.HREF_TITLE); if (target != null || title != null) { final String window = (String) styleSheet.getStyleProperty(ElementStyleKeys.HREF_WINDOW); drawHyperlink(box, target, window, title); } } final String anchor = (String) styleSheet.getStyleProperty(ElementStyleKeys.ANCHOR_NAME); if (anchor != null) { drawAnchor(box); } final String bookmark = (String) styleSheet.getStyleProperty(BandStyleKeys.BOOKMARK); if (bookmark != null) { drawBookmark(box, bookmark); } }
private void finishLine( final RenderBox inlineRenderBox, final MinorAxisNodeContext nodeContext, final MinorAxisParagraphBreakState breakState) { if (breakState.isInsideParagraph() == false || breakState.isSuspended()) { throw new IllegalStateException("No active breakstate, finish-line cannot continue."); } final PageGrid pageGrid = getPageGrid(); final OutputProcessorMetaData metaData = getMetaData(); breakState.add(EndSequenceElement.INSTANCE, inlineRenderBox); final ParagraphRenderBox paragraph = breakState.getParagraph(); final ElementAlignment textAlignment = paragraph.getTextAlignment(); final long textIndent = paragraph.getTextIndent(); final long firstLineIndent = paragraph.getFirstLineIndent(); // This aligns all direct childs. Once that is finished, we have to // check, whether possibly existing inner-paragraphs are still valid // or whether moving them violated any of the inner-pagebreak constraints. final TextAlignmentProcessor processor = create(textAlignment); final SequenceList sequence = breakState.getSequence(); final long lineEnd; final boolean overflowX = paragraph.getStaticBoxLayoutProperties().isOverflowX(); if (overflowX) { lineEnd = nodeContext.getX1() + OVERFLOW_DUMMY_WIDTH; } else { lineEnd = nodeContext.getX2(); } long lineStart = Math.min(lineEnd, nodeContext.getX1() + firstLineIndent); if (lineEnd - lineStart <= 0) { final long minimumChunkWidth = paragraph.getPool().getMinimumChunkWidth(); processor.initialize( metaData, sequence, lineStart, lineStart + minimumChunkWidth, pageGrid, overflowX); nodeContext.updateX2(lineStart + minimumChunkWidth); logger.warn("Auto-Corrected zero-width first-line on paragraph - " + paragraph.getName()); } else { processor.initialize(metaData, sequence, lineStart, lineEnd, pageGrid, overflowX); if (overflowX == false) { nodeContext.updateX2(lineEnd); } } while (processor.hasNext()) { final RenderNode linebox = processor.next(); if (linebox.getLayoutNodeType() != LayoutNodeTypes.TYPE_BOX_LINEBOX) { throw new IllegalStateException("Line must not be null"); } paragraph.addGeneratedChild(linebox); if (processor.hasNext()) { lineStart = Math.min(lineEnd, nodeContext.getX1() + textIndent); if (lineEnd - lineStart <= 0) { final long minimumChunkWidth = paragraph.getPool().getMinimumChunkWidth(); processor.updateLineSize(lineStart, lineStart + minimumChunkWidth); nodeContext.updateX2(lineStart + minimumChunkWidth); logger.warn( "Auto-Corrected zero-width text-line on paragraph continuation - " + paragraph.getName()); } else { processor.updateLineSize(lineStart, lineEnd); if (overflowX == false) { nodeContext.updateX2(lineEnd); } } } } processor.deinitialize(); }
/** * The extra-space width for an element. Some elements can expand to fill some more space * (justified text is a good example, adding some space between the letters of each word to reduce * the inner-word spacing). * * @return */ public long getMaximumWidth(final RenderNode node) { return node.getMaximumBoxWidth(); }
public RenderBox next() { cleanFirstSpacers(); Arrays.fill(elementDimensions, 0); Arrays.fill(elementPositions, 0); int lastPosition = iterate(sequenceElements, sequenceFill); if (lastPosition == 0) { // This could evolve into an infinite loop. Thats evil. // We have two choices to prevent that: // (1) Try to break the element. // if (getBreakableIndex() >= 0) // { // // Todo: Breaking is not yet implemented .. // } if (getSkipIndex() >= 0) { // This causes an overflow .. performSkipAlignment(getSkipIndex()); lastPosition = getSkipIndex(); } else { // Skip the complete line. Oh, thats not good, really! lastPosition = sequenceFill; } } // now, build the line and update the array .. pendingElements.clear(); contexts.clear(); RenderBox firstBox = null; RenderBox box = null; for (int i = 0; i < lastPosition; i++) { final RenderNode node = nodes[i]; final InlineSequenceElement element = sequenceElements[i]; if (element instanceof EndSequenceElement) { contexts.pop(); final long boxX2 = (elementPositions[i] + elementDimensions[i]); box.setCachedWidth(boxX2 - box.getCachedX()); if (contexts.isEmpty()) { box = null; } else { final RenderNode tmpnode = box; box = contexts.peek(); box.addGeneratedChild(tmpnode); } continue; } if (element instanceof StartSequenceElement) { box = (RenderBox) node.derive(false); box.setCachedX(elementPositions[i]); contexts.push(box); if (firstBox == null) { firstBox = box; } continue; } if (box == null) { throw new IllegalStateException( "Invalid sequence: " + "Cannot have elements before we open the box context."); } // Content element: Perform a deep-deriveForAdvance, so that we preserve the // possibly existing sub-nodes. final RenderNode child = node.derive(true); child.setCachedX(elementPositions[i]); child.setCachedWidth(elementDimensions[i]); if (box.getStaticBoxLayoutProperties().isPreserveSpace() && box.getStyleSheet().getBooleanStyleProperty(TextStyleKeys.TRIM_TEXT_CONTENT) == false) { // Take a shortcut as we know that we will never have any pending elements if preserve is // true and // trim-content is false. box.addGeneratedChild(child); continue; } if (child.isIgnorableForRendering()) { pendingElements.add(child); } else { for (int j = 0; j < pendingElements.size(); j++) { final RenderNode pendingNode = pendingElements.get(j); box.addGeneratedChild(pendingNode); } pendingElements.clear(); box.addGeneratedChild(child); } } // Remove all spacers and other non printable content that might // look ugly at the beginning of a new line .. for (; lastPosition < sequenceFill; lastPosition++) { final RenderNode node = nodes[lastPosition]; final StyleSheet styleSheet = node.getStyleSheet(); if (WhitespaceCollapse.PRESERVE.equals( styleSheet.getStyleProperty(TextStyleKeys.WHITE_SPACE_COLLAPSE)) && styleSheet.getBooleanStyleProperty(TextStyleKeys.TRIM_TEXT_CONTENT) == false) { break; } if (node.isIgnorableForRendering() == false) { break; } } // If there are open contexts, then add the split-result to the new line // and update the width of the current line RenderBox previousContext = null; final int openContexts = contexts.size(); for (int i = 0; i < openContexts; i++) { final RenderBox renderBox = contexts.get(i); final long cachedWidth = getEndOfLine() - renderBox.getCachedX(); renderBox.setCachedWidth(cachedWidth); final InlineRenderBox rightBox = (InlineRenderBox) renderBox.split(RenderNode.HORIZONTAL_AXIS); sequenceElements[i] = StartSequenceElement.INSTANCE; nodes[i] = rightBox; if (previousContext != null) { previousContext.addGeneratedChild(renderBox); } previousContext = renderBox; } final int length = sequenceFill - lastPosition; System.arraycopy(sequenceElements, lastPosition, sequenceElements, openContexts, length); System.arraycopy(nodes, lastPosition, nodes, openContexts, length); sequenceFill = openContexts + length; Arrays.fill(sequenceElements, sequenceFill, sequenceElements.length, null); Arrays.fill(nodes, sequenceFill, nodes.length, null); return firstBox; }
public void testWeirdTocLayout() throws ReportProcessingException, ContentProcessingException { Element textField = new Element(); textField.setName("textField"); textField.getStyle().setStyleProperty(TextStyleKeys.FONT, "Arial"); textField.getStyle().setStyleProperty(TextStyleKeys.FONTSIZE, 14); textField.getStyle().setStyleProperty(TextStyleKeys.TEXT_WRAP, TextWrap.NONE); textField.getStyle().setStyleProperty(ElementStyleKeys.MIN_WIDTH, 97f); textField.getStyle().setStyleProperty(ElementStyleKeys.MIN_HEIGHT, 20f); textField.getStyle().setStyleProperty(ElementStyleKeys.POS_X, 0f); textField.getStyle().setStyleProperty(ElementStyleKeys.POS_Y, 0f); textField.setElementType(LabelType.INSTANCE); textField.setAttribute( AttributeNames.Core.NAMESPACE, AttributeNames.Core.VALUE, "Classic Cars"); Element dotField = new Element(); dotField.setName("dotField"); dotField.getStyle().setStyleProperty(TextStyleKeys.FONT, "Arial"); dotField.getStyle().setStyleProperty(TextStyleKeys.FONTSIZE, 14); dotField.getStyle().setStyleProperty(ElementStyleKeys.ALIGNMENT, ElementAlignment.RIGHT); dotField.getStyle().setStyleProperty(ElementStyleKeys.VALIGNMENT, ElementAlignment.TOP); dotField.getStyle().setStyleProperty(ElementStyleKeys.POS_X, 97f); dotField.getStyle().setStyleProperty(ElementStyleKeys.POS_Y, 0f); dotField.getStyle().setStyleProperty(ElementStyleKeys.MIN_WIDTH, 628.463f); dotField.getStyle().setStyleProperty(ElementStyleKeys.MIN_WIDTH, 20f); dotField.getStyle().setStyleProperty(ElementStyleKeys.WIDTH, 100f); dotField.getStyle().setStyleProperty(ElementStyleKeys.MAX_WIDTH, 100f); dotField.setElementType(LabelType.INSTANCE); dotField.setAttribute( AttributeNames.Core.NAMESPACE, AttributeNames.Core.VALUE, " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . " + " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . " + ". . . . . . . . . . . . . . . . . ."); Band band = new Band(); band.setName("outer-box"); band.setLayout("inline"); band.getStyle().setStyleProperty(ElementStyleKeys.BOX_SIZING, BoxSizing.CONTENT_BOX); band.getStyle().setStyleProperty(ElementStyleKeys.OVERFLOW_X, false); band.getStyle().setStyleProperty(ElementStyleKeys.OVERFLOW_Y, false); band.getStyle().setStyleProperty(TextStyleKeys.LINEHEIGHT, 1f); band.getStyle() .setStyleProperty(TextStyleKeys.WHITE_SPACE_COLLAPSE, WhitespaceCollapse.PRESERVE_BREAKS); band.getStyle().setStyleProperty(ElementStyleKeys.MIN_WIDTH, 708f); band.getStyle().setStyleProperty(ElementStyleKeys.MIN_HEIGHT, 12f); band.getStyle().setStyleProperty(ElementStyleKeys.MAX_HEIGHT, 20f); band.addElement(textField); band.addElement(dotField); final MasterReport report = new MasterReport(); report.getReportHeader().addElement(band); LogicalPageBox logicalPageBox = DebugReportRunner.layoutSingleBand(report, report.getReportHeader(), false, false); // ModelPrinter.INSTANCE.print(logicalPageBox); RenderBox outerBox = (RenderBox) MatchFactory.findElementByName(logicalPageBox, "outer-box"); RenderNode dotFieldBox = MatchFactory.findElementByName(logicalPageBox, "dotField"); RenderNode textFieldBox = MatchFactory.findElementByName(logicalPageBox, "textField"); assertNotNull(outerBox); assertNotNull(dotFieldBox); assertNotNull(textFieldBox); assertEquals(0, outerBox.getY()); assertEquals(0, dotFieldBox.getY()); assertEquals(0, textFieldBox.getY()); // box only contains one line, and min-size is set to 8, max size = 20, so the line-height of // 14.024 is used. assertEquals(StrictGeomUtility.toInternalValue(14.024), outerBox.getHeight()); assertEquals(StrictGeomUtility.toInternalValue(14.024), outerBox.getFirstChild().getHeight()); assertEquals(StrictGeomUtility.toInternalValue(14), dotFieldBox.getHeight()); assertEquals(StrictGeomUtility.toInternalValue(14), textFieldBox.getHeight()); }
protected void processTableRowLevelNode(final RenderNode node) { assert (node instanceof FinishedRenderNode); node.setCachedX(nodeContext.getX1()); node.setCachedWidth(nodeContext.getContentAreaWidth()); }
public void performLastLineAlignment() { if (pagebreakCount == 0) { throw new IllegalStateException("Alignment processor has not been initialized correctly."); } Arrays.fill(elementDimensions, 0); Arrays.fill(elementPositions, 0); int lastPosition = iterate(sequenceElements, sequenceFill); if (lastPosition == 0) { // This could evolve into an infinite loop. Thats evil. // We have two choices to prevent that: // (1) Try to break the element. // if (getBreakableIndex() >= 0) // { // // Todo: Breaking is not yet implemented .. // } if (getSkipIndex() >= 0) { // This causes an overflow .. performSkipAlignment(getSkipIndex()); lastPosition = getSkipIndex(); } else { // Skip the complete line. Oh, thats not good, really! lastPosition = sequenceFill; } } // the elements up to the 'lastPosition' are now aligned according to the alignment rules. // now, update the element's positions and dimensions .. if (lastPosition == sequenceFill || lastLineAlignment) { // First, the simple case: The line's content did fully fit into the linebox. No linebreaks // were necessary. RenderBox firstBox = null; for (int i = 0; i < lastPosition; i++) { final RenderNode node = nodes[i]; final InlineSequenceElement element = sequenceElements[i]; if (element instanceof EndSequenceElement) { final long boxX2 = (elementPositions[i] + elementDimensions[i]); final RenderBox box = (RenderBox) node; box.setCachedWidth(boxX2 - box.getCachedX()); continue; } if (element instanceof StartSequenceElement) { final RenderBox box = (RenderBox) node; box.setCachedX(elementPositions[i]); if (firstBox == null) { firstBox = box; } continue; } // Content element: Perform a deep-deriveForAdvance, so that we preserve the // possibly existing sub-nodes. node.setCachedX(elementPositions[i]); node.setCachedWidth(elementDimensions[i]); } return; } // The second case is more complicated. The text did not fit fully into the text-element. // Left align all elements after the layouted content .. if (leftAlignProcessor == null) { leftAlignProcessor = new LeftAlignmentProcessor(); } leftAlignProcessor.initializeForLastLineAlignment(this); leftAlignProcessor.performLastLineAlignment(); leftAlignProcessor.deinitialize(); }
/** * The width of the element. This is the minimum width of the element. * * @return */ public long getMinimumWidth(final RenderNode node) { return node.getMinimumChunkWidth(); }