From e05b816bf5413f7a1f6b9dfbf4652b5927f07640 Mon Sep 17 00:00:00 2001 From: Keiron Liddle Date: Fri, 30 Aug 2002 08:03:24 +0000 Subject: [PATCH] start implementation of block-container does absolute and static and the various reference-orientation git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@195127 13f79535-47bb-0310-9956-ffa450edef68 --- src/org/apache/fop/area/Block.java | 4 + src/org/apache/fop/area/BlockParent.java | 7 + src/org/apache/fop/area/BlockViewport.java | 41 ++ src/org/apache/fop/fo/PropertyManager.java | 385 +++++++++--------- .../apache/fop/fo/flow/BlockContainer.java | 16 +- .../fop/fo/flow/InstreamForeignObject.java | 2 +- .../fop/layout/AbsolutePositionProps.java | 8 +- .../BlockContainerLayoutManager.java | 293 +++++++++++++ .../apache/fop/render/AbstractRenderer.java | 49 ++- .../apache/fop/render/pdf/PDFRenderer.java | 115 +++++- 10 files changed, 707 insertions(+), 213 deletions(-) create mode 100644 src/org/apache/fop/area/BlockViewport.java create mode 100644 src/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java diff --git a/src/org/apache/fop/area/Block.java b/src/org/apache/fop/area/Block.java index d1e605d43..0d745207c 100644 --- a/src/org/apache/fop/area/Block.java +++ b/src/org/apache/fop/area/Block.java @@ -67,6 +67,10 @@ public class Block extends BlockParent implements Serializable { return bpd; } + public void setPositioning(int pos) { + positioning = pos; + } + public int getPositioning() { return positioning; } diff --git a/src/org/apache/fop/area/BlockParent.java b/src/org/apache/fop/area/BlockParent.java index 2274c3790..f265e6d10 100644 --- a/src/org/apache/fop/area/BlockParent.java +++ b/src/org/apache/fop/area/BlockParent.java @@ -38,4 +38,11 @@ public class BlockParent extends Area implements Serializable { return children; } + public void setBounds(Rectangle2D b) { + bounds = b; + } + + public Rectangle2D getBounds() { + return bounds; + } } diff --git a/src/org/apache/fop/area/BlockViewport.java b/src/org/apache/fop/area/BlockViewport.java new file mode 100644 index 000000000..95443821e --- /dev/null +++ b/src/org/apache/fop/area/BlockViewport.java @@ -0,0 +1,41 @@ +/* + * $Id$ + * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources. + */ + +package org.apache.fop.area; + +import java.awt.geom.Rectangle2D; + +/** + * A BlockViewport. + * This is used for block level Viewport/reference pairs. + * The block-container creates this area. + */ +public class BlockViewport extends Block { + // clipping for this viewport + boolean clip = false; + CTM viewportCTM; + + public BlockViewport() { + + } + + public void setCTM(CTM ctm) { + viewportCTM = ctm; + } + + public CTM getCTM() { + return viewportCTM; + } + + public void setClip(boolean cl) { + clip = cl; + } + + public boolean getClip() { + return clip; + } +} diff --git a/src/org/apache/fop/fo/PropertyManager.java b/src/org/apache/fop/fo/PropertyManager.java index 2599cb0df..44a98f735 100644 --- a/src/org/apache/fop/fo/PropertyManager.java +++ b/src/org/apache/fop/fo/PropertyManager.java @@ -26,7 +26,7 @@ import org.apache.fop.layout.AbsolutePositionProps; import org.apache.fop.traits.BlockProps; import org.apache.fop.traits.InlineProps; import org.apache.fop.traits.SpaceVal; -import org.apache.fop.traits.LayoutProps; // keep, break, span, space? +import org.apache.fop.traits.LayoutProps; // keep, break, span, space? import org.apache.fop.fo.properties.BreakAfter; import org.apache.fop.fo.properties.BreakBefore; import org.apache.fop.fo.properties.Constants; @@ -46,55 +46,54 @@ public class PropertyManager { private HyphenationProps hyphProps = null; private TextInfo textInfo = null; - private static String[] saBefore = new String[] {"before"}; - private static String[] saAfter = new String[] {"after"}; - private static String[] saStart = new String[] {"start"}; - private static String[] saEnd = new String[] {"end"}; + private static String[] saBefore = new String[]{"before"}; + private static String[] saAfter = new String[]{"after"}; + private static String[] saStart = new String[]{"start"}; + private static String[] saEnd = new String[]{"end"}; - private static MessageFormat msgColorFmt = - new MessageFormat("border-{0}-color"); - private static MessageFormat msgStyleFmt = - new MessageFormat("border-{0}-style"); - private static MessageFormat msgWidthFmt = - new MessageFormat("border-{0}-width"); - private static MessageFormat msgPaddingFmt = - new MessageFormat("padding-{0}"); + private static MessageFormat msgColorFmt = new MessageFormat("border-{0}-color"); + private static MessageFormat msgStyleFmt = new MessageFormat("border-{0}-style"); + private static MessageFormat msgWidthFmt = new MessageFormat("border-{0}-width"); + private static MessageFormat msgPaddingFmt = new MessageFormat("padding-{0}"); public PropertyManager(PropertyList pList) { this.properties = pList; } + public PropertyList getProperties() { + return properties; + } + public void setFontInfo(FontInfo fontInfo) { - m_fontInfo = fontInfo; + m_fontInfo = fontInfo; } public FontState getFontState(FontInfo fontInfo) { if (fontState == null) { - if (fontInfo == null) { - fontInfo = m_fontInfo; - } - else if (m_fontInfo == null) { - m_fontInfo = fontInfo; - } + if (fontInfo == null) { + fontInfo = m_fontInfo; + } else if (m_fontInfo == null) { + m_fontInfo = fontInfo; + } String fontFamily = properties.get("font-family").getString(); String fontStyle = properties.get("font-style").getString(); String fw = properties.get("font-weight").getString(); int fontWeight = 400; - if(fw.equals("bolder")) { + if (fw.equals("bolder")) { // +100 from inherited - } else if(fw.equals("lighter")) { + } else if (fw.equals("lighter")) { // -100 from inherited } else { try { fontWeight = Integer.parseInt(fw); - } catch(NumberFormatException nfe) { + } catch (NumberFormatException nfe) { } } - fontWeight = ((int)fontWeight / 100) * 100; - if(fontWeight < 100) { + fontWeight = ((int) fontWeight / 100) * 100; + if (fontWeight < 100) { fontWeight = 100; - } else if(fontWeight > 900) { + } else if (fontWeight > 900) { fontWeight = 900; } @@ -125,97 +124,104 @@ public class PropertyManager { private void initBorderInfo(int whichSide, String[] saSide) { borderAndPadding.setPadding(whichSide, - properties.get(msgPaddingFmt.format(saSide)).getCondLength()); + properties.get( + msgPaddingFmt.format(saSide)).getCondLength()); // If style = none, force width to 0, don't get Color int style = properties.get(msgStyleFmt.format(saSide)).getEnum(); if (style != Constants.NONE) { borderAndPadding.setBorder(whichSide, style, - properties.get(msgWidthFmt.format(saSide)).getCondLength(), - properties.get(msgColorFmt.format(saSide)).getColorType()); + properties.get( + msgWidthFmt.format(saSide)).getCondLength(), + properties.get( + msgColorFmt.format(saSide)).getColorType()); } } public HyphenationProps getHyphenationProps() { if (hyphProps == null) { this.hyphProps = new HyphenationProps(); - hyphProps.hyphenate = this.properties.get("hyphenate").getEnum(); - hyphProps.hyphenationChar = - this.properties.get("hyphenation-character").getCharacter(); - hyphProps.hyphenationPushCharacterCount = - this.properties.get("hyphenation-push-character-count").getNumber().intValue(); - hyphProps.hyphenationRemainCharacterCount = - this.properties.get("hyphenation-remain-character-count").getNumber().intValue(); - hyphProps.language = this.properties.get("language").getString(); + hyphProps.hyphenate = + this.properties.get("hyphenate").getEnum(); + hyphProps.hyphenationChar = this.properties.get( + "hyphenation-character").getCharacter(); + hyphProps.hyphenationPushCharacterCount = this.properties.get( + "hyphenation-push-character-count").getNumber(). + intValue(); + hyphProps.hyphenationRemainCharacterCount = this.properties.get( + "hyphenation-remain-character-count").getNumber(). + intValue(); + hyphProps.language = + this.properties.get("language").getString(); hyphProps.country = this.properties.get("country").getString(); } return hyphProps; } /*public int checkBreakBefore(Area area) { - if (!(area instanceof ColumnArea)) { - switch (properties.get("break-before").getEnum()) { - case BreakBefore.PAGE: - return Status.FORCE_PAGE_BREAK; - case BreakBefore.ODD_PAGE: - return Status.FORCE_PAGE_BREAK_ODD; - case BreakBefore.EVEN_PAGE: - return Status.FORCE_PAGE_BREAK_EVEN; - case BreakBefore.COLUMN: - return Status.FORCE_COLUMN_BREAK; - default: - return Status.OK; - } - } else { - ColumnArea colArea = (ColumnArea)area; - switch (properties.get("break-before").getEnum()) { - case BreakBefore.PAGE: - // if first ColumnArea, and empty, return OK - if (!colArea.hasChildren() && (colArea.getColumnIndex() == 1)) - return Status.OK; - else - return Status.FORCE_PAGE_BREAK; - case BreakBefore.ODD_PAGE: - // if first ColumnArea, empty, _and_ in odd page, - // return OK - if (!colArea.hasChildren() && (colArea.getColumnIndex() == 1) - && (colArea.getPage().getNumber() % 2 != 0)) - return Status.OK; - else - return Status.FORCE_PAGE_BREAK_ODD; - case BreakBefore.EVEN_PAGE: - // if first ColumnArea, empty, _and_ in even page, - // return OK - if (!colArea.hasChildren() && (colArea.getColumnIndex() == 1) - && (colArea.getPage().getNumber() % 2 == 0)) - return Status.OK; - else - return Status.FORCE_PAGE_BREAK_EVEN; - case BreakBefore.COLUMN: - // if ColumnArea is empty return OK - if (!area.hasChildren()) - return Status.OK; - else - return Status.FORCE_COLUMN_BREAK; - default: - return Status.OK; - } - } - } - - public int checkBreakAfter(Area area) { - switch (properties.get("break-after").getEnum()) { - case BreakAfter.PAGE: - return Status.FORCE_PAGE_BREAK; - case BreakAfter.ODD_PAGE: - return Status.FORCE_PAGE_BREAK_ODD; - case BreakAfter.EVEN_PAGE: - return Status.FORCE_PAGE_BREAK_EVEN; - case BreakAfter.COLUMN: - return Status.FORCE_COLUMN_BREAK; - default: - return Status.OK; - } - }*/ + if (!(area instanceof ColumnArea)) { + switch (properties.get("break-before").getEnum()) { + case BreakBefore.PAGE: + return Status.FORCE_PAGE_BREAK; + case BreakBefore.ODD_PAGE: + return Status.FORCE_PAGE_BREAK_ODD; + case BreakBefore.EVEN_PAGE: + return Status.FORCE_PAGE_BREAK_EVEN; + case BreakBefore.COLUMN: + return Status.FORCE_COLUMN_BREAK; + default: + return Status.OK; + } + } else { + ColumnArea colArea = (ColumnArea)area; + switch (properties.get("break-before").getEnum()) { + case BreakBefore.PAGE: + // if first ColumnArea, and empty, return OK + if (!colArea.hasChildren() && (colArea.getColumnIndex() == 1)) + return Status.OK; + else + return Status.FORCE_PAGE_BREAK; + case BreakBefore.ODD_PAGE: + // if first ColumnArea, empty, _and_ in odd page, + // return OK + if (!colArea.hasChildren() && (colArea.getColumnIndex() == 1) + && (colArea.getPage().getNumber() % 2 != 0)) + return Status.OK; + else + return Status.FORCE_PAGE_BREAK_ODD; + case BreakBefore.EVEN_PAGE: + // if first ColumnArea, empty, _and_ in even page, + // return OK + if (!colArea.hasChildren() && (colArea.getColumnIndex() == 1) + && (colArea.getPage().getNumber() % 2 == 0)) + return Status.OK; + else + return Status.FORCE_PAGE_BREAK_EVEN; + case BreakBefore.COLUMN: + // if ColumnArea is empty return OK + if (!area.hasChildren()) + return Status.OK; + else + return Status.FORCE_COLUMN_BREAK; + default: + return Status.OK; + } + } + } + + public int checkBreakAfter(Area area) { + switch (properties.get("break-after").getEnum()) { + case BreakAfter.PAGE: + return Status.FORCE_PAGE_BREAK; + case BreakAfter.ODD_PAGE: + return Status.FORCE_PAGE_BREAK_ODD; + case BreakAfter.EVEN_PAGE: + return Status.FORCE_PAGE_BREAK_EVEN; + case BreakAfter.COLUMN: + return Status.FORCE_COLUMN_BREAK; + default: + return Status.OK; + } + }*/ public MarginProps getMarginProps() { @@ -223,21 +229,25 @@ public class PropertyManager { // Common Margin Properties-Block props.marginTop = - this.properties.get("margin-top").getLength().mvalue(); + this.properties.get("margin-top").getLength().mvalue(); props.marginBottom = - this.properties.get("margin-bottom").getLength().mvalue(); + this.properties.get("margin-bottom").getLength().mvalue(); props.marginLeft = - this.properties.get("margin-left").getLength().mvalue(); + this.properties.get("margin-left").getLength().mvalue(); props.marginRight = - this.properties.get("margin-right").getLength().mvalue(); + this.properties.get("margin-right").getLength().mvalue(); // For now, we only get the optimum value for space-before and after - props.spaceBefore = this.properties.get("space-before").getSpace(). - getOptimum().getLength().mvalue(); - props.spaceAfter = this.properties.get("space-after").getSpace(). - getOptimum().getLength().mvalue(); - props.startIndent = this.properties.get("start-indent").getLength().mvalue(); - props.endIndent = this.properties.get("end-indent").getLength().mvalue(); + props.spaceBefore = this.properties.get( + "space-before").getSpace(). getOptimum().getLength(). + mvalue(); + props.spaceAfter = this.properties.get( + "space-after").getSpace(). getOptimum().getLength(). + mvalue(); + props.startIndent = + this.properties.get("start-indent").getLength().mvalue(); + props.endIndent = + this.properties.get("end-indent").getLength().mvalue(); return props; } @@ -254,10 +264,10 @@ public class PropertyManager { public InlineProps getInlineProps() { InlineProps props = new InlineProps(); - props.spaceStart = new SpaceVal(properties.get("space-start"). - getSpace()); - props.spaceEnd = new SpaceVal(properties.get("space-end"). - getSpace()); + props.spaceStart = + new SpaceVal(properties.get("space-start"). getSpace()); + props.spaceEnd = + new SpaceVal(properties.get("space-end"). getSpace()); return props; } @@ -265,11 +275,11 @@ public class PropertyManager { AccessibilityProps props = new AccessibilityProps(); String str; str = this.properties.get("source-document").getString(); - if(!"none".equals(str)) { + if (!"none".equals(str)) { props.sourceDoc = str; } str = this.properties.get("role").getString(); - if(!"none".equals(str)) { + if (!"none".equals(str)) { props.role = str; } return props; @@ -287,19 +297,25 @@ public class PropertyManager { public AbsolutePositionProps getAbsolutePositionProps() { AbsolutePositionProps props = new AbsolutePositionProps(); + props.absolutePosition = + this.properties.get("absolute-position").getEnum(); + props.top = this.properties.get("top").getLength().mvalue(); + props.bottom = this.properties.get("bottom").getLength().mvalue(); + props.left = this.properties.get("left").getLength().mvalue(); + props.right = this.properties.get("right").getLength().mvalue(); return props; } public BlockProps getBlockProps() { BlockProps props = new BlockProps(); - props.firstIndent = this.properties.get("text-indent"). - getLength().mvalue(); + props.firstIndent = + this.properties.get("text-indent"). getLength().mvalue(); props.lastIndent = 0; /*this.properties.get("last-line-end-indent").getLength().mvalue(); */ props.textAlign = this.properties.get("text-align").getEnum(); - props.textAlignLast = this.properties.get("text-align-last"). - getEnum(); - props.lineStackType = this.properties. - get("line-stacking-strategy").getEnum(); + props.textAlignLast = + this.properties.get("text-align-last"). getEnum(); + props.lineStackType = + this.properties. get("line-stacking-strategy").getEnum(); return props; } @@ -308,81 +324,83 @@ public class PropertyManager { LayoutProps props = new LayoutProps(); props.breakBefore = this.properties.get("break-before").getEnum(); props.breakAfter = this.properties.get("break-after").getEnum(); - props.bIsSpan = (this.properties.get("span").getEnum() == Span.ALL); - props.spaceBefore = new SpaceVal(this.properties.get("space-before"). - getSpace()); - props.spaceAfter = new SpaceVal(this.properties.get("space-after"). - getSpace()); + props.bIsSpan = (this.properties.get("span").getEnum() == Span.ALL); + props.spaceBefore = new SpaceVal( + this.properties.get("space-before"). getSpace()); + props.spaceAfter = new SpaceVal( + this.properties.get("space-after"). getSpace()); return props; } public TextInfo getTextLayoutProps(FontInfo fontInfo) { - if (textInfo == null) { - textInfo = new TextInfo(); - textInfo.fs = getFontState(fontInfo); - textInfo.color = properties.get("color").getColorType(); + if (textInfo == null) { + textInfo = new TextInfo(); + textInfo.fs = getFontState(fontInfo); + textInfo.color = properties.get("color").getColorType(); - textInfo.verticalAlign = - properties.get("vertical-align").getEnum(); + textInfo.verticalAlign = + properties.get("vertical-align").getEnum(); - textInfo.wrapOption = properties.get("wrap-option").getEnum(); - textInfo.bWrap = (textInfo.wrapOption == Constants.WRAP); + textInfo.wrapOption = properties.get("wrap-option").getEnum(); + textInfo.bWrap = (textInfo.wrapOption == Constants.WRAP); - textInfo.wordSpacing = - new SpaceVal(properties.get("word-spacing").getSpace()); + textInfo.wordSpacing = new SpaceVal( + properties.get("word-spacing").getSpace()); - /* textInfo.letterSpacing = - new SpaceVal(properties.get("letter-spacing").getSpace());*/ + /* textInfo.letterSpacing = + new SpaceVal(properties.get("letter-spacing").getSpace());*/ - textInfo.whiteSpaceCollapse = - properties.get("white-space-collapse").getEnum(); + textInfo.whiteSpaceCollapse = + properties.get("white-space-collapse").getEnum(); - textInfo.lineHeight = this.properties. - get("line-height").getLength().mvalue(); - } - return textInfo; + textInfo.lineHeight = this.properties. get( + "line-height").getLength().mvalue(); + } + return textInfo; } - public CTM getCTMandRelDims(Rectangle2D absVPrect, FODimension reldims) { - int width, height; + public CTM getCTMandRelDims(Rectangle2D absVPrect, + FODimension reldims) { + int width, height; // We will use the absolute reference-orientation to set up the CTM. // The value here is relative to its ancestor reference area. - int absRefOrient = - getAbsRefOrient(this.properties.get("reference-orientation"). - getNumber().intValue()); + int absRefOrient = getAbsRefOrient( this.properties.get( + "reference-orientation"). getNumber().intValue()); if (absRefOrient % 180 == 0) { - width = (int)absVPrect.getWidth(); - height = (int)absVPrect.getHeight(); - } - else { + width = (int) absVPrect.getWidth(); + height = (int) absVPrect.getHeight(); + } else { // invert width and height since top left are rotated by 90 (cl or ccl) - height = (int)absVPrect.getWidth(); - width = (int)absVPrect.getHeight(); + height = (int) absVPrect.getWidth(); + width = (int) absVPrect.getHeight(); } - /* Set up the CTM for the content of this reference area. This will transform - * region content coordinates in writing-mode relative into absolute page-relative - * which will then be translated based on the position of the region viewport - * (Note: scrolling between region vp and ref area when doing online content!) + /* Set up the CTM for the content of this reference area. + * This will transform region content coordinates in + * writing-mode relative into absolute page-relative + * which will then be translated based on the position of + * the region viewport. + * (Note: scrolling between region vp and ref area when + * doing online content!) */ - CTM ctm = new CTM(absVPrect.getX(), absVPrect.getY()); + CTM ctm = new CTM(absVPrect.getX(), absVPrect.getY()); - // First transform for rotation - if (absRefOrient != 0) { + // First transform for rotation + if (absRefOrient != 0) { // Rotation implies translation to keep the drawing area in the // first quadrant. Note: rotation is counter-clockwise - switch (absRefOrient) { - case 90: - ctm = ctm.translate(0, width); // width = absVPrect.height - break; - case 180: - ctm = ctm.translate(width, height); - break; - case 270: - ctm = ctm.translate(height,0); // height = absVPrect.width - break; - } - ctm = ctm.rotate(absRefOrient); - } + switch (absRefOrient) { + case 90: + ctm = ctm.translate(0, width); // width = absVPrect.height + break; + case 180: + ctm = ctm.translate(width, height); + break; + case 270: + ctm = ctm.translate(height, 0); // height = absVPrect.width + break; + } + ctm = ctm.rotate(absRefOrient); + } int wm = this.properties.get("writing-mode").getEnum(); /* Since we've already put adjusted width and height values for the * top and left positions implied by the reference-orientation, we @@ -392,13 +410,12 @@ public class PropertyManager { if (wm == WritingMode.LR_TB || wm == WritingMode.RL_TB) { reldims.ipd = width; reldims.bpd = height; + } else { + reldims.ipd = height; + reldims.bpd = width; } - else { - reldims.ipd=height; - reldims.bpd=width; - } - // Set a rectangle to be the writing-mode relative version??? - // Now transform for writing mode + // Set a rectangle to be the writing-mode relative version??? + // Now transform for writing mode return ctm.multiply(CTM.getWMctm(wm, reldims.ipd, reldims.bpd)); } @@ -406,6 +423,6 @@ public class PropertyManager { * Calculate absolute reference-orientation relative to media orientation. */ private int getAbsRefOrient(int myRefOrient) { - return myRefOrient; + return myRefOrient; } } diff --git a/src/org/apache/fop/fo/flow/BlockContainer.java b/src/org/apache/fop/fo/flow/BlockContainer.java index 6bd81f1e0..ab64158b6 100644 --- a/src/org/apache/fop/fo/flow/BlockContainer.java +++ b/src/org/apache/fop/fo/flow/BlockContainer.java @@ -14,10 +14,12 @@ import org.apache.fop.fo.pagination.PageSequence; import org.apache.fop.layout.*; import org.apache.fop.apps.FOPException; import org.apache.fop.datatypes.*; - +import org.apache.fop.layoutmgr.BlockContainerLayoutManager; import org.xml.sax.Attributes; +import java.util.List; + public class BlockContainer extends FObj { ColorType backgroundColor; @@ -42,6 +44,12 @@ public class BlockContainer extends FObj { setupID(); } + public void addLayoutManager(List list) { + BlockContainerLayoutManager blm = new BlockContainerLayoutManager(this); + blm.setOverflow(properties.get("overflow").getEnum()); + list.add(blm); + } + public void setup() { // Common Accessibility Properties @@ -75,11 +83,6 @@ public class BlockContainer extends FObj { this.backgroundColor = this.properties.get("background-color").getColorType(); - this.position = this.properties.get("position").getEnum(); - this.top = this.properties.get("top").getLength().mvalue(); - this.bottom = this.properties.get("bottom").getLength().mvalue(); - this.left = this.properties.get("left").getLength().mvalue(); - this.right = this.properties.get("right").getLength().mvalue(); this.width = this.properties.get("width").getLength().mvalue(); this.height = this.properties.get("height").getLength().mvalue(); span = this.properties.get("span").getEnum(); @@ -99,3 +102,4 @@ public class BlockContainer extends FObj { } } + diff --git a/src/org/apache/fop/fo/flow/InstreamForeignObject.java b/src/org/apache/fop/fo/flow/InstreamForeignObject.java index b39e8c0db..db947752a 100644 --- a/src/org/apache/fop/fo/flow/InstreamForeignObject.java +++ b/src/org/apache/fop/fo/flow/InstreamForeignObject.java @@ -201,7 +201,7 @@ public class InstreamForeignObject extends FObj { if(overflow == Overflow.HIDDEN) { clip = true; } else if(overflow == Overflow.ERROR_IF_OVERFLOW) { - getLogger().error("Instream foreign object overflows the viewport"); + getLogger().error("Instream foreign object overflows the viewport: clipping"); clip = true; } } diff --git a/src/org/apache/fop/layout/AbsolutePositionProps.java b/src/org/apache/fop/layout/AbsolutePositionProps.java index e8e5d1a56..521c47ceb 100644 --- a/src/org/apache/fop/layout/AbsolutePositionProps.java +++ b/src/org/apache/fop/layout/AbsolutePositionProps.java @@ -15,10 +15,10 @@ import org.apache.fop.datatypes.Length; */ public class AbsolutePositionProps { public int absolutePosition; - public Length top; - public Length right; - public Length bottom; - public Length left; + public int top; + public int right; + public int bottom; + public int left; public AbsolutePositionProps() {} diff --git a/src/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java b/src/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java new file mode 100644 index 000000000..749a0d0e1 --- /dev/null +++ b/src/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java @@ -0,0 +1,293 @@ +/* + * $Id$ + * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources. + */ + +package org.apache.fop.layoutmgr; + +import org.apache.fop.fo.FObj; +import org.apache.fop.fo.TextInfo; +import org.apache.fop.area.Area; +import org.apache.fop.area.BlockParent; +import org.apache.fop.area.BlockViewport; +import org.apache.fop.area.Block; +import org.apache.fop.area.LineArea; +import org.apache.fop.area.MinOptMax; +import org.apache.fop.fo.PropertyManager; +import org.apache.fop.layout.AbsolutePositionProps; +import org.apache.fop.fo.properties.AbsolutePosition; +import org.apache.fop.fo.properties.Overflow; +import org.apache.fop.fo.PropertyList; +import org.apache.fop.area.CTM; +import org.apache.fop.datatypes.FODimension; + +import java.util.ListIterator; +import java.util.ArrayList; +import java.util.List; + +import java.awt.geom.Rectangle2D; + +/** + * LayoutManager for a block FO. + */ +public class BlockContainerLayoutManager extends BlockStackingLayoutManager { + + private BlockViewport viewportBlockArea; + private Block curBlockArea; + + ArrayList childBreaks = new ArrayList(); + + AbsolutePositionProps abProps; + FODimension relDims; + CTM absoluteCTM; + boolean clip = false; + int overflow; + PropertyManager propManager; + + public BlockContainerLayoutManager(FObj fobj) { + super(fobj); + } + + public void setOverflow(int of) { + overflow = of; + } + + protected void initProperties(PropertyManager pm) { + propManager = pm; + + abProps = pm.getAbsolutePositionProps(); + if(abProps.absolutePosition == AbsolutePosition.ABSOLUTE) { + Rectangle2D rect = new Rectangle2D.Double(abProps.left, + abProps.top, abProps.right - abProps.left, + abProps.bottom - abProps.top); + relDims = new FODimension(0, 0); + absoluteCTM = pm.getCTMandRelDims(rect, relDims); + } + } + + protected int getRotatedIPD() { + PropertyList props = propManager.getProperties(); + int height = props.get("height").getLength().mvalue(); + height = props.get("inline-progression-dimension.optimum").getLength().mvalue(); + + return height; + } + + public BreakPoss getNextBreakPoss(LayoutContext context) { + + if(abProps.absolutePosition == AbsolutePosition.ABSOLUTE) { + return getAbsoluteBreakPoss(context); + } + + Rectangle2D rect = new Rectangle2D.Double(0, 0, context.getRefIPD(), + context.getStackLimit().opt); + relDims = new FODimension(0, 0); + absoluteCTM = propManager.getCTMandRelDims(rect, relDims); + double[] vals = absoluteCTM.toArray(); + + MinOptMax stackLimit; + int ipd = context.getRefIPD(); + boolean rotated = vals[0] == 0.0; + if(rotated) { + // rotated 90 degrees + stackLimit = new MinOptMax(1000000); + ipd = getRotatedIPD(); + absoluteCTM = new CTM(vals[0], vals[1], vals[2], vals[3], 0, 0); + } else { + if(vals[0] == -1.0) { + absoluteCTM = new CTM(vals[0], vals[1], vals[2], vals[3], 0, 0); + } + stackLimit = context.getStackLimit(); + } + + BPLayoutManager curLM ; // currently active LM + + MinOptMax stackSize = new MinOptMax(); + // if starting add space before + // stackSize.add(spaceBefore); + BreakPoss lastPos = null; + + while ((curLM = getChildLM()) != null) { + // Make break positions and return blocks! + // Set up a LayoutContext + BreakPoss bp; + + LayoutContext childLC = new LayoutContext(0); + childLC.setStackLimit( + MinOptMax.subtract(stackLimit, + stackSize)); + childLC.setRefIPD(ipd); + + while (!curLM.isFinished()) { + if ((bp = curLM.getNextBreakPoss(childLC)) != null) { + stackSize.add(bp.getStackingSize()); + if (stackSize.min > stackLimit.max) { + // reset to last break + if (lastPos != null) { + reset(lastPos.getPosition()); + } else { + curLM.resetPosition(null); + } + break; + } + lastPos = bp; + childBreaks.add(bp); + + childLC.setStackLimit(MinOptMax.subtract( + stackLimit, stackSize)); + } + } + if(!rotated) { + BreakPoss breakPoss; + breakPoss = new BreakPoss(new LeafPosition(this, + childBreaks.size() - 1)); + breakPoss.setStackingSize(stackSize); + return breakPoss; + } + } + setFinished(true); + if(rotated) { + BreakPoss breakPoss; + breakPoss = new BreakPoss(new LeafPosition(this, + childBreaks.size() - 1)); + breakPoss.setStackingSize(new MinOptMax(ipd)); + return breakPoss; + } + return null; + } + + public BreakPoss getAbsoluteBreakPoss(LayoutContext context) { + + BPLayoutManager curLM ; // currently active LM + + MinOptMax stackSize = new MinOptMax(); + + int ipd = relDims.ipd; + + while ((curLM = getChildLM()) != null) { + // Make break positions and return blocks! + // Set up a LayoutContext + BreakPoss bp; + + LayoutContext childLC = new LayoutContext(0); + childLC.setStackLimit(new MinOptMax(1000000)); + childLC.setRefIPD(ipd); + + while (!curLM.isFinished()) { + if ((bp = curLM.getNextBreakPoss(childLC)) != null) { + stackSize.add(bp.getStackingSize()); + childBreaks.add(bp); + } + } + } + setFinished(true); + BreakPoss breakPoss = new BreakPoss( + new LeafPosition(this, childBreaks.size() - 1)); + // absolutely positioned areas do not contribute + // to the normal stacking + breakPoss.setStackingSize(new MinOptMax(0)); + + if(stackSize.min > relDims.bpd) { + if(overflow == Overflow.HIDDEN) { + clip = true; + } else if(overflow == Overflow.ERROR_IF_OVERFLOW) { + //log.error("contents overflows block-container viewport: clipping"); + clip = true; + } + } + + return breakPoss; + } + + public void addAreas(PositionIterator parentIter, + LayoutContext layoutContext) { + getParentArea(null); + + BPLayoutManager childLM ; + int iStartPos = 0; + LayoutContext lc = new LayoutContext(0); + while (parentIter.hasNext()) { + LeafPosition lfp = (LeafPosition) parentIter.next(); + // Add the block areas to Area + PositionIterator breakPosIter = + new BreakPossPosIter(childBreaks, iStartPos, + lfp.getLeafPos() + 1); + iStartPos = lfp.getLeafPos() + 1; + while ((childLM = breakPosIter.getNextChildLM()) != null) { + childLM.addAreas(breakPosIter, lc); + } + } + + flush(); + + childBreaks.clear(); + viewportBlockArea = null; + curBlockArea = null; + } + + public Area getParentArea(Area childArea) { + if (curBlockArea == null) { + viewportBlockArea = new BlockViewport(); + if(abProps.absolutePosition == AbsolutePosition.ABSOLUTE) { + Rectangle2D rect = new Rectangle2D.Double(abProps.left, + abProps.top, abProps.right - abProps.left, + abProps.bottom - abProps.top); + viewportBlockArea.setBounds(rect); + viewportBlockArea.setCTM(absoluteCTM); + viewportBlockArea.setClip(clip); + } else { + double[] vals = absoluteCTM.toArray(); + boolean rotated = vals[0] == 0.0; + if(rotated) { + Rectangle2D rect = new Rectangle2D.Double(0, 0, + relDims.bpd, getRotatedIPD()); + viewportBlockArea.setBounds(rect); + viewportBlockArea.setCTM(absoluteCTM); + viewportBlockArea.setClip(clip); + } else if(vals[0] == -1.0) { + // need to set bpd to actual size for rotation + // and stacking + Rectangle2D rect = new Rectangle2D.Double(0, 0, + relDims.ipd, relDims.bpd); + viewportBlockArea.setBounds(rect); + viewportBlockArea.setCTM(absoluteCTM); + viewportBlockArea.setClip(clip); + } + } + + curBlockArea = new Block(); + viewportBlockArea.addBlock(curBlockArea); + + if(abProps.absolutePosition == AbsolutePosition.ABSOLUTE) { + viewportBlockArea.setPositioning(Block.ABSOLUTE); + } + + // Set up dimensions + // Must get dimensions from parent area + Area parentArea = parentLM.getParentArea(curBlockArea); + int referenceIPD = parentArea.getIPD(); + curBlockArea.setIPD(referenceIPD); + // Get reference IPD from parentArea + setCurrentArea(viewportBlockArea); // ??? for generic operations + } + return curBlockArea; + } + + + public boolean addChild(Area childArea) { + if (curBlockArea != null) { + curBlockArea.addBlock((Block) childArea); + //return super.addChild(childArea); + } + return false; + } + + public void resetPosition(Position resetPos) { + if (resetPos == null) { + reset(null); + } + } +} + diff --git a/src/org/apache/fop/render/AbstractRenderer.java b/src/org/apache/fop/render/AbstractRenderer.java index a21eb1374..72ea1c6c4 100644 --- a/src/org/apache/fop/render/AbstractRenderer.java +++ b/src/org/apache/fop/render/AbstractRenderer.java @@ -95,7 +95,8 @@ public abstract class AbstractRenderer extends AbstractLogEnabled implements Ren } else if (inline instanceof Word) { str += ((Word) inline).getWord(); } else if (inline instanceof InlineParent) { - str += convertToString(((InlineParent)inline).getChildAreas()); + str += convertToString( + ((InlineParent) inline).getChildAreas()); } else { str += " "; } @@ -135,21 +136,21 @@ public abstract class AbstractRenderer extends AbstractLogEnabled implements Ren protected void renderRegionViewport(RegionViewport port) { if (port != null) { Rectangle2D view = port.getViewArea(); - // The CTM will transform coordinates relative to - // this region-reference area into page coords, so - // set origin for the region to 0,0. + // The CTM will transform coordinates relative to + // this region-reference area into page coords, so + // set origin for the region to 0,0. currentBPPosition = 0; // (int) (view.getY() / 1000); currentIPPosition = 0; // (int) (view.getX() / 1000); currentBlockIPPosition = currentIPPosition; RegionReference region = port.getRegion(); - startVParea(region.getCTM()); + startVParea(region.getCTM()); if (region.getRegionClass() == RegionReference.BODY) { renderBodyRegion((BodyRegion) region); } else { renderRegion(region); } - endVParea(); + endVParea(); } } @@ -237,6 +238,32 @@ public abstract class AbstractRenderer extends AbstractLogEnabled implements Ren List children = block.getChildAreas(); if (children == null) { // simply move position + } else if (block instanceof BlockViewport) { + renderBlockViewport((BlockViewport) block, children); + } else { + renderBlocks(children); + } + } + + protected void renderBlockViewport(BlockViewport bv, List children) { + // clip and position viewport if necessary + if (bv.getPositioning() == Block.ABSOLUTE) { + // save positions + int saveIP = currentIPPosition; + int saveBP = currentBPPosition; + + CTM ctm = bv.getCTM(); + currentIPPosition = 0; + currentBPPosition = 0; + + startVParea(ctm); + renderBlocks(children); + endVParea(); + + // clip if necessary + + currentIPPosition = saveIP; + currentBPPosition = saveBP; } else { renderBlocks(children); } @@ -314,7 +341,7 @@ public abstract class AbstractRenderer extends AbstractLogEnabled implements Ren int saveIP = currentBlockIPPosition; Iterator iter = ip.getChildAreas().iterator(); while (iter.hasNext()) { - ((InlineArea)iter.next()).render(this); + ((InlineArea) iter.next()).render(this); } currentBlockIPPosition = saveIP + ip.getWidth(); } @@ -322,14 +349,14 @@ public abstract class AbstractRenderer extends AbstractLogEnabled implements Ren protected void renderBlocks(List blocks) { for (int count = 0; count < blocks.size(); count++) { Object obj = blocks.get(count); - if(obj instanceof Block) { - renderBlock((Block)obj); + if (obj instanceof Block) { + renderBlock((Block) obj); } else { // a line area is rendered from the top left position // of the line, each inline object is offset from there LineArea line = (LineArea) obj; - currentBlockIPPosition = currentIPPosition - + line.getStartIndent(); + currentBlockIPPosition = + currentIPPosition + line.getStartIndent(); renderLineArea(line); currentBPPosition += line.getHeight(); } diff --git a/src/org/apache/fop/render/pdf/PDFRenderer.java b/src/org/apache/fop/render/pdf/PDFRenderer.java index 84ac9cb96..c28056958 100644 --- a/src/org/apache/fop/render/pdf/PDFRenderer.java +++ b/src/org/apache/fop/render/pdf/PDFRenderer.java @@ -276,6 +276,113 @@ public class PDFRenderer extends PrintRenderer { super.renderRegion(region); } + protected void renderBlockViewport(BlockViewport bv, List children) { + // clip and position viewport if necessary + + // save positions + int saveIP = currentIPPosition; + int saveBP = currentBPPosition; + + CTM ctm = bv.getCTM(); + + closeText(); + + if (bv.getPositioning() == Block.ABSOLUTE) { + + currentIPPosition = 0; + currentBPPosition = 0; + + currentStream.add("ET\n"); + + if(bv.getClip()) { + Rectangle2D rect = bv.getBounds(); + + currentStream.add("q\n"); + float x = (float)rect.getX() / 1000f; + float y = (float)rect.getY() / 1000f; + float width = (float)rect.getWidth() / 1000f; + float height = (float)rect.getHeight() / 1000f; + clip(x, y, width, height); + } + + startVParea(ctm); + renderBlocks(children); + endVParea(); + + if (bv.getClip()) { + currentStream.add("Q\n"); + } + currentStream.add("BT\n"); + + // clip if necessary + + currentIPPosition = saveIP; + currentBPPosition = saveBP; + } else { + + Rectangle2D rect = bv.getBounds(); + + if(ctm != null) { + currentIPPosition = 0; + currentBPPosition = 0; + + currentStream.add("ET\n"); + + double[] vals = ctm.toArray(); + boolean aclock = vals[2] == 1.0; + if(vals[2] == 1.0) { + ctm = ctm.translate(-saveBP - rect.getHeight(), -saveIP); + } else if(vals[0] == -1.0) { + ctm = ctm.translate(-saveIP - rect.getWidth(), -saveBP - rect.getHeight()); + } else { + ctm = ctm.translate(saveBP, saveIP - rect.getWidth()); + } + } + + if(bv.getClip()) { + currentStream.add("q\n"); + float x = (float)rect.getX() / 1000f; + float y = (float)rect.getY() / 1000f; + float width = (float)rect.getWidth() / 1000f; + float height = (float)rect.getHeight() / 1000f; + clip(x, y, width, height); + } + + if(ctm != null) { + startVParea(ctm); + } + renderBlocks(children); + if(ctm != null) { + endVParea(); + } + + if (bv.getClip()) { + currentStream.add("Q\n"); + } + if(ctm != null) { + currentStream.add("BT\n"); + } + + // clip if necessary + + if(rect != null) { + currentIPPosition = saveIP; + currentBPPosition = saveBP; + currentBPPosition += (int)(rect.getHeight()); + } + } + } + + protected void clip(float x, float y, float width, float height) { + currentStream.add(x + " " + y + " m\n"); + currentStream.add((x + width) + " " + y + " l\n"); + currentStream.add((x + width) + " " + (y + height) + " l\n"); + currentStream.add(x + " " + (y + height) + " l\n"); + currentStream.add("h\n"); + currentStream.add("W\n"); + currentStream.add("n\n"); + } + protected void renderLineArea(LineArea line) { super.renderLineArea(line); closeText(); @@ -609,13 +716,7 @@ public class PDFRenderer extends PrintRenderer { float y = (currentBPPosition + viewport.getOffset()) / 1000f; float width = viewport.getWidth() / 1000f; float height = viewport.getHeight() / 1000f; - currentStream.add(x + " " + y + " m\n"); - currentStream.add((x + width) + " " + y + " l\n"); - currentStream.add((x + width) + " " + (y + height) + " l\n"); - currentStream.add(x + " " + (y + height) + " l\n"); - currentStream.add("h\n"); - currentStream.add("W\n"); - currentStream.add("n\n"); + clip(x, y, width, height); } super.renderViewport(viewport); -- 2.39.5