Patch provided by Adrian Cumiskey (bugzilla #43156). git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/fop-0_94@567294 13f79535-47bb-0310-9956-ffa450edef68tags/fop-0_94^2
import org.apache.fop.fo.properties.BoxPropShorthandParser; | import org.apache.fop.fo.properties.BoxPropShorthandParser; | ||||
import org.apache.fop.fo.properties.CharacterProperty; | import org.apache.fop.fo.properties.CharacterProperty; | ||||
import org.apache.fop.fo.properties.ColorProperty; | import org.apache.fop.fo.properties.ColorProperty; | ||||
import org.apache.fop.fo.flow.TableFObj.ColumnNumberPropertyMaker; | |||||
import org.apache.fop.fo.properties.ColumnNumberPropertyMaker; | |||||
import org.apache.fop.fo.properties.CondLengthProperty; | import org.apache.fop.fo.properties.CondLengthProperty; | ||||
import org.apache.fop.fo.properties.CorrespondingPropertyMaker; | import org.apache.fop.fo.properties.CorrespondingPropertyMaker; | ||||
import org.apache.fop.fo.properties.DimensionPropertyMaker; | import org.apache.fop.fo.properties.DimensionPropertyMaker; |
*/ | */ | ||||
public boolean hasNext() { | public boolean hasNext() { | ||||
while (curCharIter != null) { | while (curCharIter != null) { | ||||
if (curCharIter.hasNext() == false) { | |||||
if (!curCharIter.hasNext()) { | |||||
getNextCharIter(); | getNextCharIter(); | ||||
} else { | } else { | ||||
return true; | return true; | ||||
} | } | ||||
/** | /** | ||||
* @see org.apache.fop.fo.CharIterator#nextChar() | |||||
* {@inheritDoc} | |||||
*/ | */ | ||||
public char nextChar() throws NoSuchElementException { | public char nextChar() throws NoSuchElementException { | ||||
if (curCharIter != null) { | if (curCharIter != null) { |
package org.apache.fop.fo.flow; | package org.apache.fop.fo.flow; | ||||
import java.awt.Color; | import java.awt.Color; | ||||
import java.util.NoSuchElementException; | |||||
import org.apache.fop.apps.FOPException; | import org.apache.fop.apps.FOPException; | ||||
import org.apache.fop.datatypes.Length; | import org.apache.fop.datatypes.Length; | ||||
import org.apache.fop.fo.FObj; | import org.apache.fop.fo.FObj; | ||||
import org.apache.fop.fo.PropertyList; | import org.apache.fop.fo.PropertyList; | ||||
import org.apache.fop.fo.ValidationException; | import org.apache.fop.fo.ValidationException; | ||||
import org.apache.fop.fo.properties.CommonAural; | |||||
import org.apache.fop.fo.properties.CommonBorderPaddingBackground; | import org.apache.fop.fo.properties.CommonBorderPaddingBackground; | ||||
import org.apache.fop.fo.properties.CommonFont; | import org.apache.fop.fo.properties.CommonFont; | ||||
import org.apache.fop.fo.properties.CommonHyphenation; | import org.apache.fop.fo.properties.CommonHyphenation; | ||||
import org.apache.fop.fo.properties.CommonMarginInline; | |||||
import org.apache.fop.fo.properties.CommonRelativePosition; | |||||
import org.apache.fop.fo.properties.CommonTextDecoration; | import org.apache.fop.fo.properties.CommonTextDecoration; | ||||
import org.apache.fop.fo.properties.KeepProperty; | |||||
import org.apache.fop.fo.properties.Property; | import org.apache.fop.fo.properties.Property; | ||||
import org.apache.fop.fo.properties.SpaceProperty; | import org.apache.fop.fo.properties.SpaceProperty; | ||||
import org.apache.fop.util.CharUtilities; | |||||
import org.xml.sax.Locator; | import org.xml.sax.Locator; | ||||
/** | /** | ||||
private Length alignmentAdjust; | private Length alignmentAdjust; | ||||
private int alignmentBaseline; | private int alignmentBaseline; | ||||
private Length baselineShift; | private Length baselineShift; | ||||
private char character; | |||||
/** Holds the character value */ | |||||
protected char character; | |||||
private Color color; | private Color color; | ||||
private int dominantBaseline; | private int dominantBaseline; | ||||
// private ToBeImplementedProperty glyphOrientationHorizontal; | // private ToBeImplementedProperty glyphOrientationHorizontal; | ||||
} | } | ||||
/** | /** | ||||
* @see org.apache.fop.fo.FObj#bind(PropertyList) | |||||
* {@inheritDoc} | |||||
*/ | */ | ||||
public void bind(PropertyList pList) throws FOPException { | public void bind(PropertyList pList) throws FOPException { | ||||
super.bind(pList); | super.bind(pList); | ||||
} | } | ||||
/** | /** | ||||
* @see org.apache.fop.fo.FONode#startOfNode | |||||
* {@inheritDoc} | |||||
*/ | */ | ||||
protected void startOfNode() throws FOPException { | protected void startOfNode() throws FOPException { | ||||
super.startOfNode(); | super.startOfNode(); | ||||
} | } | ||||
/** | /** | ||||
* @see org.apache.fop.fo.FONode#validateChildNode(Locator, String, String) | |||||
* XSL Content Model: empty | |||||
* {@inheritDoc} | |||||
*/ | */ | ||||
protected void validateChildNode(Locator loc, String nsURI, String localName) | protected void validateChildNode(Locator loc, String nsURI, String localName) | ||||
throws ValidationException { | throws ValidationException { | ||||
} | } | ||||
/** | /** | ||||
* @see org.apache.fop.fo.FObj#charIterator | |||||
* {@inheritDoc} | |||||
*/ | */ | ||||
public CharIterator charIterator() { | public CharIterator charIterator() { | ||||
return new FOCharIterator(this); | return new FOCharIterator(this); | ||||
return wordSpacing; | return wordSpacing; | ||||
} | } | ||||
/** @see org.apache.fop.fo.FONode#getLocalName() */ | |||||
/** | |||||
* {@inheritDoc} | |||||
*/ | |||||
public String getLocalName() { | public String getLocalName() { | ||||
return "character"; | return "character"; | ||||
} | } | ||||
/** | /** | ||||
* @see org.apache.fop.fo.FObj#getNameId() | |||||
* {@inheritDoc} | |||||
*/ | */ | ||||
public int getNameId() { | public int getNameId() { | ||||
return FO_CHARACTER; | return FO_CHARACTER; | ||||
} | } | ||||
private class FOCharIterator extends CharIterator { | |||||
private boolean bFirst = true; | |||||
private Character foChar; | |||||
FOCharIterator(Character foChar) { | |||||
this.foChar = foChar; | |||||
} | |||||
public boolean hasNext() { | |||||
return bFirst; | |||||
} | |||||
public char nextChar() { | |||||
if (bFirst) { | |||||
bFirst = false; | |||||
return foChar.character; | |||||
} else { | |||||
throw new NoSuchElementException(); | |||||
} | |||||
} | |||||
public void remove() { | |||||
foChar.parent.removeChild(foChar); | |||||
} | |||||
public void replaceChar(char c) { | |||||
foChar.character = c; | |||||
} | |||||
} | |||||
} | } |
/* | |||||
* 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.fo.flow; | |||||
import java.util.NoSuchElementException; | |||||
import org.apache.fop.fo.CharIterator; | |||||
/** | |||||
* Used by the RecursiveCharIterator to iterate over a Character | |||||
*/ | |||||
public class FOCharIterator extends CharIterator { | |||||
private boolean bFirst = true; | |||||
private Character foChar; | |||||
/** | |||||
* Main constructor | |||||
* @param foChar the FOCharacter | |||||
*/ | |||||
protected FOCharIterator(Character foChar) { | |||||
this.foChar = foChar; | |||||
} | |||||
/** | |||||
* @return true if this iterator has another character available | |||||
*/ | |||||
public boolean hasNext() { | |||||
return bFirst; | |||||
} | |||||
/** | |||||
* @return the next character | |||||
*/ | |||||
public char nextChar() { | |||||
if (bFirst) { | |||||
bFirst = false; | |||||
return foChar.character; | |||||
} else { | |||||
throw new NoSuchElementException(); | |||||
} | |||||
} | |||||
/** | |||||
* Removes the child from the parent | |||||
*/ | |||||
public void remove() { | |||||
foChar.getParent().removeChild(foChar); | |||||
} | |||||
/** | |||||
* Replaces the character with another one | |||||
* @param c the replacement character | |||||
*/ | |||||
public void replaceChar(char c) { | |||||
foChar.character = c; | |||||
} | |||||
} |
// Java | // Java | ||||
import java.util.BitSet; | import java.util.BitSet; | ||||
import java.util.Iterator; | |||||
import java.util.List; | import java.util.List; | ||||
import java.util.ListIterator; | |||||
import org.xml.sax.Attributes; | import org.xml.sax.Attributes; | ||||
import org.xml.sax.Locator; | import org.xml.sax.Locator; | ||||
import org.apache.fop.fo.FONode; | import org.apache.fop.fo.FONode; | ||||
import org.apache.fop.fo.FObj; | import org.apache.fop.fo.FObj; | ||||
import org.apache.fop.fo.PropertyList; | import org.apache.fop.fo.PropertyList; | ||||
import org.apache.fop.fo.StaticPropertyList; | |||||
import org.apache.fop.fo.ValidationException; | import org.apache.fop.fo.ValidationException; | ||||
import org.apache.fop.fo.flow.TableFObj.PendingSpan; | |||||
import org.apache.fop.fo.properties.CommonAccessibility; | |||||
import org.apache.fop.fo.properties.CommonAural; | |||||
import org.apache.fop.fo.properties.CommonBorderPaddingBackground; | import org.apache.fop.fo.properties.CommonBorderPaddingBackground; | ||||
import org.apache.fop.fo.properties.CommonRelativePosition; | |||||
/** | /** | ||||
* Class modelling the fo:table-body object. | * Class modelling the fo:table-body object. | ||||
* | * | ||||
* @return the next column number to use | * @return the next column number to use | ||||
*/ | */ | ||||
protected int getCurrentColumnIndex() { | |||||
public int getCurrentColumnIndex() { | |||||
return columnIndex; | return columnIndex; | ||||
} | } | ||||
* | * | ||||
* @param newIndex the new column index | * @param newIndex the new column index | ||||
*/ | */ | ||||
protected void setCurrentColumnIndex(int newIndex) { | |||||
public void setCurrentColumnIndex(int newIndex) { | |||||
columnIndex = newIndex; | columnIndex = newIndex; | ||||
} | } | ||||
* Resets the current column index for the TableBody | * Resets the current column index for the TableBody | ||||
* | * | ||||
*/ | */ | ||||
protected void resetColumnIndex() { | |||||
public void resetColumnIndex() { | |||||
columnIndex = 1; | columnIndex = 1; | ||||
for (int i = usedColumnIndices.length(); --i >= 0;) { | for (int i = usedColumnIndices.length(); --i >= 0;) { | ||||
usedColumnIndices.clear(i); | usedColumnIndices.clear(i); | ||||
* b) there is no previous cell (implicit | * b) there is no previous cell (implicit | ||||
* start of row) | * start of row) | ||||
*/ | */ | ||||
protected boolean previousCellEndedRow() { | |||||
public boolean previousCellEndedRow() { | |||||
if (firstChild != null) { | if (firstChild != null) { | ||||
FONode prevNode = getChildNodes().lastNode(); | FONode prevNode = getChildNodes().lastNode(); | ||||
if (prevNode.getNameId() == FO_TABLE_CELL) { | if (prevNode.getNameId() == FO_TABLE_CELL) { |
* | * | ||||
* @return the next column number to use | * @return the next column number to use | ||||
*/ | */ | ||||
protected int getCurrentColumnIndex() { | |||||
public int getCurrentColumnIndex() { | |||||
return 0; | return 0; | ||||
} | } | ||||
* | * | ||||
* @param newIndex new value for column index | * @param newIndex new value for column index | ||||
*/ | */ | ||||
protected void setCurrentColumnIndex(int newIndex) { | |||||
public void setCurrentColumnIndex(int newIndex) { | |||||
//do nothing by default | //do nothing by default | ||||
} | } | ||||
*/ | */ | ||||
protected void flagColumnIndices(int start, int end) { | protected void flagColumnIndices(int start, int end) { | ||||
//nop | //nop | ||||
} | |||||
/** | |||||
* PropertyMaker subclass for the column-number property | |||||
* | |||||
*/ | |||||
public static class ColumnNumberPropertyMaker extends NumberProperty.Maker { | |||||
/** | |||||
* Constructor | |||||
* @param propId the id of the property for which the maker should | |||||
* be created | |||||
*/ | |||||
public ColumnNumberPropertyMaker(int propId) { | |||||
super(propId); | |||||
} | |||||
/** | |||||
* @see PropertyMaker#make(PropertyList) | |||||
*/ | |||||
public Property make(PropertyList propertyList) | |||||
throws PropertyException { | |||||
FObj fo = propertyList.getFObj(); | |||||
if (fo.getNameId() == Constants.FO_TABLE_CELL | |||||
|| fo.getNameId() == Constants.FO_TABLE_COLUMN) { | |||||
if (fo.getNameId() == Constants.FO_TABLE_CELL | |||||
&& fo.getParent().getNameId() != Constants.FO_TABLE_ROW | |||||
&& (propertyList.get(Constants.PR_STARTS_ROW).getEnum() | |||||
== Constants.EN_TRUE)) { | |||||
TableBody parent = (TableBody) fo.getParent(); | |||||
if (!parent.previousCellEndedRow()) { | |||||
parent.resetColumnIndex(); | |||||
} | |||||
} | |||||
} | |||||
return NumberProperty.getInstance( | |||||
((TableFObj) fo.getParent()).getCurrentColumnIndex()); | |||||
} | |||||
/** | |||||
* Check the value of the column-number property. | |||||
* Return the parent's column index (initial value) in case | |||||
* of a negative or zero value | |||||
* | |||||
* @see org.apache.fop.fo.properties.PropertyMaker#make( | |||||
* org.apache.fop.fo.PropertyList, | |||||
* java.lang.String, | |||||
* org.apache.fop.fo.FObj) | |||||
*/ | |||||
public Property make(PropertyList propertyList, String value, FObj fo) | |||||
throws PropertyException { | |||||
Property p = super.make(propertyList, value, fo); | |||||
TableFObj parent = (TableFObj) propertyList.getParentFObj(); | |||||
int columnIndex = p.getNumeric().getValue(); | |||||
if (columnIndex <= 0) { | |||||
log.warn("Specified negative or zero value for " | |||||
+ "column-number on " + fo.getName() + ": " | |||||
+ columnIndex + " forced to " | |||||
+ parent.getCurrentColumnIndex()); | |||||
return NumberProperty.getInstance(parent.getCurrentColumnIndex()); | |||||
} else { | |||||
double tmpIndex = p.getNumeric().getNumericValue(); | |||||
if (tmpIndex - columnIndex > 0.0) { | |||||
columnIndex = (int) Math.round(tmpIndex); | |||||
log.warn("Rounding specified column-number of " | |||||
+ tmpIndex + " to " + columnIndex); | |||||
p = NumberProperty.getInstance(columnIndex); | |||||
} | |||||
} | |||||
parent.setCurrentColumnIndex(columnIndex); | |||||
int colSpan = propertyList.get(Constants.PR_NUMBER_COLUMNS_SPANNED) | |||||
.getNumeric().getValue(); | |||||
int i = -1; | |||||
while (++i < colSpan) { | |||||
if (parent.isColumnNumberUsed(columnIndex + i)) { | |||||
/* if column-number is already in use by another | |||||
* cell/column => error! | |||||
*/ | |||||
StringBuffer errorMessage = new StringBuffer(); | |||||
errorMessage.append(fo.getName() + " overlaps in column ") | |||||
.append(columnIndex + i); | |||||
org.xml.sax.Locator loc = fo.getLocator(); | |||||
if (loc != null && loc.getLineNumber() != -1) { | |||||
errorMessage.append(" (line #") | |||||
.append(loc.getLineNumber()).append(", column #") | |||||
.append(loc.getColumnNumber()).append(")"); | |||||
} | |||||
throw new PropertyException(errorMessage.toString()); | |||||
} | |||||
} | |||||
return p; | |||||
} | |||||
} | |||||
} | |||||
} | } |
/* | |||||
* 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.fo.properties; | |||||
import org.apache.commons.logging.Log; | |||||
import org.apache.commons.logging.LogFactory; | |||||
import org.apache.fop.fo.Constants; | |||||
import org.apache.fop.fo.FObj; | |||||
import org.apache.fop.fo.PropertyList; | |||||
import org.apache.fop.fo.expr.PropertyException; | |||||
import org.apache.fop.fo.flow.TableBody; | |||||
import org.apache.fop.fo.flow.TableFObj; | |||||
/** | |||||
* PropertyMaker subclass for the column-number property | |||||
* | |||||
*/ | |||||
public class ColumnNumberPropertyMaker extends NumberProperty.Maker { | |||||
/** | |||||
* Constructor | |||||
* @param propId the id of the property for which the maker should | |||||
* be created | |||||
*/ | |||||
public ColumnNumberPropertyMaker(int propId) { | |||||
super(propId); | |||||
} | |||||
/** | |||||
* {@inheritDoc} | |||||
*/ | |||||
public Property make(PropertyList propertyList) | |||||
throws PropertyException { | |||||
FObj fo = propertyList.getFObj(); | |||||
if (fo.getNameId() == Constants.FO_TABLE_CELL | |||||
|| fo.getNameId() == Constants.FO_TABLE_COLUMN) { | |||||
if (fo.getNameId() == Constants.FO_TABLE_CELL | |||||
&& fo.getParent().getNameId() != Constants.FO_TABLE_ROW | |||||
&& (propertyList.get(Constants.PR_STARTS_ROW).getEnum() | |||||
== Constants.EN_TRUE)) { | |||||
TableBody parent = (TableBody) fo.getParent(); | |||||
if (!parent.previousCellEndedRow()) { | |||||
parent.resetColumnIndex(); | |||||
} | |||||
} | |||||
} | |||||
return NumberProperty.getInstance( | |||||
((TableFObj) fo.getParent()).getCurrentColumnIndex()); | |||||
} | |||||
/** | |||||
* Check the value of the column-number property. | |||||
* Return the parent's column index (initial value) in case | |||||
* of a negative or zero value | |||||
* | |||||
* {@inheritDoc} | |||||
*/ | |||||
public Property make(PropertyList propertyList, String value, FObj fo) | |||||
throws PropertyException { | |||||
Property p = super.make(propertyList, value, fo); | |||||
TableFObj parent = (TableFObj) propertyList.getParentFObj(); | |||||
int columnIndex = p.getNumeric().getValue(); | |||||
if (columnIndex <= 0) { | |||||
Log log = LogFactory.getLog(TableFObj.class); | |||||
log.warn("Specified negative or zero value for " | |||||
+ "column-number on " + fo.getName() + ": " | |||||
+ columnIndex + " forced to " | |||||
+ parent.getCurrentColumnIndex()); | |||||
return NumberProperty.getInstance(parent.getCurrentColumnIndex()); | |||||
} else { | |||||
double tmpIndex = p.getNumeric().getNumericValue(); | |||||
if (tmpIndex - columnIndex > 0.0) { | |||||
columnIndex = (int) Math.round(tmpIndex); | |||||
Log log = LogFactory.getLog(TableFObj.class); | |||||
log.warn("Rounding specified column-number of " | |||||
+ tmpIndex + " to " + columnIndex); | |||||
p = NumberProperty.getInstance(columnIndex); | |||||
} | |||||
} | |||||
parent.setCurrentColumnIndex(columnIndex); | |||||
int colSpan = propertyList.get(Constants.PR_NUMBER_COLUMNS_SPANNED) | |||||
.getNumeric().getValue(); | |||||
int i = -1; | |||||
while (++i < colSpan) { | |||||
if (parent.isColumnNumberUsed(columnIndex + i)) { | |||||
/* if column-number is already in use by another | |||||
* cell/column => error! | |||||
*/ | |||||
StringBuffer errorMessage = new StringBuffer(); | |||||
errorMessage.append(fo.getName() + " overlaps in column ") | |||||
.append(columnIndex + i); | |||||
org.xml.sax.Locator loc = fo.getLocator(); | |||||
if (loc != null && loc.getLineNumber() != -1) { | |||||
errorMessage.append(" (line #") | |||||
.append(loc.getLineNumber()).append(", column #") | |||||
.append(loc.getColumnNumber()).append(")"); | |||||
} | |||||
throw new PropertyException(errorMessage.toString()); | |||||
} | |||||
} | |||||
return p; | |||||
} | |||||
} | |||||