Browse Source

Bugzilla #36391:

Fixed problem with positioning of content when reference-orientation="180" is used. CTM is now correct. It is updated after the height of the content is known. Instead of somehow inverting the element list, I've simply declared this case non-breakable, i.e. I generate one box.

Fixed a few other problems mostly occurring when rotating block-container content by 90 or 270 degrees plus a few remaining auto-height handling problems. This involved switching off some sometimes unwanted side-effects from auto-updating the BPD in some area classes.

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@618992 13f79535-47bb-0310-9956-ffa450edef68
tags/fop-0_95beta
Jeremias Maerki 16 years ago
parent
commit
448befc115

+ 12
- 3
src/java/org/apache/fop/area/Block.java View File

@@ -19,7 +19,6 @@
package org.apache.fop.area;

import java.util.ArrayList;

// block areas hold either more block areas or line
// areas can also be used as a block spacer
@@ -59,6 +58,8 @@ public class Block extends BlockParent {
private int stacking = TB;
private int positioning = STACK;

protected transient boolean allowBPDUpdate = true;
// a block with may contain the dominant styling info in
// terms of most lines or blocks with info

@@ -78,7 +79,7 @@ public class Block extends BlockParent {
* @param autoHeight increase the height of the block.
*/
public void addBlock(Block block, boolean autoHeight) {
if (autoHeight) {
if (autoHeight && allowBPDUpdate) {
bpd += block.getAllocBPD();
}
addChildArea(block);
@@ -112,6 +113,14 @@ public class Block extends BlockParent {
return positioning;
}

/**
* Indicates whether this block is stacked, rather than absolutely positioned.
* @return true if it is stacked
*/
public boolean isStacked() {
return (getPositioning() == Block.STACK || getPositioning() == Block.RELATIVE);
}
/**
* @return the start-indent trait
*/
@@ -119,6 +128,6 @@ public class Block extends BlockParent {
Integer startIndent = (Integer)getTrait(Trait.START_INDENT);
return (startIndent != null ? startIndent.intValue() : 0);
}
}


+ 9
- 0
src/java/org/apache/fop/area/BlockViewport.java View File

@@ -34,6 +34,15 @@ public class BlockViewport extends Block {
* Create a new block viewport area.
*/
public BlockViewport() {
this(false);
}

/**
* Create a new block viewport area.
* @param allowBPDUpdate true allows the BPD to be updated when children are added
*/
public BlockViewport(boolean allowBPDUpdate) {
this.allowBPDUpdate = allowBPDUpdate;
}

/**

+ 3
- 1
src/java/org/apache/fop/area/NormalFlow.java View File

@@ -37,7 +37,9 @@ public class NormalFlow extends BlockParent {
/** {@inheritDoc} */
public void addBlock(Block block) {
super.addBlock(block);
bpd += block.getAllocBPD();
if (block.isStacked()) {
bpd += block.getAllocBPD();
}
}
}


+ 63
- 36
src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java View File

@@ -65,7 +65,8 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager
private int vpContentBPD;
// When viewport should grow with the content.
private boolean autoHeight = true;
private boolean autoHeight = true;
private boolean inlineElementList = false;
/* holds the (one-time use) fo:block space-before
and -after properties. Large fo:blocks are split
@@ -196,6 +197,8 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager
return getNextKnuthElementsAbsolute(context, alignment);
}
boolean switchedProgressionDirection
= (getBlockContainerFO().getReferenceOrientation() % 180 != 0);
autoHeight = false;
//boolean rotated = (getBlockContainerFO().getReferenceOrientation() % 180 != 0);
int maxbpd = context.getStackLimit().opt;
@@ -203,9 +206,13 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager
if (height.getEnum() == EN_AUTO
|| (!height.isAbsolute() && getAncestorBlockAreaBPD() <= 0)) {
//auto height when height="auto" or "if that dimension is not specified explicitly
//(i.e., it depends on content's blockprogression-dimension)" (XSL 1.0, 7.14.1)
//(i.e., it depends on content's block-progression-dimension)" (XSL 1.0, 7.14.1)
allocBPD = maxbpd;
autoHeight = true;
if (getBlockContainerFO().getReferenceOrientation() == 0) {
//Cannot easily inline element list when ref-or="180"
inlineElementList = true;
}
} else {
allocBPD = height.getValue(this); //this is the content-height
allocBPD += getBPIndents();
@@ -229,19 +236,14 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager
contentRectOffsetY += getBlockContainerFO()
.getCommonBorderPaddingBackground().getPaddingBefore(false, this);
Rectangle2D rect = new Rectangle2D.Double(
contentRectOffsetX, contentRectOffsetY,
getContentAreaIPD(), getContentAreaBPD());
relDims = new FODimension(0, 0);
absoluteCTM = CTM.getCTMandRelDims(getBlockContainerFO().getReferenceOrientation(),
getBlockContainerFO().getWritingMode(), rect, relDims);
updateRelDims(contentRectOffsetX, contentRectOffsetY, autoHeight);

int availableIPD = referenceIPD - getIPIndents();
if (rect.getWidth() > availableIPD) {
if (getContentAreaIPD() > availableIPD) {
log.warn(FONode.decorateWithContextInfo(
"The extent in inline-progression-direction (width) of a block-container is"
+ " bigger than the available space ("
+ rect.getWidth() + "mpt > " + context.getRefIPD() + "mpt)",
+ getContentAreaIPD() + "mpt > " + context.getRefIPD() + "mpt)",
getBlockContainerFO()));
}
@@ -268,7 +270,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager
addKnuthElementsForBorderPaddingBefore(returnList, !firstVisibleMarkServed);
firstVisibleMarkServed = true;

if (autoHeight) {
if (autoHeight && inlineElementList) {
//Spaces, border and padding to be repeated at each break
addPendingMarks(context);

@@ -356,6 +358,16 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager
BlockContainerBreaker breaker = new BlockContainerBreaker(this, range);
breaker.doLayout(relDims.bpd, autoHeight);
boolean contentOverflows = breaker.isOverflow();
if (autoHeight) {
//Update content BPD now that it is known
int newHeight = breaker.deferredAlg.totalWidth;
if (switchedProgressionDirection) {
setContentAreaIPD(newHeight);
} else {
vpContentBPD = newHeight;
}
updateRelDims(contentRectOffsetX, contentRectOffsetY, false);
}

Position bcPosition = new BlockContainerPosition(this, breaker);
returnList.add(new KnuthBox(vpContentBPD, notifyPos(bcPosition), false));
@@ -385,6 +397,8 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager
private LinkedList getNextKnuthElementsAbsolute(LayoutContext context, int alignment) {
autoHeight = false;

boolean switchedProgressionDirection
= (getBlockContainerFO().getReferenceOrientation() % 180 != 0);
Point offset = getAbsOffset();
int allocBPD, allocIPD;
if (height.getEnum() == EN_AUTO
@@ -432,7 +446,9 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager
} else {
int maxbpd = context.getStackLimit().opt;
allocBPD = maxbpd;
autoHeight = true;
if (!switchedProgressionDirection) {
autoHeight = true;
}
}
} else {
allocBPD = height.getValue(this); //this is the content-height
@@ -474,6 +490,9 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager
*/
allocIPD = 0;
}
if (switchedProgressionDirection) {
autoHeight = true;
}
}
} else {
allocIPD = width.getValue(this); //this is the content-width
@@ -483,29 +502,29 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager
vpContentBPD = allocBPD - getBPIndents();
setContentAreaIPD(allocIPD - getIPIndents());
double contentRectOffsetX = 0;
double contentRectOffsetY = 0;
Rectangle2D rect = new Rectangle2D.Double(
contentRectOffsetX, contentRectOffsetY,
getContentAreaIPD(), vpContentBPD);
relDims = new FODimension(0, 0);
absoluteCTM = CTM.getCTMandRelDims(
getBlockContainerFO().getReferenceOrientation(),
getBlockContainerFO().getWritingMode(),
rect, relDims);
updateRelDims(0, 0, autoHeight);

MinOptMax range = new MinOptMax(relDims.ipd);
BlockContainerBreaker breaker = new BlockContainerBreaker(this, range);
breaker.doLayout((autoHeight ? 0 : relDims.bpd), autoHeight);
boolean contentOverflows = breaker.isOverflow();
if (autoHeight) {
//Update content BPD now that it is known
int newHeight = breaker.deferredAlg.totalWidth;
if (switchedProgressionDirection) {
setContentAreaIPD(newHeight);
} else {
vpContentBPD = newHeight;
}
updateRelDims(0, 0, false);
}
LinkedList returnList = new LinkedList();
if (!breaker.isEmpty()) {
Position bcPosition = new BlockContainerPosition(this, breaker);
returnList.add(new KnuthBox(0, notifyPos(bcPosition), false));
//TODO Maybe check for page overflow when autoHeight=true
if (!autoHeight & (contentOverflows/*usedBPD > relDims.bpd*/)) {
if (!autoHeight & (contentOverflows)) {
log.warn("Contents overflow block-container viewport: clipping");
if (getBlockContainerFO().getOverflow() == EN_ERROR_IF_OVERFLOW) {
//TODO Throw layout exception
@@ -516,6 +535,18 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager
setFinished(true);
return returnList;
}

private void updateRelDims(double xOffset, double yOffset, boolean skipAutoHeight) {
Rectangle2D rect = new Rectangle2D.Double(
xOffset, yOffset,
getContentAreaIPD(),
this.vpContentBPD);
relDims = new FODimension(0, 0);
absoluteCTM = CTM.getCTMandRelDims(
getBlockContainerFO().getReferenceOrientation(),
getBlockContainerFO().getWritingMode(),
rect, relDims);
}
private class BlockContainerPosition extends NonLeafPosition {

@@ -854,13 +885,18 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager
*/
public Area getParentArea(Area childArea) {
if (referenceArea == null) {
viewportBlockArea = new BlockViewport();
boolean switchedProgressionDirection
= (getBlockContainerFO().getReferenceOrientation() % 180 != 0);
boolean allowBPDUpdate = autoHeight && !switchedProgressionDirection;

viewportBlockArea = new BlockViewport(allowBPDUpdate);
viewportBlockArea.addTrait(Trait.IS_VIEWPORT_AREA, Boolean.TRUE);
viewportBlockArea.setIPD(getContentAreaIPD());
if (autoHeight) {
if (allowBPDUpdate) {
viewportBlockArea.setBPD(0);
} else {
viewportBlockArea.setBPD(getContentAreaBPD());
viewportBlockArea.setBPD(this.vpContentBPD);
}
transferForeignAttributes(viewportBlockArea);
@@ -941,16 +977,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager
getBlockContainerFO().getCommonBorderPaddingBackground(),
this);
// Fake a 0 height for absolute positioned blocks.
int saveBPD = viewportBlockArea.getBPD();
if (viewportBlockArea.getPositioning() == Block.ABSOLUTE) {
viewportBlockArea.setBPD(0);
}
super.flush();
// Restore the right height.
if (viewportBlockArea.getPositioning() == Block.ABSOLUTE) {
viewportBlockArea.setBPD(saveBPD);
}
}

/** {@inheritDoc} */

+ 0
- 7
test/layoutengine/disabled-testcases.xml View File

@@ -26,13 +26,6 @@
is not sized correctly if it wraps an image that is higher than the
nominal line.</description>
</testcase>
<testcase>
<name>Bugzilla #36391: reference-orientation</name>
<file>block-container_reference-orientation_bug36391.xml</file>
<description>There's a problem involving nested block-containers
and reference-orientation 180/-180.</description>
<reference>http://issues.apache.org/bugzilla/show_bug.cgi?id=36391</reference>
</testcase>
<testcase>
<name>Auto-height block-containers produce fences</name>
<file>block-container_space-before_space-after_3.xml</file>

+ 2
- 0
test/layoutengine/standard-testcases/block-container_absolute-position_display-align.xml View File

@@ -56,6 +56,8 @@
</fo:root>
</fo>
<checks>
<eval expected="0" xpath="//flow/@bpd"/> <!-- all blocks are absolutely positioned -->
<!-- first block-container -->
<true xpath="/areaTree/pageSequence/pageViewport/page[1]/regionViewport/regionBody/mainReference/span/flow/block[1]/@is-viewport-area"/>
<eval expected="[1.0 0.0 0.0 1.0 0.0 0.0]" xpath="/areaTree/pageSequence/pageViewport/page[1]/regionViewport/regionBody/mainReference/span/flow/block[1]/@ctm"/>

+ 84
- 0
test/layoutengine/standard-testcases/block-container_absolute-position_no-height_2.xml View File

@@ -0,0 +1,84 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- $Id$ -->
<testcase>
<info>
<p>
This test checks absolutely positioned block-containers where the content-bpd isn't specified.
</p>
</info>
<fo>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="normal" page-width="5in" page-height="5in">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="normal">
<fo:flow flow-name="xsl-region-body">
<fo:block-container id="bc0" width="80pt" absolute-position="absolute" left="10pt" top="10pt" overflow="visible"
reference-orientation="0" background-color="lightgray">
<fo:block>ABC</fo:block>
<fo:block font-size="200%">ABC</fo:block>
</fo:block-container>
<fo:block-container id="bc90" width="80pt" absolute-position="absolute" left="10pt" top="120pt" overflow="visible"
reference-orientation="90" background-color="lightgray">
<fo:block>ABC</fo:block>
<fo:block font-size="200%">ABC</fo:block>
</fo:block-container>
<fo:block-container id="bc180" width="80pt" absolute-position="absolute" left="120pt" top="10pt" overflow="visible"
reference-orientation="180" background-color="lightgray">
<fo:block>ABC</fo:block>
<fo:block font-size="200%">ABC</fo:block>
</fo:block-container>
<fo:block-container id="bc270" width="80pt" absolute-position="absolute" left="120pt" top="240pt" overflow="visible"
reference-orientation="270" background-color="lightgray">
<fo:block>ABC</fo:block>
<fo:block font-size="200%">ABC</fo:block>
</fo:block-container>
</fo:flow>
</fo:page-sequence>
</fo:root>
</fo>
<checks>
<!-- 0 -->
<eval expected="80000" xpath="//block[@prod-id='bc0' and boolean(@is-viewport-area)]/@ipd"/>
<eval expected="43200" xpath="//block[@prod-id='bc0' and boolean(@is-viewport-area)]/@bpd"/>
<eval expected="80000" xpath="//block[@prod-id='bc0' and boolean(@is-reference-area)]/@ipd"/>
<eval expected="43200" xpath="//block[@prod-id='bc0' and boolean(@is-reference-area)]/@bpd"/>
<eval expected="[1.0 0.0 0.0 1.0 0.0 0.0]" xpath="//block[@prod-id='bc0' and boolean(@is-viewport-area)]/@ctm"/>
<!-- 90 -->
<eval expected="43200" xpath="//block[@prod-id='bc90' and boolean(@is-viewport-area)]/@ipd"/>
<eval expected="80000" xpath="//block[@prod-id='bc90' and boolean(@is-viewport-area)]/@bpd"/>
<eval expected="80000" xpath="//block[@prod-id='bc90' and boolean(@is-reference-area)]/@ipd"/>
<eval expected="43200" xpath="//block[@prod-id='bc90' and boolean(@is-reference-area)]/@bpd"/>
<eval expected="[0.0 -1.0 1.0 0.0 0.0 80000.0]" xpath="//block[@prod-id='bc90' and boolean(@is-viewport-area)]/@ctm"/>
<!-- 180 -->
<eval expected="80000" xpath="//block[@prod-id='bc180' and boolean(@is-viewport-area)]/@ipd"/>
<eval expected="43200" xpath="//block[@prod-id='bc180' and boolean(@is-viewport-area)]/@bpd"/>
<eval expected="80000" xpath="//block[@prod-id='bc180' and boolean(@is-reference-area)]/@ipd"/>
<eval expected="43200" xpath="//block[@prod-id='bc180' and boolean(@is-reference-area)]/@bpd"/>
<eval expected="[-1.0 -0.0 0.0 -1.0 80000.0 43200.0]" xpath="//block[@prod-id='bc180' and boolean(@is-viewport-area)]/@ctm"/>
<!-- 270 -->
<eval expected="43200" xpath="//block[@prod-id='bc270' and boolean(@is-viewport-area)]/@ipd"/>
<eval expected="80000" xpath="//block[@prod-id='bc270' and boolean(@is-viewport-area)]/@bpd"/>
<eval expected="80000" xpath="//block[@prod-id='bc270' and boolean(@is-reference-area)]/@ipd"/>
<eval expected="43200" xpath="//block[@prod-id='bc270' and boolean(@is-reference-area)]/@bpd"/>
<eval expected="[0.0 1.0 -1.0 0.0 43200.0 0.0]" xpath="//block[@prod-id='bc270' and boolean(@is-viewport-area)]/@ctm"/>
</checks>
</testcase>

+ 91
- 0
test/layoutengine/standard-testcases/block-container_reference-orientation_2.xml View File

@@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- $Id$ -->
<testcase>
<info>
<p>
This test checks the element lists of in-flow block-containers with reference orientation.
</p>
</info>
<fo>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="normal" page-width="5in" page-height="5in">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence id="bc0" master-reference="normal">
<fo:flow flow-name="xsl-region-body">
<fo:block-container width="60pt" reference-orientation="0">
<fo:block>ABC</fo:block>
<fo:block font-size="200%">ABC</fo:block>
</fo:block-container>
<fo:block>EOPS</fo:block>
</fo:flow>
</fo:page-sequence>
<fo:page-sequence id="bc90" master-reference="normal">
<fo:flow flow-name="xsl-region-body">
<fo:block-container width="60pt" reference-orientation="90">
<fo:block>ABC</fo:block>
<fo:block font-size="200%">ABC</fo:block>
</fo:block-container>
<fo:block>EOPS</fo:block>
</fo:flow>
</fo:page-sequence>
<fo:page-sequence id="bc180" master-reference="normal">
<fo:flow flow-name="xsl-region-body">
<fo:block-container width="60pt" reference-orientation="180" background-color="yellow">
<fo:block>ABC</fo:block>
<fo:block font-size="200%">ABC</fo:block>
</fo:block-container>
<fo:block>EOPS</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
</fo>
<checks>
<element-list category="breaker" id="bc0">
<!-- content is inlined -->
<box w="14400"/>
<penalty w="0" p="0"/>
<box w="28800"/>
<penalty w="0" p="0"/>
<box w="14400"/>
<skip>3</skip>
</element-list>
<element-list category="breaker" id="bc90">
<!-- one box with the length of the rotated content-width -->
<box w="60000"/>
<penalty w="0" p="0"/>
<box w="14400"/>
<skip>3</skip>
</element-list>
<element-list category="breaker" id="bc180">
<!-- one box with the length of the effective content-height (auto-heigth) -->
<!-- Maybe the element list could be reversed somehow so the b-c can still be broken
correctly, even if ref-or="180". But we leave that be for the time being. -->
<box w="43200"/>
<penalty w="0" p="0"/>
<box w="14400"/>
<skip>3</skip>
</element-list>
</checks>
</testcase>

+ 2
- 5
test/layoutengine/standard-testcases/block-container_reference-orientation_bug36391.xml View File

@@ -90,13 +90,10 @@
<eval expected="[0.0 -1.0 1.0 0.0 0.0 31000.0]" xpath="//mainReference/span/flow[1]/block[6]/block[1]/block[1]/@ctm"/>
<!-- 180 -->
<eval expected="[1.0 0.0 0.0 1.0 0.0 1000.0]" xpath="//mainReference/span/flow[2]/block[2]/@ctm"/>
<!-- The following currently fails since the BCLM doesn't check the effective content BPD.
Another problem could probably arise if a BC with this ref-orientation is broken at the page end.
I'm pretty sure the element list is wrong in this case. It would need to be reversed I think. -->
<eval expected="[-1.0 -0.0 0.0 -1.0 30000.0 14400.0]" xpath="//mainReference/span/flow[2]/block[2]/block[1]/block[1]/@ctm"/>
<eval expected="[-1.0 -0.0 0.0 -1.0 30000.0 15400.0]" xpath="//mainReference/span/flow[2]/block[2]/block[1]/block[1]/@ctm"/>
<!-- -180 -->
<eval expected="[1.0 0.0 0.0 1.0 0.0 1000.0]" xpath="//mainReference/span/flow[2]/block[4]/@ctm"/>
<eval expected="[-1.0 -0.0 0.0 -1.0 30000.0 14400.0]" xpath="//mainReference/span/flow[2]/block[4]/block[1]/block[1]/@ctm"/>
<eval expected="[-1.0 -0.0 0.0 -1.0 30000.0 15400.0]" xpath="//mainReference/span/flow[2]/block[4]/block[1]/block[1]/@ctm"/>
<!-- 270 -->
<eval expected="[1.0 0.0 0.0 1.0 0.0 1000.0]" xpath="//mainReference/span/flow[2]/block[6]/@ctm"/>
<eval expected="[0.0 1.0 -1.0 0.0 90000.0 1000.0]" xpath="//mainReference/span/flow[2]/block[6]/block[1]/block[1]/@ctm"/>

Loading…
Cancel
Save