https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk ........ r660979 | vhennebert | 2008-05-28 16:24:23 +0100 (Wed, 28 May 2008) | 3 lines Bugzilla 37579: added support for footnotes in lists and table bodies (not header nor footer). This is /not/ to be considered a final fix: similar code is duplicated over several classes (LineLayoutManager, ListItemLayoutManager and to less extent TableStepper). Footnotes should probably be handled another way. ........ r660998 | maxberger | 2008-05-28 17:10:32 +0100 (Wed, 28 May 2008) | 1 line Implemented Font auto-selection word-by-word ........ r661276 | vhennebert | 2008-05-29 10:58:06 +0100 (Thu, 29 May 2008) | 2 lines Set svn:keywords and svn:eol-style properties for files added in revision 660998 ........ r661310 | maxberger | 2008-05-29 13:03:48 +0100 (Thu, 29 May 2008) | 1 line Added docs for my recent commit (word-by-word character selection) ........ r661999 | adelmelle | 2008-05-31 11:56:05 +0100 (Sat, 31 May 2008) | 3 lines Bugzilla 45097: Leading/trailing white-space not removed from nested inline-content when there is no preceding/following text. ........ r662009 | maxberger | 2008-05-31 12:45:55 +0100 (Sat, 31 May 2008) | 1 line Code Cleanups (no functional change) ........ r662203 | maxberger | 2008-06-01 12:57:33 +0100 (Sun, 01 Jun 2008) | 1 line More code Cleanups (no functional changes) ........ git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@662442 13f79535-47bb-0310-9956-ffa450edef68tags/fop-1_0
@@ -22,7 +22,7 @@ | |||
<title>Apache FOP: Fonts</title> | |||
<version>$Revision$</version> | |||
<authors> | |||
<person name="Jeremias Märki" email=""/> | |||
<person name="Jeremias Märki" email=""/> | |||
<person name="Tore Engvig" email=""/> | |||
<person name="Adrian Cumiskey" email=""/> | |||
<person name="Max Berger" email=""/> | |||
@@ -96,14 +96,14 @@ | |||
<td>yes (used for layout but not for output)</td> | |||
<td>no</td> | |||
</tr> | |||
<!--tr> NOT AVAILABLE | |||
<!--tr> NOT AVAILABLE | |||
<td>MIF</td> | |||
<td>n/a (font metrics not needed)</td> | |||
<td>n/a</td> | |||
<td>n/a</td> | |||
<td>n/a</td> | |||
</tr--> | |||
<!--tr> NOT AVAILABLE | |||
<!--tr> NOT AVAILABLE | |||
<td>SVG</td> | |||
<td>if available from OS</td> | |||
<td>yes</td> | |||
@@ -163,7 +163,6 @@ | |||
PDF or PostScript. | |||
</p> | |||
</section> | |||
<section id="custom"> | |||
<title>Custom Fonts</title> | |||
<p> | |||
@@ -184,11 +183,14 @@ | |||
Basic information about fonts can be found at: | |||
</p> | |||
<ul> | |||
<li><a href="http://partners.adobe.com/asn/developer/type/ftypes.html">Adobe font types</a></li> | |||
<li><a href="http://partners.adobe.com/asn/developer/technotes/fonts.html">Adobe Font Technote</a></li> | |||
<li> | |||
<a href="http://partners.adobe.com/asn/developer/type/ftypes.html">Adobe font types</a> | |||
</li> | |||
<li> | |||
<a href="http://partners.adobe.com/asn/developer/technotes/fonts.html">Adobe Font Technote</a> | |||
</li> | |||
</ul> | |||
</section> | |||
<section id="basics"> | |||
<title>Basic font configuration</title> | |||
<p> | |||
@@ -220,7 +222,6 @@ | |||
not possible to easily configure fonts from Java code. | |||
</note> | |||
</section> | |||
<section id="advanced"> | |||
<title>Advanced font configuration</title> | |||
<p> | |||
@@ -359,7 +360,7 @@ | |||
relative to the base directory. | |||
</li> | |||
</ul> | |||
<!--note>Cocoon users will need to setup the config, see FOPSerializer for more information.</note--> | |||
<!--note>Cocoon users will need to setup the config, see FOPSerializer for more information.</note--> | |||
</section> | |||
<section id="autodetect"> | |||
<title>Auto-Detect and auto-embed feature</title> | |||
@@ -425,14 +426,14 @@ | |||
</ul> | |||
</section> | |||
<section id="substitution"> | |||
<title>Substitution</title> | |||
<p>When a <substitutions/> section is defined in the configuration, FOP will re-map any font-family references found in your FO input to a given substitution font.</p> | |||
<ul> | |||
<li>If a <substitution/> is declared, it is mandatory that both a <from/> and <to/> child element is declared with a font-family attribute.</li> | |||
<li>Both font-weight and font-style are optional attributes, if they are provided then a value of 'normal' is assumed.</li> | |||
</ul> | |||
<p>For example you could make all FO font-family references to 'Arial' with weights between 700 and 900 reference the normal 'Arial Black' font.</p> | |||
<source><![CDATA[ | |||
<title>Substitution</title> | |||
<p>When a <substitutions/> section is defined in the configuration, FOP will re-map any font-family references found in your FO input to a given substitution font.</p> | |||
<ul> | |||
<li>If a <substitution/> is declared, it is mandatory that both a <from/> and <to/> child element is declared with a font-family attribute.</li> | |||
<li>Both font-weight and font-style are optional attributes, if they are provided then a value of 'normal' is assumed.</li> | |||
</ul> | |||
<p>For example you could make all FO font-family references to 'Arial' with weights between 700 and 900 reference the normal 'Arial Black' font.</p> | |||
<source><![CDATA[ | |||
<fop version="1.0"> | |||
<fonts> | |||
<substitutions> | |||
@@ -448,7 +449,7 @@ | |||
</fonts> | |||
</fop>]]></source> | |||
</section> | |||
<!-- The following section should no longer be required | |||
<!-- The following section should no longer be required | |||
<section id="embedding-base14"> | |||
<title>Explicitly embedding the base 14 fonts</title> | |||
<p> | |||
@@ -474,5 +475,18 @@ | |||
[..]]]></source> | |||
</section--> | |||
</section> | |||
<section id="selection"> | |||
<title>Font Selection Strategies</title> | |||
<p> | |||
There are two font selection strategies: character-by-character or auto. The default is auto.</p> | |||
<p>Auto selected the first font from the list which is able to display the most characters in a given word. This means (assume font A has characters for abclmn, font B for lnmxyz, fontlist is A,B):</p> | |||
<ul> | |||
<li>aaa lll xxx would be displayed in fonts A A B</li> | |||
<li>aaaxx would be displayed in font A</li> | |||
<li>aaaxxx would be displayed in font A</li> | |||
<li>aaaxxxx would be displayed in font B</li> | |||
</ul> | |||
<p>Character-by-Character is NOT yet supported!</p> | |||
</section> | |||
</body> | |||
</document> |
@@ -37,7 +37,7 @@ import org.apache.fop.fo.properties.SpaceProperty; | |||
/** | |||
* A text node (PCDATA) in the formatting object tree. | |||
* | |||
* Unfortunately the BufferManager implementatation holds | |||
* Unfortunately the BufferManager implementation holds | |||
* onto references to the character data in this object | |||
* longer than the lifetime of the object itself, causing | |||
* excessive memory consumption and OOM errors. |
@@ -87,39 +87,49 @@ public class XMLWhiteSpaceHandler { | |||
* @param nextChild the node that will be added to the list | |||
* after firstTextNode | |||
*/ | |||
public void handleWhiteSpace(FObjMixed fo, FONode firstTextNode, FONode nextChild) { | |||
public void handleWhiteSpace(FObjMixed fo, | |||
FONode firstTextNode, | |||
FONode nextChild) { | |||
Block currentBlock = null; | |||
int foId = fo.getNameId(); | |||
if (foId == Constants.FO_BLOCK) { | |||
currentBlock = (Block) fo; | |||
if (nestedBlockStack.isEmpty() || fo != nestedBlockStack.peek()) { | |||
if (nextChild != null) { | |||
/* if already in a block, push the current block | |||
* onto the stack of nested blocks | |||
*/ | |||
nestedBlockStack.push(currentBlock); | |||
/* set the current block */ | |||
switch (foId) { | |||
case Constants.FO_BLOCK: | |||
currentBlock = (Block) fo; | |||
if (nestedBlockStack.empty() || fo != nestedBlockStack.peek()) { | |||
if (nextChild != null) { | |||
/* if already in a block, push the current block | |||
* onto the stack of nested blocks | |||
*/ | |||
nestedBlockStack.push(currentBlock); | |||
} | |||
} else { | |||
if (nextChild == null) { | |||
nestedBlockStack.pop(); | |||
} | |||
} | |||
} else { | |||
if (nextChild == null) { | |||
nestedBlockStack.pop(); | |||
break; | |||
case Constants.FO_RETRIEVE_MARKER: | |||
/* look for the nearest block ancestor, if any */ | |||
FONode ancestor = fo; | |||
do { | |||
ancestor = ancestor.getParent(); | |||
} while (ancestor.getNameId() != Constants.FO_BLOCK | |||
&& ancestor.getNameId() != Constants.FO_STATIC_CONTENT); | |||
if (ancestor.getNameId() == Constants.FO_BLOCK) { | |||
currentBlock = (Block) ancestor; | |||
nestedBlockStack.push(currentBlock); | |||
} | |||
} | |||
} else if (foId == Constants.FO_RETRIEVE_MARKER) { | |||
/* look for the nearest block ancestor, if any */ | |||
FONode ancestor = fo; | |||
do { | |||
ancestor = ancestor.getParent(); | |||
} while (ancestor.getNameId() != Constants.FO_BLOCK | |||
&& ancestor.getNameId() != Constants.FO_STATIC_CONTENT); | |||
break; | |||
if (ancestor.getNameId() == Constants.FO_BLOCK) { | |||
currentBlock = (Block) ancestor; | |||
nestedBlockStack.push(currentBlock); | |||
} | |||
} else if (!nestedBlockStack.isEmpty()) { | |||
currentBlock = (Block) nestedBlockStack.peek(); | |||
default: | |||
if (!nestedBlockStack.empty()) { | |||
currentBlock = (Block) nestedBlockStack.peek(); | |||
} | |||
} | |||
if (currentBlock != null) { | |||
@@ -132,8 +142,15 @@ public class XMLWhiteSpaceHandler { | |||
whiteSpaceTreatment = Constants.EN_IGNORE_IF_SURROUNDING_LINEFEED; | |||
} | |||
endOfBlock = (nextChild == null && fo == currentBlock); | |||
if (firstTextNode == null) { | |||
//nothing to do but initialize related properties | |||
//no text means no white-space to handle; return early | |||
afterLinefeed = (fo == currentBlock && fo.firstChild == null); | |||
nonWhiteSpaceCount = 0; | |||
if (endOfBlock) { | |||
handlePendingInlines(); | |||
} | |||
return; | |||
} | |||
@@ -144,13 +161,32 @@ public class XMLWhiteSpaceHandler { | |||
|| currentBlock == null | |||
|| (foId == Constants.FO_RETRIEVE_MARKER | |||
&& fo.getParent() == currentBlock)) { | |||
afterLinefeed = ( | |||
(firstTextNode == fo.firstChild) | |||
|| (firstTextNode.siblings[0].getNameId() | |||
== Constants.FO_BLOCK)); | |||
if (firstTextNode == fo.firstChild) { | |||
afterLinefeed = true; | |||
} else { | |||
int previousChildId = firstTextNode.siblings[0].getNameId(); | |||
afterLinefeed = (previousChildId == Constants.FO_BLOCK | |||
|| previousChildId == Constants.FO_TABLE_AND_CAPTION | |||
|| previousChildId == Constants.FO_TABLE | |||
|| previousChildId == Constants.FO_LIST_BLOCK | |||
|| previousChildId == Constants.FO_BLOCK_CONTAINER); | |||
} | |||
} | |||
endOfBlock = (nextChild == null && fo == currentBlock); | |||
if (foId == Constants.FO_WRAPPER) { | |||
FONode parent = fo.parent; | |||
int parentId = parent.getNameId(); | |||
while (parentId == Constants.FO_WRAPPER) { | |||
parent = parent.parent; | |||
parentId = parent.getNameId(); | |||
} | |||
if (parentId == Constants.FO_FLOW | |||
|| parentId == Constants.FO_STATIC_CONTENT | |||
|| parentId == Constants.FO_BLOCK_CONTAINER | |||
|| parentId == Constants.FO_TABLE_CELL) { | |||
endOfBlock = (nextChild == null); | |||
} | |||
} | |||
if (nextChild != null) { | |||
int nextChildId = nextChild.getNameId(); | |||
@@ -167,26 +203,8 @@ public class XMLWhiteSpaceHandler { | |||
handleWhiteSpace(); | |||
if (fo == currentBlock | |||
&& pendingInlines != null | |||
&& !pendingInlines.isEmpty()) { | |||
/* current FO is a block, and has pending inlines */ | |||
if (endOfBlock || nextChildIsBlockLevel) { | |||
if (nonWhiteSpaceCount == 0) { | |||
/* handle white-space for all pending inlines*/ | |||
PendingInline p; | |||
for (int i = pendingInlines.size(); --i >= 0;) { | |||
p = (PendingInline)pendingInlines.get(i); | |||
charIter = (RecursiveCharIterator)p.firstTrailingWhiteSpace; | |||
handleWhiteSpace(); | |||
pendingInlines.remove(p); | |||
} | |||
} else { | |||
/* there is non-white-space text between the pending | |||
* inline(s) and the end of the block; | |||
* clear list of pending inlines */ | |||
pendingInlines.clear(); | |||
} | |||
} | |||
&& (endOfBlock || nextChildIsBlockLevel)) { | |||
handlePendingInlines(); | |||
} | |||
if (nextChild == null) { | |||
@@ -333,6 +351,26 @@ public class XMLWhiteSpaceHandler { | |||
pendingInlines.add(new PendingInline(fo, firstWhiteSpaceInSeq)); | |||
} | |||
private void handlePendingInlines() { | |||
if (!(pendingInlines == null || pendingInlines.isEmpty())) { | |||
if (nonWhiteSpaceCount == 0) { | |||
/* handle white-space for all pending inlines*/ | |||
PendingInline p; | |||
for (int i = pendingInlines.size(); --i >= 0;) { | |||
p = (PendingInline)pendingInlines.get(i); | |||
charIter = (RecursiveCharIterator)p.firstTrailingWhiteSpace; | |||
handleWhiteSpace(); | |||
pendingInlines.remove(p); | |||
} | |||
} else { | |||
/* there is non-white-space text between the pending | |||
* inline(s) and the end of the block; | |||
* clear list of pending inlines */ | |||
pendingInlines.clear(); | |||
} | |||
} | |||
} | |||
/** | |||
* Helper class, used during white-space handling to look ahead, and | |||
* see if the next character is a linefeed (or if there will be |
@@ -0,0 +1,142 @@ | |||
/* | |||
* 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$ */ | |||
package org.apache.fop.fonts; | |||
import org.apache.fop.datatypes.PercentBaseContext; | |||
import org.apache.fop.fo.FONode; | |||
import org.apache.fop.fo.FOText; | |||
import org.apache.fop.fo.flow.Character; | |||
import org.apache.fop.fo.properties.CommonFont; | |||
/** | |||
* Helper class for automatic font selection. | |||
* <p> | |||
* TODO: Check if this could be merged with another font class, such as | |||
* {@link FontManager}. | |||
*/ | |||
public final class FontSelector { | |||
private FontSelector() { | |||
// Static since this is an utility class. | |||
} | |||
private static Font selectFontForCharacter(char c, FONode fonode, | |||
CommonFont commonFont, PercentBaseContext context) { | |||
FontInfo fi = fonode.getFOEventHandler().getFontInfo(); | |||
FontTriplet[] fontkeys = commonFont.getFontState(fi); | |||
for (int i = 0; i < fontkeys.length; i++) { | |||
Font font = fi.getFontInstance(fontkeys[i], commonFont.fontSize | |||
.getValue(context)); | |||
if (font.hasChar(c)) { | |||
return font; | |||
} | |||
} | |||
return fi.getFontInstance(fontkeys[0], commonFont.fontSize | |||
.getValue(context)); | |||
} | |||
/** | |||
* Selects a font which is able to display the given character. | |||
* | |||
* @param fobj | |||
* a Character object containing the character and its | |||
* attributes. | |||
* @param context | |||
* the Percent-based context needed for creating the actual font. | |||
* @return a Font object. | |||
*/ | |||
public static Font selectFontForCharacter(Character fobj, | |||
PercentBaseContext context) { | |||
return FontSelector.selectFontForCharacter(fobj.getCharacter(), fobj, | |||
fobj.getCommonFont(), context); | |||
} | |||
/** | |||
* Selects a font which is able to display the given character. | |||
* | |||
* @param c | |||
* character to find. | |||
* @param text | |||
* the text object which contains the character | |||
* @param context | |||
* the Percent-based context needed for creating the actual font. | |||
* @return a Font object. | |||
*/ | |||
public static Font selectFontForCharacterInText(char c, FOText text, | |||
PercentBaseContext context) { | |||
return FontSelector.selectFontForCharacter(c, text, text | |||
.getCommonFont(), context); | |||
} | |||
/** | |||
* Selects a font which is able to display the most of the given characters. | |||
* | |||
* @param textArray | |||
* Text to go through | |||
* @param firstIndex | |||
* first index within text. | |||
* @param breakIndex | |||
* last index +1 within text. | |||
* @param text | |||
* the text object which contains the character | |||
* @param context | |||
* the Percent-based context needed for creating the actual font. | |||
* @return a Font object. | |||
*/ | |||
public static Font selectFontForCharactersInText(char[] textArray, | |||
int firstIndex, int breakIndex, FOText text, | |||
PercentBaseContext context) { | |||
final FontInfo fi = text.getFOEventHandler().getFontInfo(); | |||
final CommonFont commonFont = text.getCommonFont(); | |||
final FontTriplet[] fontkeys = commonFont.getFontState(fi); | |||
final int numFonts = fontkeys.length; | |||
final Font[] fonts = new Font[numFonts]; | |||
final int[] fontCount = new int[numFonts]; | |||
for (int fontnum = 0; fontnum < numFonts; fontnum++) { | |||
final Font font = fi.getFontInstance(fontkeys[fontnum], | |||
commonFont.fontSize.getValue(context)); | |||
fonts[fontnum] = font; | |||
for (int pos = firstIndex; pos < breakIndex; pos++) { | |||
if (font.hasChar(textArray[pos])) { | |||
fontCount[fontnum]++; | |||
} | |||
} | |||
// quick fall through if all characters can be displayed | |||
if (fontCount[fontnum] == (breakIndex - firstIndex)) { | |||
return font; | |||
} | |||
} | |||
Font font = fonts[0]; | |||
int max = fontCount[0]; | |||
for (int fontnum = 1; fontnum < numFonts; fontnum++) { | |||
final int curCount = fontCount[fontnum]; | |||
if (curCount > max) { | |||
font = fonts[fontnum]; | |||
max = curCount; | |||
} | |||
} | |||
return font; | |||
} | |||
} |
@@ -26,8 +26,7 @@ import org.apache.fop.area.Trait; | |||
import org.apache.fop.fo.flow.Character; | |||
import org.apache.fop.fo.properties.CommonBorderPaddingBackground; | |||
import org.apache.fop.fonts.Font; | |||
import org.apache.fop.fonts.FontInfo; | |||
import org.apache.fop.fonts.FontTriplet; | |||
import org.apache.fop.fonts.FontSelector; | |||
import org.apache.fop.layoutmgr.InlineKnuthSequence; | |||
import org.apache.fop.layoutmgr.KnuthElement; | |||
import org.apache.fop.layoutmgr.KnuthGlue; | |||
@@ -62,7 +61,7 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager { | |||
/** {@inheritDoc} */ | |||
public void initialize() { | |||
Character fobj = (Character)this.fobj; | |||
font = this.selectFontForCharacter(fobj); | |||
font = FontSelector.selectFontForCharacter(fobj, this); | |||
SpaceVal ls = SpaceVal.makeLetterSpacing(fobj.getLetterSpacing()); | |||
letterSpaceIPD = ls.getSpace(); | |||
hyphIPD = fobj.getCommonHyphenation().getHyphIPD(font); | |||
@@ -72,33 +71,6 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager { | |||
chArea.setBaselineOffset(font.getAscender()); | |||
setCurrentArea(chArea); | |||
} | |||
/** | |||
* Selects a font which is able to display the given character. | |||
* <p> | |||
* Please note: this implements the font-selection-strategy | |||
* character-by-character. | |||
* <p> | |||
* TODO: The same function could apply to other elements as well. | |||
* | |||
* @param fobj | |||
* a Character object containing the character and its | |||
* attributed. | |||
* @return a Font object. | |||
*/ | |||
private Font selectFontForCharacter(Character fobj) { | |||
FontInfo fi = fobj.getFOEventHandler().getFontInfo(); | |||
FontTriplet[] fontkeys = fobj.getCommonFont().getFontState(fi); | |||
for (int i = 0; i < fontkeys.length; i++) { | |||
font = fi.getFontInstance(fontkeys[i], | |||
fobj.getCommonFont().fontSize.getValue(this)); | |||
if (font.hasChar(fobj.getCharacter())) { | |||
return font; | |||
} | |||
} | |||
return fi.getFontInstance(fontkeys[0], | |||
fobj.getCommonFont().fontSize.getValue(this)); | |||
} | |||
private org.apache.fop.area.inline.TextArea getCharacterInlineArea(Character node) { | |||
org.apache.fop.area.inline.TextArea text |
@@ -26,7 +26,6 @@ import java.util.ListIterator; | |||
import org.apache.commons.logging.Log; | |||
import org.apache.commons.logging.LogFactory; | |||
import org.apache.fop.area.Area; | |||
import org.apache.fop.area.Block; | |||
import org.apache.fop.fo.flow.ListItem; | |||
@@ -39,12 +38,14 @@ import org.apache.fop.layoutmgr.ConditionalElementListener; | |||
import org.apache.fop.layoutmgr.ElementListObserver; | |||
import org.apache.fop.layoutmgr.ElementListUtils; | |||
import org.apache.fop.layoutmgr.KeepUtil; | |||
import org.apache.fop.layoutmgr.KnuthBlockBox; | |||
import org.apache.fop.layoutmgr.KnuthBox; | |||
import org.apache.fop.layoutmgr.KnuthElement; | |||
import org.apache.fop.layoutmgr.KnuthPenalty; | |||
import org.apache.fop.layoutmgr.KnuthPossPosIter; | |||
import org.apache.fop.layoutmgr.LayoutContext; | |||
import org.apache.fop.layoutmgr.LayoutManager; | |||
import org.apache.fop.layoutmgr.ListElement; | |||
import org.apache.fop.layoutmgr.NonLeafPosition; | |||
import org.apache.fop.layoutmgr.Position; | |||
import org.apache.fop.layoutmgr.PositionIterator; | |||
@@ -279,8 +280,7 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager | |||
int keepWithNextActive = BlockLevelLayoutManager.KEEP_AUTO; | |||
LinkedList returnList = new LinkedList(); | |||
while ((step = getNextStep(elementLists, start, end, partialHeights)) | |||
> 0) { | |||
while ((step = getNextStep(elementLists, start, end, partialHeights)) > 0) { | |||
if (end[0] + 1 == elementLists[0].size()) { | |||
keepWithNextActive = Math.max(keepWithNextActive, keepWithNextPendingOnLabel); | |||
@@ -312,11 +312,33 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager | |||
int boxHeight = step - addedBoxHeight - penaltyHeight; | |||
penaltyHeight += additionalPenaltyHeight; //Add AFTER calculating boxHeight! | |||
// collect footnote information | |||
// TODO this should really not be done like this. ListItemLM should remain as | |||
// footnote-agnostic as possible | |||
LinkedList footnoteList = null; | |||
ListElement el; | |||
for (int i = 0; i < elementLists.length; i++) { | |||
for (int j = start[i]; j <= end[i]; j++) { | |||
el = (ListElement) elementLists[i].get(j); | |||
if (el instanceof KnuthBlockBox && ((KnuthBlockBox) el).hasAnchors()) { | |||
if (footnoteList == null) { | |||
footnoteList = new LinkedList(); | |||
} | |||
footnoteList.addAll(((KnuthBlockBox) el).getFootnoteBodyLMs()); | |||
} | |||
} | |||
} | |||
// add the new elements | |||
addedBoxHeight += boxHeight; | |||
ListItemPosition stepPosition = new ListItemPosition(this, | |||
start[0], end[0], start[1], end[1]); | |||
returnList.add(new KnuthBox(boxHeight, stepPosition, false)); | |||
if (footnoteList == null) { | |||
returnList.add(new KnuthBox(boxHeight, stepPosition, false)); | |||
} else { | |||
returnList.add(new KnuthBlockBox(boxHeight, footnoteList, stepPosition, false)); | |||
} | |||
if (addedBoxHeight < totalHeight) { | |||
int strength = BlockLevelLayoutManager.KEEP_AUTO; | |||
strength = Math.max(strength, keepWithNextActive); |
@@ -19,12 +19,12 @@ | |||
package org.apache.fop.layoutmgr.table; | |||
import java.util.LinkedList; | |||
import java.util.List; | |||
import java.util.ListIterator; | |||
import org.apache.commons.logging.Log; | |||
import org.apache.commons.logging.LogFactory; | |||
import org.apache.fop.fo.Constants; | |||
import org.apache.fop.fo.flow.table.ConditionalBorder; | |||
import org.apache.fop.fo.flow.table.EffRow; | |||
@@ -32,6 +32,7 @@ import org.apache.fop.fo.flow.table.PrimaryGridUnit; | |||
import org.apache.fop.fo.properties.CommonBorderPaddingBackground; | |||
import org.apache.fop.layoutmgr.BlockLevelLayoutManager; | |||
import org.apache.fop.layoutmgr.ElementListUtils; | |||
import org.apache.fop.layoutmgr.KnuthBlockBox; | |||
import org.apache.fop.layoutmgr.KnuthBox; | |||
import org.apache.fop.layoutmgr.KnuthElement; | |||
import org.apache.fop.layoutmgr.KnuthPenalty; | |||
@@ -101,6 +102,8 @@ class ActiveCell { | |||
private int penaltyLength; | |||
/** Value of the penalty ending this step, 0 if the step does not end on a penalty. */ | |||
private int penaltyValue; | |||
/** List of footnotes for this step. */ | |||
private List footnoteList; | |||
/** | |||
* One of {@link Constants#EN_AUTO}, {@link Constants#EN_COLUMN}, | |||
* {@link Constants#EN_PAGE}, {@link Constants#EN_EVEN_PAGE}, | |||
@@ -130,6 +133,7 @@ class ActiveCell { | |||
this.totalLength = other.totalLength; | |||
this.penaltyLength = other.penaltyLength; | |||
this.penaltyValue = other.penaltyValue; | |||
this.footnoteList = other.footnoteList; | |||
this.condBeforeContentLength = other.condBeforeContentLength; | |||
this.breakClass = other.breakClass; | |||
} | |||
@@ -293,6 +297,7 @@ class ActiveCell { | |||
afterNextStep.penaltyValue = 0; | |||
afterNextStep.condBeforeContentLength = 0; | |||
afterNextStep.breakClass = Constants.EN_AUTO; | |||
afterNextStep.footnoteList = null; | |||
boolean breakFound = false; | |||
boolean prevIsBox = false; | |||
boolean boxFound = false; | |||
@@ -322,6 +327,12 @@ class ActiveCell { | |||
} | |||
prevIsBox = false; | |||
} else { | |||
if (el instanceof KnuthBlockBox && ((KnuthBlockBox) el).hasAnchors()) { | |||
if (afterNextStep.footnoteList == null) { | |||
afterNextStep.footnoteList = new LinkedList(); | |||
} | |||
afterNextStep.footnoteList.addAll(((KnuthBlockBox) el).getFootnoteBodyLMs()); | |||
} | |||
prevIsBox = true; | |||
boxFound = true; | |||
afterNextStep.contentLength += el.getW(); | |||
@@ -543,6 +554,18 @@ class ActiveCell { | |||
} | |||
} | |||
/** | |||
* Adds the footnotes (if any) that are part of the next step, if this cell | |||
* contributes content to the next step. | |||
* | |||
* @param footnoteList the list to which this cell must add its footnotes | |||
*/ | |||
void addFootnotes(List footnoteList) { | |||
if (includedInLastStep() && nextStep.footnoteList != null) { | |||
footnoteList.addAll(nextStep.footnoteList); | |||
} | |||
} | |||
int getKeepWithNextStrength() { | |||
return keepWithNextStrength; | |||
} |
@@ -33,6 +33,7 @@ import org.apache.fop.fo.flow.table.PrimaryGridUnit; | |||
import org.apache.fop.layoutmgr.BlockLevelLayoutManager; | |||
import org.apache.fop.layoutmgr.BreakElement; | |||
import org.apache.fop.layoutmgr.KeepUtil; | |||
import org.apache.fop.layoutmgr.KnuthBlockBox; | |||
import org.apache.fop.layoutmgr.KnuthBox; | |||
import org.apache.fop.layoutmgr.KnuthElement; | |||
import org.apache.fop.layoutmgr.KnuthGlue; | |||
@@ -199,12 +200,14 @@ public class TableStepper { | |||
} | |||
} | |||
LinkedList footnoteList = new LinkedList(); | |||
//Put all involved grid units into a list | |||
List cellParts = new java.util.ArrayList(columnCount); | |||
for (Iterator iter = activeCells.iterator(); iter.hasNext();) { | |||
ActiveCell activeCell = (ActiveCell) iter.next(); | |||
CellPart part = activeCell.createCellPart(); | |||
cellParts.add(part); | |||
activeCell.addFootnotes(footnoteList); | |||
} | |||
//Create elements for step | |||
@@ -217,7 +220,13 @@ public class TableStepper { | |||
tcpos.setFlag(TableContentPosition.FIRST_IN_ROWGROUP, true); | |||
} | |||
lastTCPos = tcpos; | |||
returnList.add(new KnuthBox(boxLen, tcpos, false)); | |||
// TODO TableStepper should remain as footnote-agnostic as possible | |||
if (footnoteList.isEmpty()) { | |||
returnList.add(new KnuthBox(boxLen, tcpos, false)); | |||
} else { | |||
returnList.add(new KnuthBlockBox(boxLen, footnoteList, tcpos, false)); | |||
} | |||
int effPenaltyLen = Math.max(0, penaltyOrGlueLen); | |||
TableHFPenaltyPosition penaltyPos = new TableHFPenaltyPosition(getTableLM()); |
@@ -60,6 +60,13 @@ | |||
<action context="Renderers" dev="AC" importance="high" type="add"> | |||
Added de-duplication and externalization support for IOCA and GOCA data resource objects. | |||
</action --> | |||
<action context="Code" dev="AD" type="fix" fixes-bug="45097"> | |||
Corrected white-space-treatment for situations where an inline-node is the first/last | |||
child node of an fo:block, without preceding/following text. | |||
</action> | |||
<action context="Layout" dev="MB" type="add"> | |||
Implemented word-by-ford font-selection strategy on text. | |||
</action> | |||
<action context="Layout" dev="MB" type="add"> | |||
Support character-by-character font-selection strategy on fo:character element. | |||
</action> |
@@ -97,24 +97,6 @@ | |||
<description>Space resolution does not work between footnote | |||
regions.</description> | |||
</testcase> | |||
<testcase> | |||
<name>Footnotes swallowed in lists</name> | |||
<file>footnote_in_list.xml</file> | |||
<description>Element lists for lists are created by combining the | |||
element lists from list-item-label and list-item-body. The | |||
footnotes contained in the KnuthBlockBoxes are not propagated to | |||
the combined element list.</description> | |||
<reference>http://issues.apache.org/bugzilla/show_bug.cgi?id=37579</reference> | |||
</testcase> | |||
<testcase> | |||
<name>Footnotes swallowed in tables</name> | |||
<file>footnote_in_table.xml</file> | |||
<description>Element lists for tables are created by combining the | |||
element lists from the individual table-cells. The footnotes | |||
contained in the KnuthBlockBoxes are not propagated to the combined | |||
element list.</description> | |||
<reference>http://issues.apache.org/bugzilla/show_bug.cgi?id=37579</reference> | |||
</testcase> | |||
<testcase> | |||
<name>NPE for table inside an inline</name> | |||
<file>inline_block_nested_3.xml</file> |
@@ -0,0 +1,54 @@ | |||
<?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 font auto selection. | |||
</p> | |||
</info> | |||
<fo> | |||
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:svg="http://www.w3.org/2000/svg"> | |||
<fo:layout-master-set> | |||
<fo:simple-page-master master-name="normal" page-width="210mm" page-height="297mm"> | |||
<fo:region-body/> | |||
</fo:simple-page-master> | |||
</fo:layout-master-set> | |||
<fo:page-sequence master-reference="normal" white-space-collapse="true"> | |||
<fo:flow flow-name="xsl-region-body"> | |||
<fo:block>font-family not given</fo:block> | |||
<fo:block>this text contains a ∑ symbol in the middle</fo:block> | |||
<fo:block>mixed contents should be</fo:block> | |||
<fo:block>∑∑text</fo:block> | |||
<fo:block>∑∑∑∑text</fo:block> | |||
<fo:block>∑∑∑∑sym</fo:block> | |||
</fo:flow> | |||
</fo:page-sequence> | |||
</fo:root> | |||
</fo> | |||
<checks> | |||
<eval expected="sans-serif" xpath="//flow/block[1]/lineArea/text/@font-name"/> | |||
<eval expected="sans-serif" xpath="//flow/block[2]/lineArea/text[1]/@font-name"/> | |||
<eval expected="Symbol" xpath="//flow/block[2]/lineArea/text[2]/@font-name"/> | |||
<eval expected="sans-serif" xpath="//flow/block[2]/lineArea/text[3]/@font-name"/> | |||
<eval expected="sans-serif" xpath="//flow/block[3]/lineArea/text[1]/@font-name"/> | |||
<eval expected="sans-serif" xpath="//flow/block[4]/lineArea/text[1]/@font-name"/> | |||
<eval expected="sans-serif" xpath="//flow/block[5]/lineArea/text[1]/@font-name"/> | |||
<eval expected="Symbol" xpath="//flow/block[6]/lineArea/text[1]/@font-name"/> | |||
</checks> | |||
</testcase> |
@@ -65,5 +65,7 @@ | |||
</fo> | |||
<checks> | |||
<eval expected="2" xpath="count(//footnote/block)"/> | |||
<eval expected="1) The footnote from the normal block." xpath="//footnote/block[1]"/> | |||
<eval expected="2) The footnote from the list." xpath="//footnote/block[2]"/> | |||
</checks> | |||
</testcase> |
@@ -0,0 +1,125 @@ | |||
<?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 footnotes as descendants of list-item-body elements. | |||
</p> | |||
</info> | |||
<fo> | |||
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> | |||
<fo:layout-master-set> | |||
<fo:simple-page-master master-name="simple" page-height="220pt" page-width="3in" | |||
margin="10pt"> | |||
<fo:region-body background-color="#F0F0F0"/> | |||
</fo:simple-page-master> | |||
</fo:layout-master-set> | |||
<fo:page-sequence master-reference="simple" font-size="8pt" line-height="10pt"> | |||
<fo:flow flow-name="xsl-region-body"> | |||
<fo:block>Before the list.</fo:block> | |||
<fo:list-block provisional-distance-between-starts="1.2em" provisional-label-separation="2pt"> | |||
<fo:list-item> | |||
<fo:list-item-label end-indent="label-end()"> | |||
<fo:block>–</fo:block> | |||
</fo:list-item-label> | |||
<fo:list-item-body start-indent="body-start()"> | |||
<fo:block>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Pellentesque<fo:footnote> | |||
<fo:inline>(1)</fo:inline> | |||
<fo:footnote-body> | |||
<fo:block start-indent="0"> | |||
<fo:inline>(1)</fo:inline> First footnote from the list.</fo:block> | |||
</fo:footnote-body> | |||
</fo:footnote> hendrerit euismod velit. Nulla facilisi. Etiam et risus at neque ultrices | |||
facilisis. Donec lectus est, nonummy quis, rhoncus bibendum, porta at, nisl<fo:footnote> | |||
<fo:inline>(2)</fo:inline> | |||
<fo:footnote-body> | |||
<fo:block start-indent="0"> | |||
<fo:inline>(2)</fo:inline> Second footnote from the list.</fo:block> | |||
</fo:footnote-body> | |||
</fo:footnote>. | |||
</fo:block> | |||
</fo:list-item-body> | |||
</fo:list-item> | |||
<fo:list-item> | |||
<fo:list-item-label end-indent="label-end()"> | |||
<fo:block>–</fo:block> | |||
</fo:list-item-label> | |||
<fo:list-item-body start-indent="body-start()"> | |||
<fo:block>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Pellentesque<fo:footnote> | |||
<fo:inline>(3)</fo:inline> | |||
<fo:footnote-body> | |||
<fo:block start-indent="0"> | |||
<fo:inline>(3)</fo:inline> Third footnote from the list.</fo:block> | |||
</fo:footnote-body> | |||
</fo:footnote> hendrerit euismod velit. Nulla facilisi. Etiam et risus at neque ultrices | |||
facilisis. Donec lectus est, nonummy quis, rhoncus bibendum, porta at, nisl<fo:footnote> | |||
<fo:inline>(4)</fo:inline> | |||
<fo:footnote-body> | |||
<fo:block start-indent="0"> | |||
<fo:inline>(4)</fo:inline> Fourth footnote from the list.</fo:block> | |||
</fo:footnote-body> | |||
</fo:footnote>. | |||
</fo:block> | |||
</fo:list-item-body> | |||
</fo:list-item> | |||
</fo:list-block> | |||
</fo:flow> | |||
</fo:page-sequence> | |||
<fo:page-sequence master-reference="simple" font-size="8pt" line-height="10pt"> | |||
<fo:flow flow-name="xsl-region-body"> | |||
<fo:block space-after="130pt">Before the list.</fo:block> | |||
<fo:list-block provisional-distance-between-starts="1.2em" provisional-label-separation="2pt"> | |||
<fo:list-item> | |||
<fo:list-item-label end-indent="label-end()"> | |||
<fo:block>–</fo:block> | |||
</fo:list-item-label> | |||
<fo:list-item-body start-indent="body-start()"> | |||
<fo:block orphans="1" widows="1">Lorem ipsum dolor sit amet, consectetuer adipiscing | |||
elit. Pellentesque<fo:footnote> | |||
<fo:inline>(1)</fo:inline> | |||
<fo:footnote-body> | |||
<fo:block start-indent="0">(1) First footnote from the list.</fo:block> | |||
</fo:footnote-body> | |||
</fo:footnote> hendrerit euismod velit. Nulla facilisi. Etiam et risus at neque ultrices | |||
facilisis. Donec lectus est, nonummy quis, rhoncus bibendum, porta at, nisl<fo:footnote> | |||
<fo:inline>(2)</fo:inline> | |||
<fo:footnote-body> | |||
<fo:block start-indent="0">(2) Second footnote from the list.</fo:block> | |||
</fo:footnote-body> | |||
</fo:footnote>. | |||
</fo:block> | |||
</fo:list-item-body> | |||
</fo:list-item> | |||
</fo:list-block> | |||
</fo:flow> | |||
</fo:page-sequence> | |||
</fo:root> | |||
</fo> | |||
<checks> | |||
<eval expected="4" xpath="count(//pageSequence[1]//footnote/block)"/> | |||
<eval expected="(1) First footnote from the list." xpath="//pageSequence[1]//footnote/block[1]"/> | |||
<eval expected="(2) Second footnote from the list." xpath="//pageSequence[1]//footnote/block[2]"/> | |||
<eval expected="(3) Third footnote from the list." xpath="//pageSequence[1]//footnote/block[3]"/> | |||
<eval expected="(4) Fourth footnote from the list." xpath="//pageSequence[1]//footnote/block[4]"/> | |||
<eval expected="1" xpath="count(//pageSequence[2]/pageViewport[1]//footnote/block)"/> | |||
<eval expected="(1) First footnote from the list." xpath="//pageSequence[2]/pageViewport[1]//footnote/block"/> | |||
<eval expected="1" xpath="count(//pageSequence[2]/pageViewport[2]//footnote/block)"/> | |||
<eval expected="(2) Second footnote from the list." xpath="//pageSequence[2]/pageViewport[2]//footnote/block"/> | |||
</checks> | |||
</testcase> |
@@ -69,5 +69,7 @@ | |||
</fo> | |||
<checks> | |||
<eval expected="2" xpath="count(//footnote/block)"/> | |||
<eval expected="1) The footnote from the normal block." xpath="//footnote/block[1]"/> | |||
<eval expected="2) The footnote from the table." xpath="//footnote/block[2]"/> | |||
</checks> | |||
</testcase> |
@@ -0,0 +1,185 @@ | |||
<?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 footnotes as descendants of table-body elements. | |||
</p> | |||
</info> | |||
<fo> | |||
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> | |||
<fo:layout-master-set> | |||
<fo:simple-page-master master-name="simple" page-height="220pt" page-width="3in" | |||
margin="10pt"> | |||
<fo:region-body background-color="#F0F0F0"/> | |||
</fo:simple-page-master> | |||
</fo:layout-master-set> | |||
<fo:page-sequence master-reference="simple" font-size="8pt" line-height="10pt"> | |||
<fo:flow flow-name="xsl-region-body"> | |||
<fo:block>Before the table</fo:block> | |||
<fo:table table-layout="fixed" width="100%"> | |||
<fo:table-column column-width="proportional-column-width(1)"/> | |||
<fo:table-column column-width="proportional-column-width(1)"/> | |||
<fo:table-body border="1pt solid black"> | |||
<fo:table-row border="inherit"> | |||
<fo:table-cell border="inherit" number-rows-spanned="2"> | |||
<fo:block>Cell 1.1</fo:block> | |||
<fo:block>Cell 1.1</fo:block> | |||
<fo:block>Cell 1.1<fo:footnote> | |||
<fo:inline>(2)</fo:inline> | |||
<fo:footnote-body> | |||
<fo:block>(2) Second footnote from the table.</fo:block> | |||
</fo:footnote-body> | |||
</fo:footnote></fo:block> | |||
<fo:block>Cell 1.1</fo:block> | |||
</fo:table-cell> | |||
<fo:table-cell border="inherit"> | |||
<fo:block>Cell 1.2</fo:block> | |||
<fo:block>Cell 1.2<fo:footnote> | |||
<fo:inline>(1)</fo:inline> | |||
<fo:footnote-body> | |||
<fo:block>(1) First footnote from the table.</fo:block> | |||
</fo:footnote-body> | |||
</fo:footnote>. | |||
</fo:block> | |||
</fo:table-cell> | |||
</fo:table-row> | |||
<fo:table-row border="inherit"> | |||
<fo:table-cell> | |||
<fo:block>Cell<fo:footnote> | |||
<fo:inline>(3)</fo:inline> | |||
<fo:footnote-body> | |||
<fo:block>(3) Third footnote from the table.</fo:block> | |||
</fo:footnote-body> | |||
</fo:footnote> 2.2</fo:block> | |||
</fo:table-cell> | |||
</fo:table-row> | |||
</fo:table-body> | |||
</fo:table> | |||
</fo:flow> | |||
</fo:page-sequence> | |||
<fo:page-sequence master-reference="simple" font-size="8pt" line-height="10pt"> | |||
<fo:flow flow-name="xsl-region-body"> | |||
<fo:block space-after="159pt">Before the table</fo:block> | |||
<fo:table table-layout="fixed" width="100%"> | |||
<fo:table-column column-width="proportional-column-width(1)"/> | |||
<fo:table-column column-width="proportional-column-width(1)"/> | |||
<fo:table-body border="1pt solid black"> | |||
<fo:table-row border="inherit"> | |||
<fo:table-cell border="inherit" number-rows-spanned="2"> | |||
<fo:block>Cell 1.1</fo:block> | |||
<fo:block>Cell 1.1</fo:block> | |||
<fo:block>Cell 1.1<fo:footnote> | |||
<fo:inline>(2)</fo:inline> | |||
<fo:footnote-body> | |||
<fo:block>(2) Second footnote from the table.</fo:block> | |||
</fo:footnote-body> | |||
</fo:footnote></fo:block> | |||
<fo:block>Cell 1.1</fo:block> | |||
</fo:table-cell> | |||
<fo:table-cell border="inherit"> | |||
<fo:block>Cell 1.2</fo:block> | |||
<fo:block>Cell 1.2<fo:footnote> | |||
<fo:inline>(1)</fo:inline> | |||
<fo:footnote-body> | |||
<fo:block>(1) First footnote from the table.</fo:block> | |||
</fo:footnote-body> | |||
</fo:footnote>. | |||
</fo:block> | |||
</fo:table-cell> | |||
</fo:table-row> | |||
<fo:table-row border="inherit"> | |||
<fo:table-cell> | |||
<fo:block>Cell<fo:footnote> | |||
<fo:inline>(3)</fo:inline> | |||
<fo:footnote-body> | |||
<fo:block>(3) Third footnote from the table.</fo:block> | |||
</fo:footnote-body> | |||
</fo:footnote> 2.2</fo:block> | |||
</fo:table-cell> | |||
</fo:table-row> | |||
</fo:table-body> | |||
</fo:table> | |||
</fo:flow> | |||
</fo:page-sequence> | |||
<fo:page-sequence master-reference="simple" font-size="8pt" line-height="10pt"> | |||
<fo:flow flow-name="xsl-region-body"> | |||
<fo:block space-after="139pt">Before the table</fo:block> | |||
<fo:table table-layout="fixed" width="100%"> | |||
<fo:table-column column-width="proportional-column-width(1)"/> | |||
<fo:table-column column-width="proportional-column-width(1)"/> | |||
<fo:table-body border="1pt solid black"> | |||
<fo:table-row border="inherit"> | |||
<fo:table-cell border="inherit" number-rows-spanned="2"> | |||
<fo:block>Cell 1.1</fo:block> | |||
<fo:block>Cell 1.1</fo:block> | |||
<fo:block>Cell 1.1<fo:footnote> | |||
<fo:inline>(2)</fo:inline> | |||
<fo:footnote-body> | |||
<fo:block>(2) Second footnote from the table.</fo:block> | |||
</fo:footnote-body> | |||
</fo:footnote></fo:block> | |||
<fo:block>Cell 1.1</fo:block> | |||
</fo:table-cell> | |||
<fo:table-cell border="inherit"> | |||
<fo:block>Cell 1.2</fo:block> | |||
<fo:block>Cell 1.2<fo:footnote> | |||
<fo:inline>(1)</fo:inline> | |||
<fo:footnote-body> | |||
<fo:block>(1) First footnote from the table.</fo:block> | |||
</fo:footnote-body> | |||
</fo:footnote>. | |||
</fo:block> | |||
</fo:table-cell> | |||
</fo:table-row> | |||
<fo:table-row border="inherit"> | |||
<fo:table-cell> | |||
<fo:block>Cell<fo:footnote> | |||
<fo:inline>(3)</fo:inline> | |||
<fo:footnote-body> | |||
<fo:block>(3) Third footnote from the table.</fo:block> | |||
</fo:footnote-body> | |||
</fo:footnote> 2.2</fo:block> | |||
</fo:table-cell> | |||
</fo:table-row> | |||
</fo:table-body> | |||
</fo:table> | |||
</fo:flow> | |||
</fo:page-sequence> | |||
</fo:root> | |||
</fo> | |||
<checks> | |||
<eval expected="3" xpath="count(//pageSequence[1]//footnote/block)"/> | |||
<eval expected="(1) First footnote from the table." xpath="//pageSequence[1]//footnote/block[1]"/> | |||
<eval expected="(2) Second footnote from the table." xpath="//pageSequence[1]//footnote/block[2]"/> | |||
<eval expected="(3) Third footnote from the table." xpath="//pageSequence[1]//footnote/block[3]"/> | |||
<eval expected="1" xpath="count(//pageSequence[2]/pageViewport[1]//footnote/block)"/> | |||
<eval expected="(1) First footnote from the table." xpath="//pageSequence[2]/pageViewport[1]//footnote/block[1]"/> | |||
<eval expected="2" xpath="count(//pageSequence[2]/pageViewport[2]//footnote/block)"/> | |||
<eval expected="(2) Second footnote from the table." xpath="//pageSequence[2]/pageViewport[2]//footnote/block[1]"/> | |||
<eval expected="(3) Third footnote from the table." xpath="//pageSequence[2]/pageViewport[2]//footnote/block[2]"/> | |||
<eval expected="2" xpath="count(//pageSequence[3]/pageViewport[1]//footnote/block)"/> | |||
<eval expected="(1) First footnote from the table." xpath="//pageSequence[3]/pageViewport[1]//footnote/block[1]"/> | |||
<eval expected="(2) Second footnote from the table." xpath="//pageSequence[3]/pageViewport[1]//footnote/block[2]"/> | |||
<eval expected="1" xpath="count(//pageSequence[3]/pageViewport[2]//footnote/block)"/> | |||
<eval expected="(3) Third footnote from the table." xpath="//pageSequence[3]/pageViewport[2]//footnote/block[1]"/> | |||
</checks> | |||
</testcase> |
@@ -0,0 +1,79 @@ | |||
<?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 for white-space related bugs as reported in Bugzilla 45097. | |||
</p> | |||
</info> | |||
<fo> | |||
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> | |||
<fo:layout-master-set> | |||
<fo:simple-page-master master-name="all-pages" margin-top="0.5in" margin-bottom="0.5in" margin-left="0.38in" margin-right="0.38in" page-width="8.5in" page-height="11in"> | |||
<fo:region-body margin-top="0.5in + 1mm" margin-bottom="0.5in + 1mm"/> | |||
<fo:region-before extent="0.5in"/> | |||
<fo:region-after extent="0.5in"/> | |||
</fo:simple-page-master> | |||
</fo:layout-master-set> | |||
<fo:page-sequence master-reference="all-pages"> | |||
<fo:static-content flow-name="xsl-region-before"><fo:block/></fo:static-content> | |||
<fo:static-content flow-name="xsl-region-after"><fo:block/></fo:static-content> | |||
<fo:flow flow-name="xsl-region-body"> | |||
<fo:block> | |||
<fo:block><fo:leader leader-pattern="space"/></fo:block> | |||
<fo:block text-decoration="underline">Example 1: white-space-collapse="false" linefeed-treatment="preserve" white-space-treatment="preserve"</fo:block> | |||
<fo:block font-family="Courier" | |||
white-space-collapse="false" | |||
linefeed-treatment="preserve" | |||
white-space-treatment="preserve"><fo:block><fo:inline id="inline-1a" border="1mm solid red"> *** </fo:inline></fo:block><fo:block><fo:inline border="1mm solid red">*************</fo:inline></fo:block><fo:block><fo:inline id="inline-1b" border="1mm solid red"> *** </fo:inline></fo:block></fo:block> | |||
<fo:block><fo:leader leader-pattern="space"/></fo:block> | |||
<fo:block text-decoration="underline">Example 2: white-space-collapse="false" linefeed-treatment="preserve" w/ inlines</fo:block> | |||
<fo:block font-family="Courier" | |||
white-space-collapse="false" | |||
linefeed-treatment="preserve"><fo:block><fo:inline id="inline-2a" border="1mm solid red"> *** </fo:inline></fo:block><fo:block><fo:inline border="1mm solid red">*************</fo:inline></fo:block><fo:block><fo:inline id="inline-2b" border="1mm solid red"> *** </fo:inline></fo:block></fo:block> | |||
</fo:block> | |||
<fo:block><fo:leader leader-pattern="space"/></fo:block> | |||
<fo:block text-decoration="underline">Example 1: white-space-collapse="false" linefeed-treatment="preserve" white-space-treatment="preserve"</fo:block> | |||
<fo:block font-family="Courier" | |||
white-space-collapse="false" | |||
linefeed-treatment="preserve" | |||
white-space-treatment="preserve"><fo:block><fo:inline id="inline-3a" border="1mm solid red"> *** </fo:inline></fo:block><fo:block><fo:inline border="1mm solid red">*************</fo:inline></fo:block><fo:block><fo:inline id="inline-3b" border="1mm solid red"> *** </fo:inline></fo:block></fo:block> | |||
<fo:block><fo:leader leader-pattern="space"/></fo:block> | |||
<fo:block text-decoration="underline">Example 2: white-space-collapse="false" linefeed-treatment="preserve" w/ inlines</fo:block> | |||
<fo:block font-family="Courier" | |||
white-space-collapse="false" | |||
linefeed-treatment="preserve"><fo:block><fo:inline id="inline-4a" border="1mm solid red"> *** </fo:inline></fo:block><fo:block><fo:inline border="1mm solid red">*************</fo:inline></fo:block><fo:block><fo:inline id="inline-4b" border="1mm solid red"> *** </fo:inline></fo:block></fo:block> | |||
</fo:flow> | |||
</fo:page-sequence> | |||
</fo:root> | |||
</fo> | |||
<checks> | |||
<eval expected="10" xpath="count(//inlineparent[@prod-id='inline-1a']//space)" /> | |||
<eval expected="10" xpath="count(//inlineparent[@prod-id='inline-1b']//space)" /> | |||
<eval expected="0" xpath="count(//inlineparent[@prod-id='inline-2a']//space)" /> | |||
<eval expected="0" xpath="count(//inlineparent[@prod-id='inline-2b']//space)" /> | |||
<eval expected="10" xpath="count(//inlineparent[@prod-id='inline-3a']//space)" /> | |||
<eval expected="10" xpath="count(//inlineparent[@prod-id='inline-3b']//space)" /> | |||
<eval expected="0" xpath="count(//inlineparent[@prod-id='inline-4a']//space)" /> | |||
<eval expected="0" xpath="count(//inlineparent[@prod-id='inline-4b']//space)" /> | |||
</checks> | |||
</testcase> |