deweese 02/04/12 07:36:48 Modified: samples/extensions flowText.svg sources/org/apache/batik/extension/svg BatikDomExtension.java BatikExtConstants.java SVGFlowTextElementBridge.java sources/org/apache/batik/gvt/renderer StrokingTextPainter.java sources/org/apache/batik/gvt/text GlyphIterator.java GlyphLayout.java MarginInfo.java Added: sources/org/apache/batik/extension/svg FlowRegionBreakElement.java Log: 1) Added new flowRegionBreak element that is the same as a flowPara element but causes the text to move to the next flow rectangle after it ends (it can be empty). 2) Text wrapping is now done on the visual advance of the glyph not the glyph advance. This is usually a small difference but because everything else is done with visual advance (centering/right/full justification) this is the right thing to do. 3) Now handles paragraphs and margins when moving between flow regions in accordance to current WG thinking (especially empty paragraphs). 4) Multiple empty flowLine elements collapse (also in accordance with current WG thinking - this is what happens in XHTML or so I'm told). 5) Fixed a bug or two in text chunking. Revision Changes Path 1.4 +3 -3 xml-batik/samples/extensions/flowText.svg Index: flowText.svg =================================================================== RCS file: /home/cvs/xml-batik/samples/extensions/flowText.svg,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- flowText.svg 4 Apr 2002 03:29:57 -0000 1.3 +++ flowText.svg 12 Apr 2002 14:36:47 -0000 1.4 @@ -14,7 +14,7 @@ <!-- Tests various text on a path --> <!-- --> <!-- @author [EMAIL PROTECTED] --> -<!-- @version $Id: flowText.svg,v 1.3 2002/04/04 03:29:57 deweese Exp $ --> +<!-- @version $Id: flowText.svg,v 1.4 2002/04/12 14:36:47 deweese Exp $ --> <!-- ====================================================================== --> <?xml-stylesheet type="text/css" href="extension.css" ?> @@ -42,9 +42,9 @@ </batik:flowRegion> <batik:flowDiv> <batik:flowPara bottom-margin="10" >This is an <batik:flowSpan font-size="40" fill="crimson">ex­ample</batik:flowSpan> of a very long string that is split ‍across multi­ple lines via text wrap­ping.</batik:flowPara> - <batik:flowPara justification="middle" top-margin="10" left-margin="10" right-margin="10" bottom-margin="10"><batik:flowLine>Now check if text wrapping handles a number of tricky situations: </batik:flowLine>averylongrunonwordthatspansmultiplelines<batik:flowSpan font-weight="bold">with<batik:flowSpan fill="crimson">embedded</batik:flowSpan>span</batik:flowSpan>elements & <batik:flowSpan fill="green" dy="-.3em" font-size="80%">super</batik:flowSpan><batik:flowSpan dy=".3em"> or </batik:flowSpan><batik:flowSpan fill="darkgreen" dy=".3em" font-size="80%">sub</batik:flowSpan><batik:flowSpan dy="-.3em"> scripts.</batik:flowSpan></batik:flowPara> + <batik:flowPara justification="middle" top-margin="10" left-margin="10" right-margin="10" bottom-margin="10"><batik:flowLine>Now check if text wrapping handles a number of tricky</batik:flowLine> situations: averylongrunonwordthatspansmultiplelines<batik:flowSpan font-weight="bold">with<batik:flowSpan fill="crimson">embedded</batik:flowSpan>span</batik:flowSpan>elements & <batik:flowSpan fill="green" dy="-.3em" font-size="80%">super</batik:flowSpan><batik:flowSpan dy=".3em"> or </batik:flowSpan><batik:flowSpan fill="darkgreen" dy=".3em" font-size="80%">sub</batik:flowSpan><batik:flowSpan dy="-.3em"> scripts.</batik:flowSpan></batik:flowPara> <batik:flowPara top-margin="10" justification="end">Now we are just <batik:flowSpan font-size="30" fill="blue">about</batik:flowSpan> to go to the next flow rect <batik:flowSpan font-size="10">(note if the 'about' were included on the last line of the previous flow rect the line would not have fit and the whole line would have moved here).</batik:flowSpan></batik:flowPara> - <batik:flowPara margin="10" justification="full"> I'll keep going because I want to make sure that it properly stops when it hits the end of the flow regions. I'm going to try and trick it by having the last line include larger text so it wouldn't fit vertically. The end of this sentence will be cut off because the line size gets larg<batik:flowSpan font-size="35">er</batik:flowSpan></batik:flowPara> + <batik:flowPara margin="10" justification="full"> I'll keep going because I want to make sure that it properly stops when it hits the end of all of the the flow regions defined. Also the last line includes text in a larger font size so it will not fit. Thus the end of this sentence will be cut off because the line size gets <batik:flowSpan font-size="35">tall</batik:flowSpan>er</batik:flowPara> </batik:flowDiv> </batik:flowText> </g> 1.10 +20 -0 xml-batik/sources/org/apache/batik/extension/svg/BatikDomExtension.java Index: BatikDomExtension.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/extension/svg/BatikDomExtension.java,v retrieving revision 1.9 retrieving revision 1.10 diff -u -r1.9 -r1.10 --- BatikDomExtension.java 29 Mar 2002 20:00:54 -0000 1.9 +++ BatikDomExtension.java 12 Apr 2002 14:36:47 -0000 1.10 @@ -117,6 +117,11 @@ di.registerCustomElementFactory (BATIK_EXT_NAMESPACE_URI, + BATIK_EXT_FLOW_REGION_BREAK_TAG, + new FlowRegionBreakElementFactory()); + + di.registerCustomElementFactory + (BATIK_EXT_NAMESPACE_URI, BATIK_EXT_FLOW_LINE_TAG, new FlowLineElementFactory()); @@ -269,6 +274,21 @@ */ public Element create(String prefix, Document doc) { return new FlowParaElement(prefix, (AbstractDocument)doc); + } + } + + /** + * To create a 'flowRegionBreak' element. + */ + protected static class FlowRegionBreakElementFactory + implements SVGDOMImplementation.ElementFactory { + public FlowRegionBreakElementFactory() { + } + /** + * Creates an instance of the associated element type. + */ + public Element create(String prefix, Document doc) { + return new FlowRegionBreakElement(prefix, (AbstractDocument)doc); } } 1.9 +5 -0 xml-batik/sources/org/apache/batik/extension/svg/BatikExtConstants.java Index: BatikExtConstants.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/extension/svg/BatikExtConstants.java,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- BatikExtConstants.java 29 Mar 2002 20:00:54 -0000 1.8 +++ BatikExtConstants.java 12 Apr 2002 14:36:47 -0000 1.9 @@ -75,6 +75,11 @@ public static final String BATIK_EXT_FLOW_PARA_TAG = "flowPara"; + /** Tag name for Batik's flowText extension flow Region break + * element SVG 1.1). */ + public static final String BATIK_EXT_FLOW_REGION_BREAK_TAG = + "flowRegionBreak"; + /** Tag name for Batik's flowText extension line element SVG 1.1). */ public static final String BATIK_EXT_FLOW_LINE_TAG = "flowLine"; 1.2 +22 -6 xml-batik/sources/org/apache/batik/extension/svg/SVGFlowTextElementBridge.java Index: SVGFlowTextElementBridge.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/extension/svg/SVGFlowTextElementBridge.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- SVGFlowTextElementBridge.java 29 Mar 2002 20:00:54 -0000 1.1 +++ SVGFlowTextElementBridge.java 12 Apr 2002 14:36:47 -0000 1.2 @@ -39,7 +39,7 @@ * Bridge class for the <flowText> element. * * @author <a href="[EMAIL PROTECTED]">Thomas DeWeese</a> - * @version $Id: SVGFlowTextElementBridge.java,v 1.1 2002/03/29 20:00:54 deweese Exp $ + * @version $Id: SVGFlowTextElementBridge.java,v 1.2 2002/04/12 14:36:47 deweese Exp $ */ public class SVGFlowTextElementBridge extends SVGTextElementBridge implements BatikExtConstants { @@ -169,6 +169,7 @@ } String ln = child.getLocalName(); if (ln.equals(BATIK_EXT_FLOW_PARA_TAG) || + ln.equals(BATIK_EXT_FLOW_REGION_BREAK_TAG) || ln.equals(BATIK_EXT_FLOW_LINE_TAG) || ln.equals(BATIK_EXT_FLOW_SPAN_TAG) || ln.equals(SVG_A_TAG) || @@ -230,6 +231,7 @@ } String ln = child.getLocalName(); if (ln.equals(BATIK_EXT_FLOW_PARA_TAG) || + ln.equals(BATIK_EXT_FLOW_REGION_BREAK_TAG) || ln.equals(BATIK_EXT_FLOW_LINE_TAG) || ln.equals(BATIK_EXT_FLOW_SPAN_TAG) || ln.equals(SVG_A_TAG) || @@ -276,6 +278,11 @@ paraElems.add(e); paraEnds.add(new Integer(asb.length())); + } else if (ln.equals(BATIK_EXT_FLOW_REGION_BREAK_TAG)) { + fillAttributedStringBuffer(ctx, e, true, asb, lnLocs); + + paraElems.add(e); + paraEnds.add(new Integer(asb.length())); } } @@ -286,6 +293,10 @@ List emptyPara = null; int prevLN = -1; Iterator lnIter = lnLocs.iterator(); + + // The Working Group (in conjunction with XHTML working group + // has decided that multiple line elements collapse so I don't + // use the counting I do. int lnCount = 0; while (lnIter.hasNext()) { int nextLN = ((Integer)lnIter.next()).intValue(); @@ -293,21 +304,22 @@ lnCount++; } else { if (prevLN != -1) - ret.addAttribute(FLOW_LINE_BREAK, new Integer(lnCount), + ret.addAttribute(FLOW_LINE_BREAK, + new Integer(1), // new Integer(lnCount), prevLN-1, prevLN); prevLN = nextLN; lnCount = 1; } } if (prevLN != -1) - ret.addAttribute(FLOW_LINE_BREAK, new Integer(lnCount), + ret.addAttribute(FLOW_LINE_BREAK, + new Integer(1), // new Integer(lnCount), prevLN-1, prevLN); int end; for (int i=0; i<paraElems.size(); i++, start=end) { Element elem = (Element)paraElems.get(i); end = ((Integer)paraEnds.get(i)).intValue(); - if (start == end) { if (emptyPara == null) emptyPara = new LinkedList(); @@ -550,7 +562,7 @@ * @param breakIdx The character after which to break. * @param lineAdvAdj The line advance adjustment. * @param relative If true lineAdvAdj must be multiplied by -1 * the line height. + * the line height. */ public LineBreakInfo(int breakIdx, float lineAdvAdj, boolean relative){ this.breakIdx = breakIdx; @@ -565,6 +577,7 @@ public MarginInfo makeMarginInfo(Element e) { String s; float top=0, right=0, bottom=0, left=0; + s = e.getAttributeNS(null, BATIK_EXT_MARGIN_ATTRIBUTE); try { if (s.length() != 0) { @@ -617,7 +630,10 @@ } } } catch(NumberFormatException nfe) { /* nothing */ } - return new MarginInfo(top, right, bottom, left, justification); + + String ln = e.getLocalName(); + boolean rgnBr = ln.equals(BATIK_EXT_FLOW_REGION_BREAK_TAG); + return new MarginInfo(top, right, bottom, left, justification, rgnBr); } 1.1 xml-batik/sources/org/apache/batik/extension/svg/FlowRegionBreakElement.java Index: FlowRegionBreakElement.java =================================================================== /***************************************************************************** * Copyright (C) The Apache Software Foundation. All rights reserved. * * ------------------------------------------------------------------------- * * This software is published under the terms of the Apache Software License * * version 1.1, a copy of which has been included with this distribution in * * the LICENSE file. * *****************************************************************************/ package org.apache.batik.extension.svg; import org.w3c.dom.Node; import org.apache.batik.dom.AbstractDocument; import org.apache.batik.extension.PrefixableStylableExtensionElement; /** * This class implements a regular polygon extension to SVG * * @author <a href="mailto:[EMAIL PROTECTED]">Thomas DeWeese</a> * @version $Id: FlowRegionBreakElement.java,v 1.1 2002/04/12 14:36:47 deweese Exp $ */ public class FlowRegionBreakElement extends PrefixableStylableExtensionElement implements BatikExtConstants { /** * Creates a new BatikRegularPolygonElement object. */ protected FlowRegionBreakElement() { } /** * Creates a new BatikRegularPolygonElement object. * @param prefix The namespace prefix. * @param owner The owner document. */ public FlowRegionBreakElement(String prefix, AbstractDocument owner) { super(prefix, owner); } /** * <b>DOM</b>: Implements {@link org.w3c.dom.Node#getLocalName()}. */ public String getLocalName() { return BATIK_EXT_FLOW_REGION_BREAK_TAG; } /** * <b>DOM</b>: Implements {@link org.w3c.dom.Node#getNamespaceURI()}. */ public String getNamespaceURI() { return BATIK_EXT_NAMESPACE_URI; } /** * Returns a new uninitialized instance of this object's class. */ protected Node newNode() { return new FlowRegionBreakElement(); } } 1.32 +8 -10 xml-batik/sources/org/apache/batik/gvt/renderer/StrokingTextPainter.java Index: StrokingTextPainter.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/gvt/renderer/StrokingTextPainter.java,v retrieving revision 1.31 retrieving revision 1.32 diff -u -r1.31 -r1.32 --- StrokingTextPainter.java 3 Apr 2002 04:58:21 -0000 1.31 +++ StrokingTextPainter.java 12 Apr 2002 14:36:48 -0000 1.32 @@ -61,7 +61,7 @@ * @see org.apache.batik.gvt.text.GVTAttributedCharacterIterator * * @author <a href="[EMAIL PROTECTED]>Bill Haneman</a> - * @version $Id: StrokingTextPainter.java,v 1.31 2002/04/03 04:58:21 deweese Exp $ + * @version $Id: StrokingTextPainter.java,v 1.32 2002/04/12 14:36:48 deweese Exp $ */ public class StrokingTextPainter extends BasicTextPainter { @@ -243,18 +243,15 @@ List layouts = new ArrayList(); chunkLayouts.add(layouts); layouts.add(tr.getLayout()); - while (true) { - while (i.hasNext()) { - tr = (TextRun)i.next(); - if (tr.isFirstRunInChunk()) break; - layouts.add(tr.getLayout()); + while (i.hasNext()) { + tr = (TextRun)i.next(); + if (tr.isFirstRunInChunk()) { + layouts = new ArrayList(); + chunkLayouts.add(layouts); } - - if (!i.hasNext()) break; - layouts = new ArrayList(); - chunkLayouts.add(layouts); layouts.add(tr.getLayout()); } + org.apache.batik.gvt.text.GlyphLayout.textWrapTextChunk (chunkACIs, chunkLayouts, rgns); } @@ -305,6 +302,7 @@ // This prevents BIDI reordering across paragraphs. if (aci.getAttribute(FLOW_PARAGRAPH) != null) { end = aci.getRunLimit(FLOW_PARAGRAPH); + // System.out.println("End: " + end); aci.setIndex(end); break; } 1.3 +27 -13 xml-batik/sources/org/apache/batik/gvt/text/GlyphIterator.java Index: GlyphIterator.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/gvt/text/GlyphIterator.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- GlyphIterator.java 3 Apr 2002 04:58:21 -0000 1.2 +++ GlyphIterator.java 12 Apr 2002 14:36:48 -0000 1.3 @@ -103,7 +103,8 @@ this.numGlyphs = gv.getNumGlyphs(); this.gp = gv.getGlyphPositions(0, this.numGlyphs+1, null); - this.adv = this.adj = getCharAdvance(); + this.adv = getCharWidth(); + this.adj = getCharAdvance(); } public GlyphIterator(GlyphIterator gi) { @@ -239,7 +240,8 @@ // Special handling for soft hyphens and zero-width spaces gv.setGlyphVisible(idx, false); float chAdv = getCharAdvance(); - adv -= chAdv; + float chW = getCharWidth(); + adv -= chW; adj -= chAdv; if (leftShiftIdx == null) { leftShiftIdx = new int[1]; @@ -281,7 +283,8 @@ adj += chAdv; if (isPrinting()) { chIdx = idx; - adv = adj; + float chW = getCharWidth(); + adv = adj-(chAdv-chW); } } @@ -303,15 +306,6 @@ gv.setGlyphVisible(idx, true); } - // Tweak line advance to account for visual bounds of last - // printing glyph. - Rectangle2D lcBound = gv.getGlyphVisualBounds(chIdx).getBounds2D(); - Point2D lcLoc = gv.getGlyphPosition(chIdx); - float charW = (float)(lcBound.getX()+lcBound.getWidth()- - lcLoc.getX()); - float charAdv = getCharAdvance(chIdx); - adv -= charAdv-charW; - int lsi = 0; int nextLSI; if (leftShiftIdx != null) nextLSI = leftShiftIdx[lsi]; @@ -329,7 +323,7 @@ leftShiftAmt = null; return new LineInfo(aci, gv, lineIdx, idx+1, loc, adv, adj, - charW, lineWidth, partial); + getCharWidth(chIdx), lineWidth, partial); } public void newLine() { @@ -359,9 +353,29 @@ } /** + * Get the visual advance associated with the current glyph. + * This is the distance from the location of the glyph to + * the rightmost part of the glyph. + */ + public float getCharWidth() { + return getCharWidth(idx); + } + + /** * Get the advance associated with any glyph */ protected float getCharAdvance(int gvIdx) { return gp[2*gvIdx+2] - gp[2*gvIdx]; + } + + /** + * Get the visual advance associated with the current glyph. + * This is the distance from the location of the glyph to + * the rightmost part of the glyph. + */ + protected float getCharWidth(int gvIdx) { + Rectangle2D lcBound = gv.getGlyphVisualBounds(chIdx).getBounds2D(); + Point2D lcLoc = gv.getGlyphPosition(chIdx); + return (float)(lcBound.getX()+lcBound.getWidth()- lcLoc.getX()); } } 1.39 +114 -15 xml-batik/sources/org/apache/batik/gvt/text/GlyphLayout.java Index: GlyphLayout.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/gvt/text/GlyphLayout.java,v retrieving revision 1.38 retrieving revision 1.39 diff -u -r1.38 -r1.39 --- GlyphLayout.java 3 Apr 2002 04:58:21 -0000 1.38 +++ GlyphLayout.java 12 Apr 2002 14:36:48 -0000 1.39 @@ -47,7 +47,7 @@ * @see org.apache.batik.gvt.text.TextSpanLayout * * @author <a href="[EMAIL PROTECTED]>Bill Haneman</a> - * @version $Id: GlyphLayout.java,v 1.38 2002/04/03 04:58:21 deweese Exp $ + * @version $Id: GlyphLayout.java,v 1.39 2002/04/12 14:36:48 deweese Exp $ */ public class GlyphLayout implements TextSpanLayout { @@ -1803,6 +1803,27 @@ // Should dy be considered for line offsets? (super scripts) // Should p's & br's carry over from flow rect to flow rect if // so how much???? + + // In cases where 1/2 leading is negative (lineBox is smaller than + // lineAscent+lineDescent) do we use the lineBox (some glyphs will + // go outside flowRegion) or the visual box. My feeling is that + // we should use the larger of the two. + + // We stated that for empty para elements it moves to the new flow + // region if the zero-height line is outside the flow region. In + // this case the para elements top-margin is used in the new flow + // region (and it's bottom-margin is collapsed with the next + // flowPara element if any). What happens when the first line of + // a non-empty flowPara doesn't fit (so the top margin does fit + // but the first line of text doesn't). I think the para should + // move to the next flow region and the top margin should apply in + // the new flow region. The top margin does not apply if + // subsequint lines move to a new flow region. + + // Note that line wrapping is done on visual bounds of glyph + // not the glyph advance (which often includes some whitespace + // after the right edge of the glyph char). + // // How are Margins done? Can't figure out Box size until // after we know the margins. @@ -1818,8 +1839,14 @@ // bit as well as grow (pretty easy to add). // // This Only does horizontal languages. - // text-decoration won't work on this text. - // Soft hyphen isn't handled yet. + // Supports Zero Width Spaces (0x200B) Zero Width Joiner( 0x200D), + // and soft hyphens (0x00AD). + // + // Does not properly handle Bi-DI languages (does text wrapping on + // display order not logical order). + // + // Does not drop leading non-printing chars on a line.. + /** * This will wrap the text associated with <tt>aci</tt> and * <tt>layouts</tt>. @@ -1853,8 +1880,8 @@ Iterator flowRectsIter = flowRects.iterator(); // Get info for new flow rect. Rectangle2D cRect = (Rectangle2D)flowRectsIter.next(); - float y0 = (float)cRect.getY(); - float x0, width, height; + float y0, x0, width, height; + height = (float)cRect.getHeight(); boolean lineHeightRelative = true; float lineHeight = 1.0f; @@ -1873,11 +1900,29 @@ Iterator epi = extraP.iterator(); while (epi.hasNext()) { MarginInfo emi = (MarginInfo)epi.next(); - dy += ((prevBotMargin > emi.getTopMargin()) - ? prevBotMargin - : emi.getTopMargin()); + float inc = ((prevBotMargin > emi.getTopMargin()) + ? prevBotMargin + : emi.getTopMargin()); + if ((dy + inc <= height) && + !emi.isFlowRegionBreak()) { + dy += inc; + } else { + // Move to next flow region.. + if (!flowRectsIter.hasNext()) { + cRect = null; + break; // No flow rect stop layout here... + } + + cRect = (Rectangle2D)flowRectsIter.next(); + height = (float)cRect.getHeight(); + + // New rect so no previous row to consider... + dy = emi.getTopMargin(); + } prevBotMargin = emi.getBottomMargin(); } + + if (cRect == null) break; } } aci.first(); @@ -1903,11 +1948,27 @@ continue; } - dy += ((prevBotMargin > mi.getTopMargin()) ? - prevBotMargin : mi.getTopMargin()); + float inc = ((prevBotMargin > mi.getTopMargin()) + ? prevBotMargin : mi.getTopMargin()); + if (dy + inc <= height) { + dy += inc; + } else { + // Move to next flow region.. + if (!flowRectsIter.hasNext()) { + cRect = null; + break; // No flow rect stop layout here... + } + + cRect = (Rectangle2D)flowRectsIter.next(); + height = (float)cRect.getHeight(); + + // New rect so no previous row to consider... + dy = mi.getTopMargin(); + } prevBotMargin = mi.getBottomMargin(); x0 = (float)cRect.getX() + mi.getLeftMargin(); + y0 = (float)cRect.getY(); width = (float)(cRect.getWidth() - (mi.getLeftMargin()+mi.getRightMargin())); height = (float)cRect.getHeight(); @@ -1918,13 +1979,36 @@ GlyphIterator gi = new GlyphIterator(aci, gv); GlyphIterator breakGI = null, newBreakGI = null; GlyphIterator lineGI = gi.copy(); + boolean firstLine = true; while (!gi.done()) { boolean doBreak = false; boolean partial = false; - if (gi.isPrinting() && - (breakGI != null) && // Don't break at first char in line - (gi.getAdv() > width)) { + if (gi.isPrinting() && (gi.getAdv() > width)) { + if (breakGI == null) { + // first char on line didn't fit. + // move to next flow rect. + if (!flowRectsIter.hasNext()) { + cRect = null; + gi = lineGI.copy(gi); + break; // No flow rect stop layout here... + } + + cRect = (Rectangle2D)flowRectsIter.next(); + x0 = (float) cRect.getX() + mi.getLeftMargin(); + y0 = (float) cRect.getY(); + width = (float)(cRect.getWidth() - + (mi.getLeftMargin()+ + mi.getRightMargin())); + height = (float)cRect.getHeight(); + + // New rect so no previous row to consider... + dy = firstLine?mi.getTopMargin():0; ; + prevDesc = 0; + gi = lineGI.copy(gi); + continue; + } + gi = breakGI.copy(gi); // Back up to break loc... nextLineMult = 1; @@ -1992,7 +2076,11 @@ float newDesc = halfLeading + gi.getMaxDescent(); dy += ladv; - if ((dy + newDesc) > height) { + float bottomEdge = newDesc; + if (newDesc < gi.getMaxDescent()) + bottomEdge = gi.getMaxDescent(); + + if ((dy + bottomEdge) > height) { // The current Line doesn't fit in the // current flow rectangle so we need to // move line to the next flow rect. @@ -2017,7 +2105,7 @@ height = (float)cRect.getHeight(); // New rect so no previous row to consider... - dy = 0; // mi.getTopMargin(); + dy = firstLine?mi.getTopMargin():0; ; prevDesc = 0; // previous flows? @@ -2038,6 +2126,7 @@ width, partial)); gi.newLine(); + firstLine = false; // The line fits in the current flow rectangle. lineGI = gi.copy(lineGI); breakGI = null; @@ -2049,6 +2138,16 @@ gv.setGlyphVisible(idx++, false); layoutChunk(aci, gv, justification, lineInfos); + + if (mi.isFlowRegionBreak()) { + // Move to next flow region.. + cRect = null; + if (flowRectsIter.hasNext()) { + cRect = (Rectangle2D)flowRectsIter.next(); + height = (float)cRect.getHeight(); + dy = mi.getTopMargin(); + } + } } } 1.2 +15 -11 xml-batik/sources/org/apache/batik/gvt/text/MarginInfo.java Index: MarginInfo.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/gvt/text/MarginInfo.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- MarginInfo.java 29 Mar 2002 20:00:55 -0000 1.1 +++ MarginInfo.java 12 Apr 2002 14:36:48 -0000 1.2 @@ -14,19 +14,22 @@ public final static int JUSTIFY_END = 2; public final static int JUSTIFY_FULL = 3; - protected float top; - protected float right; - protected float bottom; - protected float left; - protected int justification; + protected float top; + protected float right; + protected float bottom; + protected float left; + protected int justification; + protected boolean flowRegionBreak; + public MarginInfo(float top, float right, float bottom, float left, - int justification) { + int justification, boolean flowRegionBreak) { this.top = top; this.right = right; this.bottom = bottom; this.left = left; this.justification = justification; + this.flowRegionBreak = flowRegionBreak; } public MarginInfo(float margin, int justification) { @@ -39,9 +42,10 @@ this.bottom = margin; this.left = margin; } - public float getTopMargin() { return top; } - public float getRightMargin() { return right; } - public float getBottomMargin() { return bottom; } - public float getLeftMargin() { return left; } - public int getJustification() { return justification; } + public float getTopMargin() { return top; } + public float getRightMargin() { return right; } + public float getBottomMargin() { return bottom; } + public float getLeftMargin() { return left; } + public int getJustification() { return justification; } + public boolean isFlowRegionBreak() { return flowRegionBreak; } }
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]