Bugfix: page-number-citations are now properly resolved. The new method in AreaTreeHandler may not be optimal, but I haven't found a better way, yet. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@198642 13f79535-47bb-0310-9956-ffa450edef68tags/fop-0_90-alpha1
@@ -160,19 +160,45 @@ public class AreaTreeHandler extends FOEventHandler { | |||
* See if this ID is in the unresolved idref list, if so | |||
* resolve Resolvable objects tied to it. | |||
*/ | |||
Set todo = (Set) unresolvedIDRefs.get(id); | |||
if (todo != null) { | |||
for (Iterator iter = todo.iterator(); iter.hasNext();) { | |||
Resolvable res = (Resolvable) iter.next(); | |||
res.resolveIDRef(id, pvList); | |||
} | |||
unresolvedIDRefs.remove(id); | |||
} | |||
tryIDResolution(id, pv, pvList); | |||
} else { | |||
pvList.add(pv); | |||
} | |||
} | |||
/** | |||
* Tries to resolve all unresolved ID references on the given page. | |||
* @param id ID to resolve | |||
* @param pv page viewport whose ID refs to resolve | |||
* @param List of PageViewports | |||
*/ | |||
private void tryIDResolution(String id, PageViewport pv, List pvList) { | |||
Set todo = (Set) unresolvedIDRefs.get(id); | |||
if (todo != null) { | |||
for (Iterator iter = todo.iterator(); iter.hasNext();) { | |||
Resolvable res = (Resolvable) iter.next(); | |||
res.resolveIDRef(id, pvList); | |||
} | |||
unresolvedIDRefs.remove(id); | |||
} | |||
} | |||
/** | |||
* Tries to resolve all unresolved ID references on the given page. | |||
* @param pv page viewport whose ID refs to resolve | |||
*/ | |||
public void tryIDResolution(PageViewport pv) { | |||
String[] ids = pv.getIDRefs(); | |||
if (ids != null) { | |||
for (int i = 0; i < ids.length; i++) { | |||
List pvList = (List) idLocations.get(ids[i]); | |||
if (pvList != null) { | |||
tryIDResolution(ids[i], pv, pvList); | |||
} | |||
} | |||
} | |||
} | |||
/** | |||
* Get the list of page viewports that have an area with a given id. | |||
* @param id the id to lookup |
@@ -69,23 +69,24 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager { | |||
* inline area. | |||
* This is used for vertical alignment. | |||
* Subclasses should override this if necessary. | |||
* @param area the inline area to be updated | |||
* @param context the layout context used for adding the area | |||
*/ | |||
protected void offsetArea(LayoutContext context) { | |||
int bpd = curArea.getBPD(); | |||
protected void offsetArea(InlineArea area, LayoutContext context) { | |||
int bpd = area.getBPD(); | |||
switch (verticalAlignment) { | |||
case EN_MIDDLE: | |||
curArea.setOffset(context.getMiddleBaseline() + fs.getXHeight() / 2); | |||
area.setOffset(context.getMiddleBaseline() + fs.getXHeight() / 2); | |||
break; | |||
case EN_TOP: | |||
curArea.setOffset(fs.getAscender()); | |||
area.setOffset(fs.getAscender()); | |||
break; | |||
case EN_BOTTOM: | |||
curArea.setOffset(context.getLineHeight() - bpd + fs.getAscender()); | |||
area.setOffset(context.getLineHeight() - bpd + fs.getAscender()); | |||
break; | |||
case EN_BASELINE: | |||
default: | |||
curArea.setOffset(context.getBaseline()); | |||
area.setOffset(context.getBaseline()); | |||
break; | |||
} | |||
} |
@@ -212,11 +212,6 @@ public class ContentLayoutManager implements InlineLevelLayoutManager { | |||
return false; | |||
} | |||
/** @see org.apache.fop.layoutmgr.LayoutManager */ | |||
public BreakPoss getNextBreakPoss(LayoutContext context) { | |||
return null; | |||
} | |||
/** @see org.apache.fop.layoutmgr.LayoutManager */ | |||
public boolean isFinished() { | |||
return false; |
@@ -146,42 +146,42 @@ public class LeaderLayoutManager extends LeafNodeLayoutManager { | |||
return leaderArea; | |||
} | |||
protected void offsetArea(LayoutContext context) { | |||
protected void offsetArea(InlineArea area, LayoutContext context) { | |||
int pattern = fobj.getLeaderPattern(); | |||
int bpd = curArea.getBPD(); | |||
int bpd = area.getBPD(); | |||
switch (pattern) { | |||
case EN_RULE: | |||
switch (verticalAlignment) { | |||
case EN_TOP: | |||
curArea.setOffset(0); | |||
area.setOffset(0); | |||
break; | |||
case EN_MIDDLE: | |||
curArea.setOffset(context.getMiddleBaseline() - bpd / 2); | |||
area.setOffset(context.getMiddleBaseline() - bpd / 2); | |||
break; | |||
case EN_BOTTOM: | |||
curArea.setOffset(context.getLineHeight() - bpd); | |||
area.setOffset(context.getLineHeight() - bpd); | |||
break; | |||
case EN_BASELINE: // fall through | |||
default: | |||
curArea.setOffset(context.getBaseline() - bpd); | |||
area.setOffset(context.getBaseline() - bpd); | |||
break; | |||
} | |||
break; | |||
case EN_DOTS: | |||
switch (verticalAlignment) { | |||
case EN_TOP: | |||
curArea.setOffset(0); | |||
area.setOffset(0); | |||
break; | |||
case EN_MIDDLE: | |||
curArea.setOffset(context.getMiddleBaseline()); | |||
area.setOffset(context.getMiddleBaseline()); | |||
break; | |||
case EN_BOTTOM: | |||
curArea.setOffset(context.getLineHeight() - bpd + font.getAscender()); | |||
area.setOffset(context.getLineHeight() - bpd + font.getAscender()); | |||
break; | |||
case EN_BASELINE: // fall through | |||
default: | |||
curArea.setOffset(context.getBaseline()); | |||
area.setOffset(context.getBaseline()); | |||
break; | |||
} | |||
break; | |||
@@ -191,17 +191,17 @@ public class LeaderLayoutManager extends LeafNodeLayoutManager { | |||
case EN_USECONTENT: | |||
switch (verticalAlignment) { | |||
case EN_TOP: | |||
curArea.setOffset(0); | |||
area.setOffset(0); | |||
break; | |||
case EN_MIDDLE: | |||
curArea.setOffset(context.getMiddleBaseline()); | |||
area.setOffset(context.getMiddleBaseline()); | |||
break; | |||
case EN_BOTTOM: | |||
curArea.setOffset(context.getLineHeight() - bpd); | |||
area.setOffset(context.getLineHeight() - bpd); | |||
break; | |||
case EN_BASELINE: // fall through | |||
default: | |||
curArea.setOffset(context.getBaseline()); | |||
area.setOffset(context.getBaseline()); | |||
break; | |||
} | |||
break; | |||
@@ -215,12 +215,12 @@ public class LeaderLayoutManager extends LeafNodeLayoutManager { | |||
} else { | |||
addId(); | |||
widthAdjustArea(context); | |||
widthAdjustArea(curArea, context); | |||
// add content areas | |||
KnuthPossPosIter contentIter = new KnuthPossPosIter(contentList, 0, contentList.size()); | |||
clm.addAreas(contentIter, context); | |||
offsetArea(context); | |||
offsetArea(curArea, context); | |||
parentLM.addChildArea(curArea); | |||
@@ -33,7 +33,7 @@ import java.util.LinkedList; | |||
* This class can be extended to handle the creation and adding of the | |||
* inline area. | |||
*/ | |||
public class LeafNodeLayoutManager extends AbstractLayoutManager | |||
public abstract class LeafNodeLayoutManager extends AbstractLayoutManager | |||
implements InlineLevelLayoutManager { | |||
/** | |||
* The inline area that this leafnode will add. | |||
@@ -172,17 +172,26 @@ public class LeafNodeLayoutManager extends AbstractLayoutManager | |||
public void addAreas(PositionIterator posIter, LayoutContext context) { | |||
addId(); | |||
offsetArea(context); | |||
widthAdjustArea(context); | |||
parentLM.addChildArea(curArea); | |||
InlineArea area = getEffectiveArea(); | |||
offsetArea(area, context); | |||
widthAdjustArea(area, context); | |||
parentLM.addChildArea(area); | |||
while (posIter.hasNext()) { | |||
posIter.next(); | |||
} | |||
} | |||
/** | |||
* @return the effective area to be added to the area tree. Normally, this is simply "curArea" | |||
* but in the case of page-number(-citation) curArea is cloned, updated and returned. | |||
*/ | |||
protected InlineArea getEffectiveArea() { | |||
return curArea; | |||
} | |||
protected void addId() { | |||
// Do nothing here, overriden in subclasses that has a 'id' property. | |||
// Do nothing here, overriden in subclasses that have an 'id' property. | |||
} | |||
/** | |||
@@ -191,23 +200,24 @@ public class LeafNodeLayoutManager extends AbstractLayoutManager | |||
* inline area. | |||
* This is used for vertical alignment. | |||
* Subclasses should override this if necessary. | |||
* @param area the inline area to be updated | |||
* @param context the layout context used for adding the area | |||
*/ | |||
protected void offsetArea(LayoutContext context) { | |||
int bpd = curArea.getBPD(); | |||
protected void offsetArea(InlineArea area, LayoutContext context) { | |||
int bpd = area.getBPD(); | |||
switch (verticalAlignment) { | |||
case EN_MIDDLE: | |||
curArea.setOffset(context.getMiddleBaseline() - bpd / 2); | |||
area.setOffset(context.getMiddleBaseline() - bpd / 2); | |||
break; | |||
case EN_TOP: | |||
curArea.setOffset(context.getTopBaseline()); | |||
area.setOffset(context.getTopBaseline()); | |||
break; | |||
case EN_BOTTOM: | |||
curArea.setOffset(context.getBottomBaseline() - bpd); | |||
area.setOffset(context.getBottomBaseline() - bpd); | |||
break; | |||
case EN_BASELINE: | |||
default: | |||
curArea.setOffset(context.getBaseline() - bpd); | |||
area.setOffset(context.getBaseline() - bpd); | |||
break; | |||
} | |||
} | |||
@@ -216,9 +226,10 @@ public class LeafNodeLayoutManager extends AbstractLayoutManager | |||
* Adjust the width of the area when adding. | |||
* This uses the min/opt/max values to adjust the with | |||
* of the inline area by a percentage. | |||
* @param area the inline area to be updated | |||
* @param context the layout context for adding this area | |||
*/ | |||
protected void widthAdjustArea(LayoutContext context) { | |||
protected void widthAdjustArea(InlineArea area, LayoutContext context) { | |||
double dAdjust = context.getIPDAdjust(); | |||
int width = areaInfo.ipdArea.opt; | |||
if (dAdjust < 0) { | |||
@@ -228,7 +239,7 @@ public class LeafNodeLayoutManager extends AbstractLayoutManager | |||
width = (int) (width + dAdjust * (areaInfo.ipdArea.max | |||
- areaInfo.ipdArea.opt)); | |||
} | |||
curArea.setIPD(width); | |||
area.setIPD(width); | |||
} | |||
/** |
@@ -33,7 +33,7 @@ import org.apache.fop.fonts.Font; | |||
public class PageNumberCitationLayoutManager extends LeafNodeLayoutManager { | |||
private PageNumberCitation fobj; | |||
Font font = null; | |||
private Font font = null; | |||
// whether the page referred to by the citation has been resolved yet | |||
private boolean resolved = false; | |||
@@ -62,8 +62,8 @@ public class PageNumberCitationLayoutManager extends LeafNodeLayoutManager { | |||
} | |||
} | |||
protected void offsetArea(LayoutContext context) { | |||
curArea.setOffset(context.getBaseline()); | |||
protected void offsetArea(InlineArea area, LayoutContext context) { | |||
area.setOffset(context.getBaseline()); | |||
} | |||
/** | |||
@@ -81,12 +81,7 @@ public class PageNumberCitationLayoutManager extends LeafNodeLayoutManager { | |||
int width = getStringWidth(str); | |||
text.setTextArea(str); | |||
inline.setIPD(width); | |||
inline.setBPD(font.getAscender() - font.getDescender()); | |||
inline.setOffset(font.getAscender()); | |||
inline.addTrait(Trait.FONT_NAME, font.getFontName()); | |||
inline.addTrait(Trait.FONT_SIZE, | |||
new Integer(font.getFontSize())); | |||
resolved = true; | |||
} else { | |||
resolved = false; | |||
@@ -94,12 +89,12 @@ public class PageNumberCitationLayoutManager extends LeafNodeLayoutManager { | |||
String str = "MMM"; // reserve three spaces for page number | |||
int width = getStringWidth(str); | |||
inline.setIPD(width); | |||
inline.setBPD(font.getAscender() - font.getDescender()); | |||
inline.setOffset(font.getAscender()); | |||
inline.addTrait(Trait.FONT_NAME, font.getFontName()); | |||
inline.addTrait(Trait.FONT_SIZE, new Integer(font.getFontSize())); | |||
} | |||
inline.setBPD(font.getAscender() - font.getDescender()); | |||
inline.setOffset(font.getAscender()); | |||
inline.addTrait(Trait.FONT_NAME, font.getFontName()); | |||
inline.addTrait(Trait.FONT_SIZE, new Integer(font.getFontSize())); | |||
TraitSetter.addTextDecoration(inline, fobj.getTextDecoration()); | |||
return inline; |
@@ -29,7 +29,7 @@ import org.apache.fop.fonts.Font; | |||
*/ | |||
public class PageNumberLayoutManager extends LeafNodeLayoutManager { | |||
private PageNumber fobj; | |||
Font font = null; | |||
private Font font = null; | |||
/** | |||
* Constructor | |||
@@ -64,8 +64,27 @@ public class PageNumberLayoutManager extends LeafNodeLayoutManager { | |||
return inline; | |||
} | |||
protected void offsetArea(LayoutContext context) { | |||
curArea.setOffset(context.getBaseline()); | |||
protected void offsetArea(InlineArea area, LayoutContext context) { | |||
area.setOffset(context.getBaseline()); | |||
} | |||
protected InlineArea getEffectiveArea() { | |||
TextArea baseArea = (TextArea)curArea; | |||
//TODO Maybe replace that with a clone() call or better, a copy constructor | |||
//TODO or even better: delay area creation until addAreas() stage | |||
//TextArea is cloned because the LM is reused in static areas and the area can't be. | |||
TextArea ta = new TextArea(); | |||
ta.setIPD(baseArea.getIPD()); | |||
ta.setBPD(baseArea.getBPD()); | |||
ta.setOffset(baseArea.getOffset()); | |||
ta.addTrait(Trait.FONT_NAME, font.getFontName()); //only to initialize the trait map | |||
ta.getTraits().putAll(baseArea.getTraits()); | |||
updateContent(ta); | |||
return ta; | |||
} | |||
private void updateContent(TextArea area) { | |||
area.setTextArea(getCurrentPV().getPageNumberString()); | |||
} | |||
protected void addId() { |
@@ -531,6 +531,10 @@ public class PageSequenceLayoutManager extends AbstractLayoutManager { | |||
layoutSideRegion(FO_REGION_AFTER); | |||
layoutSideRegion(FO_REGION_START); | |||
layoutSideRegion(FO_REGION_END); | |||
// Try to resolve any unresolved IDs for the current page. | |||
// | |||
areaTreeHandler.tryIDResolution(curPV); | |||
// Queue for ID resolution and rendering | |||
areaTreeHandler.getAreaTreeModel().addPage(curPV); | |||
log.debug("page finished: " + curPV.getPageNumberString() |