From 2bddcdef54e1544953538649d643b11476c2ea61 Mon Sep 17 00:00:00 2001 From: Keiron Liddle Date: Fri, 16 Aug 2002 12:44:07 +0000 Subject: [PATCH] calculate line height and do vertical alignment better git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@195089 13f79535-47bb-0310-9956-ffa450edef68 --- src/org/apache/fop/area/LineArea.java | 103 ------------------ .../apache/fop/area/inline/InlineArea.java | 2 - src/org/apache/fop/fo/FObj.java | 5 +- src/org/apache/fop/fo/flow/BidiOverride.java | 4 +- .../apache/fop/fo/flow/ExternalGraphic.java | 5 +- .../fop/fo/flow/InstreamForeignObject.java | 5 +- src/org/apache/fop/fo/flow/Leader.java | 4 +- src/org/apache/fop/layoutmgr/BreakPoss.java | 40 ++++++- .../apache/fop/layoutmgr/LayoutContext.java | 22 ++++ src/org/apache/fop/layoutmgr/LayoutInfo.java | 26 ----- .../fop/layoutmgr/LeafNodeLayoutManager.java | 58 ++++++++-- .../fop/layoutmgr/LineBPLayoutManager.java | 53 +++++++-- .../fop/layoutmgr/TextBPLayoutManager.java | 9 +- 13 files changed, 164 insertions(+), 172 deletions(-) delete mode 100644 src/org/apache/fop/layoutmgr/LayoutInfo.java diff --git a/src/org/apache/fop/area/LineArea.java b/src/org/apache/fop/area/LineArea.java index 306d50be6..0ba001f5e 100644 --- a/src/org/apache/fop/area/LineArea.java +++ b/src/org/apache/fop/area/LineArea.java @@ -59,108 +59,5 @@ public class LineArea extends Area { public List getInlineAreas() { return inlineAreas; } - - public void verticalAlign(int lh, int lead, int follow) { - int maxHeight = lh; - List inlineAreas = getInlineAreas(); - - // get smallest possible offset to before edge - // this depends on the height of no and middle alignments - int before = lead; - int after = follow; - int halfLeading = (lineHeight - lead - follow) / 2; - before += halfLeading; - for (Iterator iter = inlineAreas.iterator(); iter.hasNext();) { - InlineArea inline = (InlineArea) iter.next(); - LayoutInfo info = inline.info; - int al; - int ld = inline.getHeight(); - if (info != null) { - al = info.alignment; - ld = info.lead; - } else { - al = VerticalAlign.BASELINE; - } - if (al == VerticalAlign.BASELINE) { - if (ld > before) { - before = ld; - } - if (inline.getHeight() > before) { - before = inline.getHeight(); - } - } else if (al == VerticalAlign.MIDDLE) { - if (inline.getHeight() / 2 + lead / 2 > before) { - before = inline.getHeight() / 2 + lead / 2; - } - if (inline.getHeight() / 2 - lead / 2 > after) { - after = inline.getHeight() / 2 - lead / 2; - } - } else if (al == VerticalAlign.TOP) { - } else if (al == VerticalAlign.BOTTOM) { - } - } - // then align all before, no and middle alignment - for (Iterator iter = inlineAreas.iterator(); iter.hasNext();) { - InlineArea inline = (InlineArea) iter.next(); - LayoutInfo info = inline.info; - int al; - int ld = inline.getHeight(); - boolean bloffset = false; - if (info != null) { - al = info.alignment; - ld = info.lead; - bloffset = info.blOffset; - } else { - al = VerticalAlign.BASELINE; - } - if (al == VerticalAlign.BASELINE) { - // the offset position for text is the baseline - if (bloffset) { - inline.setOffset(before); - } else { - inline.setOffset(before - ld); - } - if (inline.getHeight() - ld > after) { - after = inline.getHeight() - ld; - } - } else if (al == VerticalAlign.MIDDLE) { - inline.setOffset(before - inline.getHeight() / 2 - - lead / 2); - } else if (al == VerticalAlign.TOP) { - inline.setOffset(0); - if (inline.getHeight() - before > after) { - after = inline.getHeight() - before; - } - } else if (al == VerticalAlign.BOTTOM) { - if (inline.getHeight() - before > after) { - after = inline.getHeight() - before; - } - } - } - - // after alignment depends on maximum height of before - // and middle alignments - for (Iterator iter = inlineAreas.iterator(); iter.hasNext();) { - InlineArea inline = (InlineArea) iter.next(); - LayoutInfo info = inline.info; - int al; - if (info != null) { - al = info.alignment; - } else { - al = VerticalAlign.BASELINE; - } - if (al == VerticalAlign.BASELINE) { - } else if (al == VerticalAlign.MIDDLE) { - } else if (al == VerticalAlign.TOP) { - } else if (al == VerticalAlign.BOTTOM) { - inline.setOffset(before + after - inline.getHeight()); - } - } - if (before + after > maxHeight) { - setHeight(before + after); - } else { - setHeight(maxHeight); - } - } } diff --git a/src/org/apache/fop/area/inline/InlineArea.java b/src/org/apache/fop/area/inline/InlineArea.java index 645e67a0b..2278806d5 100644 --- a/src/org/apache/fop/area/inline/InlineArea.java +++ b/src/org/apache/fop/area/inline/InlineArea.java @@ -32,8 +32,6 @@ public class InlineArea extends Area { // position within the line area, either top or baseline int verticalPosition; - // width, height, vertical alignment - public LayoutInfo info = null; // store properties in array list, need better solution ArrayList props = null; diff --git a/src/org/apache/fop/fo/FObj.java b/src/org/apache/fop/fo/FObj.java index fc29ef8a2..e4a0f5503 100644 --- a/src/org/apache/fop/fo/FObj.java +++ b/src/org/apache/fop/fo/FObj.java @@ -211,7 +211,10 @@ public class FObj extends FONode { * @return A ListIterator. */ public ListIterator getChildren() { - return children.listIterator(); + if(children != null) { + return children.listIterator(); + } + return null; } /** diff --git a/src/org/apache/fop/fo/flow/BidiOverride.java b/src/org/apache/fop/fo/flow/BidiOverride.java index f9a8b661b..280dff4d9 100644 --- a/src/org/apache/fop/fo/flow/BidiOverride.java +++ b/src/org/apache/fop/fo/flow/BidiOverride.java @@ -85,7 +85,7 @@ public class BidiOverride extends FObjMixed { BidiLayoutManager(FObj obj, LeafNodeLayoutManager cLM) { super(obj); childs = new ArrayList(); - for (int count = cLM.size() - 1; count >= 0; count--) { +/* for (int count = cLM.size() - 1; count >= 0; count--) { InlineArea ia = cLM.get(count); if (ia instanceof Word) { // reverse word @@ -95,7 +95,7 @@ public class BidiOverride extends FObjMixed { } childs.add(ia); } - } +*/ } public int size() { return childs.size(); diff --git a/src/org/apache/fop/fo/flow/ExternalGraphic.java b/src/org/apache/fop/fo/flow/ExternalGraphic.java index 561f95ac9..bef021138 100644 --- a/src/org/apache/fop/fo/flow/ExternalGraphic.java +++ b/src/org/apache/fop/fo/flow/ExternalGraphic.java @@ -48,6 +48,8 @@ public class ExternalGraphic extends FObj { public void addLayoutManager(List list) { LeafNodeLayoutManager lm = new LeafNodeLayoutManager(this); lm.setCurrentArea(getInlineArea()); + lm.setAlignment(properties.get("vertical-align").getEnum()); + lm.setLead(viewHeight); list.add(lm); } @@ -63,9 +65,6 @@ public class ExternalGraphic extends FObj { vp.setClip(clip); vp.setContentPosition(placement); vp.setOffset(0); - vp.info = new LayoutInfo(); - vp.info.alignment = properties.get("vertical-align").getEnum(); - vp.info.lead = vp.getHeight(); return vp; } diff --git a/src/org/apache/fop/fo/flow/InstreamForeignObject.java b/src/org/apache/fop/fo/flow/InstreamForeignObject.java index 398293f43..47a50453d 100644 --- a/src/org/apache/fop/fo/flow/InstreamForeignObject.java +++ b/src/org/apache/fop/fo/flow/InstreamForeignObject.java @@ -57,6 +57,8 @@ public class InstreamForeignObject extends FObj { public void addLayoutManager(List list) { LeafNodeLayoutManager lm = new LeafNodeLayoutManager(this); lm.setCurrentArea(getInlineArea()); + lm.setAlignment(properties.get("vertical-align").getEnum()); + lm.setLead(areaCurrent.getHeight()); list.add(lm); } @@ -247,9 +249,6 @@ public class InstreamForeignObject extends FObj { areaCurrent.setContentPosition(placement); areaCurrent.setClip(clip); areaCurrent.setOffset(0); - areaCurrent.info = new LayoutInfo(); - areaCurrent.info.alignment = properties.get("vertical-align").getEnum(); - areaCurrent.info.lead = areaCurrent.getHeight(); return areaCurrent; } diff --git a/src/org/apache/fop/fo/flow/Leader.java b/src/org/apache/fop/fo/flow/Leader.java index 5e5c4e49f..d4e56a3d1 100644 --- a/src/org/apache/fop/fo/flow/Leader.java +++ b/src/org/apache/fop/fo/flow/Leader.java @@ -34,9 +34,7 @@ public class Leader extends FObjMixed { public void addLayoutManager(List list) { list.add(new LeafNodeLayoutManager(this) { - public InlineArea get(int index) { - if(index > 0) - return null; + public InlineArea get() { int contentIPD = parentLM.getContentIPD(); return getInlineArea(contentIPD); } diff --git a/src/org/apache/fop/layoutmgr/BreakPoss.java b/src/org/apache/fop/layoutmgr/BreakPoss.java index 5c44b6acb..e8a745a67 100644 --- a/src/org/apache/fop/layoutmgr/BreakPoss.java +++ b/src/org/apache/fop/layoutmgr/BreakPoss.java @@ -54,8 +54,11 @@ public class BreakPoss { /** * Max height above and below the baseline. These are cumulative. */ - private int m_iMaxAscender; - private int m_iMaxDescender; + private int m_iLead; + // the max height of before and after alignment + private int m_iTotal; + // middle alignment height for after + private int m_iMiddle; /** Size in the non-stacking direction (perpendicular). */ private MinOptMax m_nonStackSize; @@ -198,4 +201,37 @@ public class BreakPoss { public boolean checkIPD() { return ((m_flags & NEED_IPD) != 0); } + + public int getLead() { + return m_iLead; + } + + public int getTotal() { + return m_iTotal; + } + + public int getMiddle() { + return m_iMiddle; + } + + /** + * set lead height of baseline positioned element + */ + public void setLead(int ld) { + m_iLead = ld; + } + + /** + * Set total height of top or bottom aligned element + */ + public void setTotal(int t) { + m_iTotal = t; + } + + /** + * Set distance below baseline of middle aligned element + */ + public void setMiddle(int t) { + m_iMiddle = t; + } } diff --git a/src/org/apache/fop/layoutmgr/LayoutContext.java b/src/org/apache/fop/layoutmgr/LayoutContext.java index 2ec273ee4..e359720ac 100644 --- a/src/org/apache/fop/layoutmgr/LayoutContext.java +++ b/src/org/apache/fop/layoutmgr/LayoutContext.java @@ -69,6 +69,9 @@ public class LayoutContext { /** Stretch or shrink value when making areas. */ private double m_dSpaceAdjust = 0.0; + private int m_iLineHeight; + private int m_iBaseline; + public LayoutContext(LayoutContext parentLC) { this.flags = parentLC.flags; this.refIPD = parentLC.refIPD; @@ -77,6 +80,8 @@ public class LayoutContext { this.m_trailingSpace = parentLC.m_trailingSpace; //??? this.m_hyphContext = parentLC.m_hyphContext; this.m_dSpaceAdjust = parentLC.m_dSpaceAdjust; + this.m_iLineHeight = parentLC.m_iLineHeight; + this.m_iBaseline = parentLC.m_iBaseline; // Copy other fields as necessary. Use clone??? } @@ -171,4 +176,21 @@ public class LayoutContext { public double getSpaceAdjust() { return m_dSpaceAdjust; } + + public void setLineHeight(int lh) { + m_iLineHeight = lh; + } + + public int getLineHeight() { + return m_iLineHeight; + } + + public void setBaseline(int bl) { + m_iBaseline = bl; + } + + public int getBaseline() { + return m_iBaseline; + } } + diff --git a/src/org/apache/fop/layoutmgr/LayoutInfo.java b/src/org/apache/fop/layoutmgr/LayoutInfo.java deleted file mode 100644 index bab3cb781..000000000 --- a/src/org/apache/fop/layoutmgr/LayoutInfo.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * $Id$ - * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. - * For details on use and redistribution please refer to the - * LICENSE file included with these sources. - */ - -package org.apache.fop.layoutmgr; - -import org.apache.fop.area.Area; -import org.apache.fop.area.MinOptMax; - -public class LayoutInfo { - public int alignment; - public int lead; - public boolean blOffset = false; - public boolean breakAfter = false; - - public boolean keepNext = false; - public boolean keepPrev = false; - public boolean isText = false; - - public LayoutInfo() { - } - -} diff --git a/src/org/apache/fop/layoutmgr/LeafNodeLayoutManager.java b/src/org/apache/fop/layoutmgr/LeafNodeLayoutManager.java index 32c2633e9..f0a63d2cd 100644 --- a/src/org/apache/fop/layoutmgr/LeafNodeLayoutManager.java +++ b/src/org/apache/fop/layoutmgr/LeafNodeLayoutManager.java @@ -11,7 +11,7 @@ import org.apache.fop.fo.FObj; import org.apache.fop.area.Area; import org.apache.fop.area.MinOptMax; import org.apache.fop.area.inline.InlineArea; - +import org.apache.fop.fo.properties.VerticalAlign; /** * Base LayoutManager for leaf-node FObj, ie: ones which have no children. @@ -21,18 +21,14 @@ import org.apache.fop.area.inline.InlineArea; public class LeafNodeLayoutManager extends AbstractBPLayoutManager { private InlineArea curArea = null; + private int alignment; + private int lead; public LeafNodeLayoutManager(FObj fobj) { super(fobj); } - public int size() { - return 1; - } - - public InlineArea get(int index) { - if (index > 0) - return null; + public InlineArea get() { return curArea; } @@ -48,8 +44,12 @@ public class LeafNodeLayoutManager extends AbstractBPLayoutManager { curArea = ia; } - protected boolean flush() { - return false; + public void setAlignment(int al) { + alignment = al; + } + + public void setLead(int l) { + lead = l; } /** @@ -68,7 +68,7 @@ public class LeafNodeLayoutManager extends AbstractBPLayoutManager { public BreakPoss getNextBreakPoss(LayoutContext context, Position prevBreakPoss) { - curArea = get(0); + curArea = get(); if (curArea == null) { setFinished(true); return null; @@ -79,6 +79,24 @@ public class LeafNodeLayoutManager extends AbstractBPLayoutManager { BreakPoss.ISLAST); bp.setStackingSize(curArea.getAllocationIPD()); bp.setNonStackingSize(curArea.getAllocationBPD()); + + int bpd = curArea.getHeight(); + switch(alignment) { + case VerticalAlign.MIDDLE: + bp.setMiddle(bpd / 2 /* - fontLead/2 */); + bp.setLead(bpd / 2 /* + fontLead/2 */); + break; + case VerticalAlign.TOP: + bp.setTotal(bpd); + break; + case VerticalAlign.BOTTOM: + bp.setTotal(bpd); + break; + case VerticalAlign.BASELINE: + default: + bp.setLead(bpd); + break; + } setFinished(true); return bp; } @@ -92,6 +110,24 @@ public class LeafNodeLayoutManager extends AbstractBPLayoutManager { public void addAreas(PositionIterator posIter, LayoutContext context) { parentLM.addChild(curArea); + + int bpd = curArea.getHeight(); + switch(alignment) { + case VerticalAlign.MIDDLE: + curArea.setOffset(context.getBaseline() - bpd / 2 /* - fontLead/2 */); + break; + case VerticalAlign.TOP: + //curArea.setOffset(0); + break; + case VerticalAlign.BOTTOM: + curArea.setOffset(context.getLineHeight() - bpd); + break; + case VerticalAlign.BASELINE: + default: + curArea.setOffset(context.getBaseline() - bpd); + break; + } + while (posIter.hasNext()) { posIter.next(); } diff --git a/src/org/apache/fop/layoutmgr/LineBPLayoutManager.java b/src/org/apache/fop/layoutmgr/LineBPLayoutManager.java index dfeb56aa3..eebec2529 100644 --- a/src/org/apache/fop/layoutmgr/LineBPLayoutManager.java +++ b/src/org/apache/fop/layoutmgr/LineBPLayoutManager.java @@ -47,12 +47,16 @@ public class LineBPLayoutManager extends InlineStackingBPLayoutManager { private static class LineBreakPosition extends LeafPosition { // int m_iPos; double m_dAdjust; // Percentage to adjust (stretch or shrink) + int lineHeight; + int baseline; LineBreakPosition(BPLayoutManager lm, int iBreakIndex, - double dAdjust) { + double dAdjust, int lh, int bl) { super(lm, iBreakIndex); // m_iPos = iBreakIndex; m_dAdjust = dAdjust; + lineHeight = lh; + baseline = bl; } } @@ -104,7 +108,7 @@ public class LineBPLayoutManager extends InlineStackingBPLayoutManager { * (page) should check reference area and possibly * create a new one. */ - return new BreakPoss(new LineBreakPosition(this, -1, 0.0), + return new BreakPoss(new LineBreakPosition(this, -1, 0.0, lineHeight, lead), BreakPoss.NEED_IPD); } @@ -286,7 +290,7 @@ public class LineBPLayoutManager extends InlineStackingBPLayoutManager { // Don't justify last line in the sequence or if forced line-end boolean bJustify = (m_bJustify && !m_prevBP.isForcedBreak() && !isFinished()); - return makeLineBreak(m_prevBP, availIPD, actual, bJustify); + return makeLineBreak(iPrevLineEnd, availIPD, actual, bJustify); } @@ -344,8 +348,6 @@ public class LineBPLayoutManager extends InlineStackingBPLayoutManager { return true; } - - private HyphContext getHyphenContext(BreakPoss prevBP, BreakPoss newBP) { // Get a "word" to hyphenate by getting characters from all @@ -403,8 +405,8 @@ public class LineBPLayoutManager extends InlineStackingBPLayoutManager { } - private BreakPoss makeLineBreak(BreakPoss inlineBP, - MinOptMax target, MinOptMax actual, boolean bJustify) { + private BreakPoss makeLineBreak(int prevLineEnd, MinOptMax target, + MinOptMax actual, boolean bJustify) { // make a new BP // Store information needed to make areas in the LineBreakPosition! // Calculate stretch or shrink factor @@ -421,16 +423,45 @@ public class LineBPLayoutManager extends InlineStackingBPLayoutManager { (double)(actual.opt - actual.min); } } + + // lead to baseline is + // max of: baseline fixed alignment and middle/2 + // after baseline is + // max: top height-lead, middle/2 and bottom height-lead + int halfLeading = (lineHeight - lead - follow) / 2; + // height before baseline + int lineLead = lead + halfLeading; + // maximum size of top and bottom alignment + int maxtb = follow + halfLeading; + // max size of middle alignment below baseline + int middlefollow = maxtb; + for(Iterator iter = m_vecInlineBreaks.listIterator(prevLineEnd); + iter.hasNext(); ) { + BreakPoss bp = (BreakPoss)iter.next(); + if(bp.getLead() > lineLead) { + lineLead = bp.getLead(); + } + if(bp.getTotal() > maxtb) { + maxtb = bp.getTotal(); + } + if(bp.getMiddle() > middlefollow) { + middlefollow = bp.getMiddle(); + } + } + if(maxtb - lineLead > middlefollow) { + middlefollow = maxtb - lineLead; + } + //log.debug("Adjustment factor=" + dAdjust); BreakPoss curLineBP = new BreakPoss( new LineBreakPosition(this, - m_vecInlineBreaks.size() - 1, dAdjust)); + m_vecInlineBreaks.size() - 1, dAdjust, lineLead + middlefollow, lineLead)); /* FIX ME!! * Need to calculate line height based on all inline BP info * for this line not just the current inlineBP! */ curLineBP.setFlag(BreakPoss.ISLAST, isFinished()); - curLineBP.setStackingSize(inlineBP.getNonStackingSize()); + curLineBP.setStackingSize(new MinOptMax(lineLead + middlefollow)); return curLineBP; } @@ -452,6 +483,9 @@ public class LineBPLayoutManager extends InlineStackingBPLayoutManager { while (parentIter.hasNext()) { LineBreakPosition lbp = (LineBreakPosition) parentIter.next(); LineArea lineArea = new LineArea(); + lineArea.setHeight(lbp.lineHeight); + lc.setBaseline(lbp.baseline); + lc.setLineHeight(lbp.lineHeight); setCurrentArea(lineArea); // Add the inline areas to lineArea PositionIterator inlinePosIter = @@ -471,7 +505,6 @@ if(lc.getTrailingSpace() != null) { addSpace(lineArea, lc.getTrailingSpace().resolve(true), lc.getSpaceAdjust()); } - lineArea.verticalAlign(lineHeight, lead, follow); parentLM.addChild(lineArea); } setCurrentArea(null); // ?? necessary diff --git a/src/org/apache/fop/layoutmgr/TextBPLayoutManager.java b/src/org/apache/fop/layoutmgr/TextBPLayoutManager.java index dc573270d..2abba0a17 100644 --- a/src/org/apache/fop/layoutmgr/TextBPLayoutManager.java +++ b/src/org/apache/fop/layoutmgr/TextBPLayoutManager.java @@ -468,7 +468,7 @@ public class TextBPLayoutManager extends AbstractBPLayoutManager { // Make an area containing all characters between start and end. Word word = createWord( new String(chars, iStart, ai.m_iBreakIndex - iStart), - ai.m_ipdArea.opt + iAdjust); + ai.m_ipdArea.opt + iAdjust, context.getBaseline()); if (iWScount > 0) { //log.error("Adjustment per word-space= " + // iAdjust / iWScount); @@ -498,16 +498,13 @@ public class TextBPLayoutManager extends AbstractBPLayoutManager { - protected Word createWord(String str, int width) { + protected Word createWord(String str, int width, int base) { Word curWordArea = new Word(); curWordArea.setWidth(width); curWordArea.setHeight(textInfo.fs.getAscender() - textInfo.fs.getDescender()); curWordArea.setOffset(textInfo.fs.getAscender()); - curWordArea.info = new LayoutInfo(); - curWordArea.info.lead = textInfo.fs.getAscender(); - curWordArea.info.alignment = VerticalAlign.BASELINE; - curWordArea.info.blOffset = true; + curWordArea.setOffset(base); curWordArea.setWord(str); curWordArea.addTrait(Trait.FONT_NAME, textInfo.fs.getFontName()); -- 2.39.5