diff options
-rw-r--r-- | docs/examples/fo/textdeko.fo | 95 | ||||
-rw-r--r-- | src/codegen/foproperties.xml | 5 | ||||
-rw-r--r-- | src/org/apache/fop/fo/FOText.java | 20 | ||||
-rw-r--r-- | src/org/apache/fop/fo/flow/Inline.java | 10 | ||||
-rw-r--r-- | src/org/apache/fop/fo/flow/PageNumber.java | 5 | ||||
-rw-r--r-- | src/org/apache/fop/fo/flow/PageNumberCitation.java | 4 | ||||
-rw-r--r-- | src/org/apache/fop/layout/BlockArea.java | 259 | ||||
-rw-r--r-- | src/org/apache/fop/layout/LineArea.java | 52 | ||||
-rw-r--r-- | src/org/apache/fop/layout/inline/InlineArea.java | 16 | ||||
-rw-r--r-- | src/org/apache/fop/layout/inline/InlineSpace.java | 33 | ||||
-rw-r--r-- | src/org/apache/fop/render/pdf/PDFRenderer.java | 70 |
11 files changed, 425 insertions, 144 deletions
diff --git a/docs/examples/fo/textdeko.fo b/docs/examples/fo/textdeko.fo index 24f55132f..f12fc3333 100644 --- a/docs/examples/fo/textdeko.fo +++ b/docs/examples/fo/textdeko.fo @@ -64,7 +64,7 @@ element, it affects all boxes generated by the element. </fo:block> - <fo:block font-size="12pt" font-family="sans-serif" line-height="15pt" space-after.optimum="3pt"> + <fo:block font-size="12pt" font-family="sans-serif" line-height="15pt" space-after.optimum="13pt"> Example: <fo:inline text-decoration="underline">underline</fo:inline> </fo:block> @@ -96,10 +96,10 @@ </fo:block> <fo:block font-size="12pt" font-family="sans-serif" line-height="15pt" text-align="justify" space-after.optimum="3pt"> - The following text decorations are defined in the WD: + The following text decorations are defined in the CR: </fo:block> - <fo:list-block> + <fo:list-block space-after.optimum="13pt"> <fo:list-item> <fo:list-item-label> @@ -156,8 +156,97 @@ </fo:list-item-body> </fo:list-item> + <fo:list-item> + <fo:list-item-label> + <fo:block>•</fo:block> + </fo:list-item-label> + <fo:list-item-body> + <fo:block> + <fo:inline text-decoration="no-underline">no-underline</fo:inline> + </fo:block> + </fo:list-item-body> + </fo:list-item> + + <fo:list-item> + <fo:list-item-label> + <fo:block>•</fo:block> + </fo:list-item-label> + <fo:list-item-body> + <fo:block> + <fo:inline text-decoration="no-overline">no-overline</fo:inline> + </fo:block> + </fo:list-item-body> + </fo:list-item> + + <fo:list-item> + <fo:list-item-label> + <fo:block>•</fo:block> + </fo:list-item-label> + <fo:list-item-body> + <fo:block> + <fo:inline text-decoration="no-line-through">no-line-through</fo:inline> + </fo:block> + </fo:list-item-body> + </fo:list-item> + + <fo:list-item> + <fo:list-item-label> + <fo:block>•</fo:block> + </fo:list-item-label> + <fo:list-item-body> + <fo:block> + <fo:inline text-decoration="no-blink">no-blink</fo:inline> + </fo:block> + </fo:list-item-body> + </fo:list-item> + </fo:list-block> + <fo:block font-size="12pt" space-after.optimum="3pt"> + <fo:inline text-decoration="underline overline">Combination</fo:inline> of property + values should also be possible, but does not work in FOP at the moment. + </fo:block> + + <fo:block font-size="12pt" space-after.optimum="13pt"> + <fo:inline font-family="monospace"><![CDATA[<fo:inline text-decoration="underline overline"> + Combination</fo:inline>]]></fo:inline> + </fo:block> + + + <fo:block space-after.optimum="13pt"> + And now <fo:inline text-decoration="underline">more than a word...</fo:inline> + </fo:block> + + <fo:block space-after.optimum="13pt" font-size="14pt" > + <fo:inline text-decoration="underline"> + This is a whole block wrapped in fo:inline with the property text-decoration="underline". + Some more Text to get at least two lines. + </fo:inline> + </fo:block> + + <fo:block font-size="22pt" + font-family="sans-serif" + line-height="22pt" + space-after.optimum="10pt" + text-align="start"> + This is simple test with a <fo:inline text-decoration="overline">bigger font-size</fo:inline>. + </fo:block> + <fo:block font-size="15pt" + font-family="monospace" + line-height="15pt" + space-after.optimum="10pt" + text-align="start"> + This is simple test with a <fo:inline text-decoration="line-through">monospaced font</fo:inline>. + </fo:block> + + <fo:block font-size="15pt" + line-height="15pt" + space-after.optimum="10pt" + text-align="start"> + What about underlining of whitespace only<fo:inline text-decoration="underline"> </fo:inline>? + </fo:block> + + </fo:flow> </fo:page-sequence> </fo:root> diff --git a/src/codegen/foproperties.xml b/src/codegen/foproperties.xml index a436fb24c..ad03a9477 100644 --- a/src/codegen/foproperties.xml +++ b/src/codegen/foproperties.xml @@ -1069,6 +1069,11 @@ <value const="UNDERLINE">underline</value> <value const="OVERLINE">overline</value> <value const="LINE_THROUGH">line-through</value> + <value const="BLINK">blink</value> + <value const="NO_UNDERLINE">no-underline</value> + <value const="NO_OVERLINE">no-overline</value> + <value const="NO_LINE_THROUGH">no-line-through</value> + <value const="NO_BLINK">no-blink</value> </enumeration> <default>none</default> </property> diff --git a/src/org/apache/fop/fo/FOText.java b/src/org/apache/fop/fo/FOText.java index debc06e14..6fc253fa5 100644 --- a/src/org/apache/fop/fo/FOText.java +++ b/src/org/apache/fop/fo/FOText.java @@ -56,6 +56,7 @@ import org.apache.fop.layout.Area; import org.apache.fop.messaging.MessageHandler; import org.apache.fop.layout.BlockArea; import org.apache.fop.layout.FontState; +import org.apache.fop.layout.TextState; import org.apache.fop.datatypes.*; import org.apache.fop.fo.properties.*; import org.apache.fop.apps.FOPException; @@ -81,6 +82,8 @@ public class FOText extends FONode { protected boolean overlined = false; protected boolean lineThrough = false; + TextState ts; + public FOText(char[] chars, int s, int e, FObj parent) { super(parent); @@ -95,6 +98,15 @@ public class FOText extends FONode { this.underlined = ul; } + public void setOverlined(boolean ol) { + this.overlined = ol; + } + + public void setLineThrough(boolean lt) { + this.lineThrough = lt; + } + + public boolean willCreateArea() { this.whiteSpaceCollapse = this.parent.properties.get( @@ -143,14 +155,18 @@ public class FOText extends FONode { this.wrapOption = this.parent.properties.get("wrap-option").getEnum(); this.whiteSpaceCollapse = this.parent.properties.get( - "white-space-collapse").getEnum(); + "white-space-collapse").getEnum(); + this.ts = new TextState(); + ts.setUnderlined(underlined); + ts.setOverlined(overlined); + ts.setLineThrough(lineThrough); this.marker = this.start; } int orig_start = this.marker; this.marker = ((BlockArea) area).addText(fs, red, green, blue, wrapOption, this.getLinkSet(), whiteSpaceCollapse, ca, - this.marker, length, underlined); + this.marker, length, ts); if (this.marker == -1) { diff --git a/src/org/apache/fop/fo/flow/Inline.java b/src/org/apache/fop/fo/flow/Inline.java index efc831028..598d4dbe4 100644 --- a/src/org/apache/fop/fo/flow/Inline.java +++ b/src/org/apache/fop/fo/flow/Inline.java @@ -91,6 +91,14 @@ public class Inline extends FObjMixed { this.underlined = true; } + if (textDecoration == TextDecoration.OVERLINE) { + this.overlined = true; + } + + if (textDecoration == TextDecoration.LINE_THROUGH) { + this.lineThrough = true; + } + if (parent.getName().equals("fo:flow")) { throw new FOPException("fo:inline can't be directly" + " under flow"); @@ -101,6 +109,8 @@ public class Inline extends FObjMixed { protected void addCharacters(char data[], int start, int length) { FOText ft = new FOText(data,start,length, this); ft.setUnderlined(underlined); + ft.setOverlined(overlined); + ft.setLineThrough(lineThrough); children.addElement(ft); } diff --git a/src/org/apache/fop/fo/flow/PageNumber.java b/src/org/apache/fop/fo/flow/PageNumber.java index 8eb8741ef..4dbe320fc 100644 --- a/src/org/apache/fop/fo/flow/PageNumber.java +++ b/src/org/apache/fop/fo/flow/PageNumber.java @@ -81,6 +81,7 @@ public class PageNumber extends FObj { float blue; int wrapOption; int whiteSpaceCollapse; + TextState ts; public PageNumber(FObj parent, PropertyList propertyList) { super(parent, propertyList); @@ -117,7 +118,7 @@ public class PageNumber extends FObj { this.wrapOption = this.properties.get("wrap-option").getEnum(); this.whiteSpaceCollapse = this.properties.get("white-space-collapse").getEnum(); - + ts = new TextState(); this.marker = 0; // initialize id @@ -128,7 +129,7 @@ public class PageNumber extends FObj { String p = Integer.toString(area.getPage().getNumber()); this.marker = ((BlockArea) area).addText(fs, red, green, blue, wrapOption, null, whiteSpaceCollapse, p.toCharArray(), - 0, p.length(), false); + 0, p.length(), ts); return new Status(Status.OK); } } diff --git a/src/org/apache/fop/fo/flow/PageNumberCitation.java b/src/org/apache/fop/fo/flow/PageNumberCitation.java index 16e979526..817a647e1 100644 --- a/src/org/apache/fop/fo/flow/PageNumberCitation.java +++ b/src/org/apache/fop/fo/flow/PageNumberCitation.java @@ -138,6 +138,7 @@ public class PageNumberCitation extends FObj { String pageNumber; String refId; String id; + TextState ts; public PageNumberCitation(FObj parent, PropertyList propertyList) { @@ -189,6 +190,7 @@ public class PageNumberCitation extends FObj { // create id this.id = this.properties.get("id").getString(); idReferences.createID(id); + ts = new TextState(); this.marker = 0; } @@ -204,7 +206,7 @@ public class PageNumberCitation extends FObj { this.marker = ((BlockArea) area).addText(fs, red, green, blue, wrapOption, null, whiteSpaceCollapse, pageNumber.toCharArray(), 0, pageNumber.length(), - false); + ts); } else { // add pageNumberCitation to area to be resolved during rendering BlockArea blockArea = (BlockArea)area; LineArea la = blockArea.getCurrentLineArea(); diff --git a/src/org/apache/fop/layout/BlockArea.java b/src/org/apache/fop/layout/BlockArea.java index 4defdde76..30744ef71 100644 --- a/src/org/apache/fop/layout/BlockArea.java +++ b/src/org/apache/fop/layout/BlockArea.java @@ -74,16 +74,16 @@ import org.apache.fop.messaging.MessageHandler; */ public class BlockArea extends Area { - /* relative to area container */ - protected int startIndent; - protected int endIndent; + /* relative to area container */ + protected int startIndent; + protected int endIndent; /* first line startIndent modifier */ - protected int textIndent; + protected int textIndent; - protected int lineHeight; + protected int lineHeight; - protected int halfLeading; + protected int halfLeading; /* text-align of all but the last line */ @@ -152,145 +152,145 @@ public class BlockArea extends Area { } } - // font-variant support : addText is a wrapper for addRealText - // added by Eric SCHAEFFER - public int addText(FontState fontState, float red, float green, - float blue, int wrapOption, LinkSet ls, - int whiteSpaceCollapse, char data[], int start, int end, - boolean ul) { - if (fontState.getFontVariant() == FontVariant.SMALL_CAPS) { - FontState smallCapsFontState; - try { - int smallCapsFontHeight = (int) (((double) fontState.getFontSize()) * 0.8d); - smallCapsFontState = new FontState( - fontState.getFontInfo(), - fontState.getFontFamily(), - fontState.getFontStyle(), - fontState.getFontWeight(), - smallCapsFontHeight, - FontVariant.NORMAL); - } catch (FOPException ex) { - smallCapsFontState = fontState; - MessageHandler.errorln("Error creating small-caps FontState: " + ex.getMessage()); - } - - // parse text for upper/lower case and call addRealText - char c; - boolean isLowerCase; - int caseStart; - FontState fontStateToUse; - for (int i = start; i < end; ) { - caseStart = i; - c = data[i]; - isLowerCase = (java.lang.Character.isLetter(c) && java.lang.Character.isLowerCase(c)); - while (isLowerCase == (java.lang.Character.isLetter(c) && java.lang.Character.isLowerCase(c))) { - if (isLowerCase) { - data[i] = java.lang.Character.toUpperCase(c); - } - i++; - if (i == end) - break; - c = data[i]; - } - if (isLowerCase) { - fontStateToUse = smallCapsFontState; - } else { - fontStateToUse = fontState; - } - int index = this.addRealText(fontStateToUse, red, green, blue, wrapOption, ls, - whiteSpaceCollapse, data, caseStart, i, ul); - if (index != -1) { - return index; - } - } - - return -1; - } - - // font-variant normal - return this.addRealText(fontState, red, green, blue, wrapOption, ls, - whiteSpaceCollapse, data, start, end, ul); - } - - protected int addRealText(FontState fontState, float red, float green, - float blue, int wrapOption, LinkSet ls, - int whiteSpaceCollapse, char data[], int start, int end, - boolean ul) { - int ts, te; - char[] ca; - - ts = start; - te = end; - ca = data; + // font-variant support : addText is a wrapper for addRealText + // added by Eric SCHAEFFER + public int addText(FontState fontState, float red, float green, + float blue, int wrapOption, LinkSet ls, + int whiteSpaceCollapse, char data[], int start, int end, + TextState textState) { + if (fontState.getFontVariant() == FontVariant.SMALL_CAPS) { + FontState smallCapsFontState; + try { + int smallCapsFontHeight = (int) (((double) fontState.getFontSize()) * 0.8d); + smallCapsFontState = new FontState( + fontState.getFontInfo(), + fontState.getFontFamily(), + fontState.getFontStyle(), + fontState.getFontWeight(), + smallCapsFontHeight, + FontVariant.NORMAL); + } catch (FOPException ex) { + smallCapsFontState = fontState; + MessageHandler.errorln("Error creating small-caps FontState: " + ex.getMessage()); + } + + // parse text for upper/lower case and call addRealText + char c; + boolean isLowerCase; + int caseStart; + FontState fontStateToUse; + for (int i = start; i < end; ) { + caseStart = i; + c = data[i]; + isLowerCase = (java.lang.Character.isLetter(c) && java.lang.Character.isLowerCase(c)); + while (isLowerCase == (java.lang.Character.isLetter(c) && java.lang.Character.isLowerCase(c))) { + if (isLowerCase) { + data[i] = java.lang.Character.toUpperCase(c); + } + i++; + if (i == end) + break; + c = data[i]; + } + if (isLowerCase) { + fontStateToUse = smallCapsFontState; + } else { + fontStateToUse = fontState; + } + int index = this.addRealText(fontStateToUse, red, green, blue, wrapOption, ls, + whiteSpaceCollapse, data, caseStart, i, textState); + if (index != -1) { + return index; + } + } + + return -1; + } - if (currentHeight + currentLineArea.getHeight() > maxHeight) { - return start; - } + // font-variant normal + return this.addRealText(fontState, red, green, blue, wrapOption, ls, + whiteSpaceCollapse, data, start, end, textState); + } - this.currentLineArea.changeFont(fontState); - this.currentLineArea.changeColor(red, green, blue); - this.currentLineArea.changeWrapOption(wrapOption); - this.currentLineArea.changeWhiteSpaceCollapse(whiteSpaceCollapse); - this.currentLineArea.changeHyphenation(language, country, hyphenate, - hyphenationChar, hyphenationPushCharacterCount, - hyphenationRemainCharacterCount); - if (ls != null) { - this.currentLinkSet = ls; - ls.setYOffset(currentHeight); - } + protected int addRealText(FontState fontState, float red, float green, + float blue, int wrapOption, LinkSet ls, + int whiteSpaceCollapse, char data[], int start, int end, + TextState textState) { + int ts, te; + char[] ca; - ts = this.currentLineArea.addText(ca, ts, te, ls, ul); - this.hasLines = true; + ts = start; + te = end; + ca = data; - while (ts != -1) { - this.currentLineArea.align(this.align); - this.addLineArea(this.currentLineArea); + if (currentHeight + currentLineArea.getHeight() > maxHeight) { + return start; + } - this.currentLineArea = - new LineArea(fontState, lineHeight, halfLeading, - allocationWidth, startIndent, endIndent, - currentLineArea); - if (currentHeight + currentLineArea.getHeight() > - this.maxHeight) { - return ts; - } - this.currentLineArea.changeFont(fontState); - this.currentLineArea.changeColor(red, green, blue); - this.currentLineArea.changeWrapOption(wrapOption); - this.currentLineArea.changeWhiteSpaceCollapse( - whiteSpaceCollapse); - this.currentLineArea.changeHyphenation(language, country, hyphenate, - hyphenationChar, hyphenationPushCharacterCount, - hyphenationRemainCharacterCount); - if (ls != null) { - ls.setYOffset(currentHeight); - } + this.currentLineArea.changeFont(fontState); + this.currentLineArea.changeColor(red, green, blue); + this.currentLineArea.changeWrapOption(wrapOption); + this.currentLineArea.changeWhiteSpaceCollapse(whiteSpaceCollapse); + this.currentLineArea.changeHyphenation(language, country, hyphenate, + hyphenationChar, hyphenationPushCharacterCount, + hyphenationRemainCharacterCount); + if (ls != null) { + this.currentLinkSet = ls; + ls.setYOffset(currentHeight); + } - ts = this.currentLineArea.addText(ca, ts, te, ls, ul); - } - return -1; - } + ts = this.currentLineArea.addText(ca, ts, te, ls, textState); + this.hasLines = true; + + while (ts != -1) { + this.currentLineArea.align(this.align); + this.addLineArea(this.currentLineArea); + + this.currentLineArea = + new LineArea(fontState, lineHeight, halfLeading, + allocationWidth, startIndent, endIndent, + currentLineArea); + if (currentHeight + currentLineArea.getHeight() > + this.maxHeight) { + return ts; + } + this.currentLineArea.changeFont(fontState); + this.currentLineArea.changeColor(red, green, blue); + this.currentLineArea.changeWrapOption(wrapOption); + this.currentLineArea.changeWhiteSpaceCollapse( + whiteSpaceCollapse); + this.currentLineArea.changeHyphenation(language, country, hyphenate, + hyphenationChar, hyphenationPushCharacterCount, + hyphenationRemainCharacterCount); + if (ls != null) { + ls.setYOffset(currentHeight); + } + + ts = this.currentLineArea.addText(ca, ts, te, ls, textState); + } + return -1; + } - /** + /** * adds a leader to current line area of containing block area * the actual leader area is created in the line area * * @return int +1 for success and -1 for none */ - public int addLeader(FontState fontState, float red, float green, - float blue, int leaderPattern, int leaderLengthMinimum, - int leaderLengthOptimum, int leaderLengthMaximum, - int ruleThickness, int ruleStyle, int leaderPatternWidth, - int leaderAlignment) { + public int addLeader(FontState fontState, float red, float green, + float blue, int leaderPattern, int leaderLengthMinimum, + int leaderLengthOptimum, int leaderLengthMaximum, + int ruleThickness, int ruleStyle, int leaderPatternWidth, + int leaderAlignment) { //this should start a new page - if (currentHeight + currentLineArea.getHeight() > maxHeight) { - return -1; - } + if (currentHeight + currentLineArea.getHeight() > maxHeight) { + return -1; + } - this.currentLineArea.changeFont(fontState); - this.currentLineArea.changeColor(red, green, blue); + this.currentLineArea.changeFont(fontState); + this.currentLineArea.changeColor(red, green, blue); //check whether leader fits into the (rest of the) line //using length.optimum to determine where to break the line as defined @@ -393,6 +393,7 @@ public class BlockArea extends Area { return endIndent; } +// KL: I think we should just return startIndent here! public int getStartIndent() { return startIndent + paddingLeft + borderWidthLeft; } diff --git a/src/org/apache/fop/layout/LineArea.java b/src/org/apache/fop/layout/LineArea.java index ebbeaeb4c..cd3d1a8e4 100644 --- a/src/org/apache/fop/layout/LineArea.java +++ b/src/org/apache/fop/layout/LineArea.java @@ -136,6 +136,11 @@ public class LineArea extends Area { /* the width of the pendingAreas */ protected int pendingWidth = 0; + /* text-decoration of the previous text */ + protected boolean prevUlState = false; + protected boolean prevOlState = false; + protected boolean prevLTState = false; + public LineArea(FontState fontState, int lineHeight, int halfLeading, int allocationWidth, int startIndent, int endIndent, LineArea prevLineArea) { @@ -199,7 +204,7 @@ public class LineArea extends Area { * @return int character position */ public int addText(char odata[], int start, int end, LinkSet ls, - boolean ul) { + TextState textState) { // this prevents an array index out of bounds // which occurs when some text is laid out again. if(start == -1) return -1; @@ -259,7 +264,17 @@ public class LineArea extends Area { // was some) if (spaceWidth > 0) { - addChild(new InlineSpace(spaceWidth)); + InlineSpace is = new InlineSpace(spaceWidth); + if (prevUlState) { + is.setUnderlined(textState.getUnderlined()); + } + if (prevOlState) { + is.setOverlined(textState.getOverlined()); + } + if (prevLTState) { + is.setLineThrough(textState.getLineThrough()); + } + addChild(is); finalWidth += spaceWidth; spaceWidth = 0; } @@ -295,7 +310,13 @@ public class LineArea extends Area { new String(data, wordStart, wordLength), wordWidth); ia.setYOffset(placementOffset); - ia.setUnderlined(ul); + ia.setUnderlined(textState.getUnderlined()); + prevUlState = textState.getUnderlined(); + ia.setOverlined(textState.getOverlined()); + prevOlState = textState.getOverlined(); + ia.setLineThrough(textState.getLineThrough()); + prevLTState = textState.getLineThrough(); + addChild(ia); if (ls != null) { Rectangle lr = new Rectangle(finalWidth, 0, @@ -407,14 +428,35 @@ public class LineArea extends Area { } } // end of iteration over text - if (prev == TEXT) { + if (prev == TEXT) { + + if (spaceWidth > 0) { + InlineSpace pis = new InlineSpace(spaceWidth); + if (prevUlState) { + pis.setUnderlined(textState.getUnderlined()); + } + if (prevOlState) { + pis.setOverlined(textState.getOverlined()); + } + if (prevLTState) { + pis.setLineThrough(textState.getLineThrough()); + } + pendingAreas.addElement(pis); + pendingWidth += spaceWidth; + spaceWidth = 0; + } WordArea pia = new WordArea(currentFontState, this.red, this.green, this.blue, new String(data, wordStart, wordLength), wordWidth); pia.setYOffset(placementOffset); - pia.setUnderlined(ul); + pia.setUnderlined(textState.getUnderlined()); + prevUlState = textState.getUnderlined(); + pia.setOverlined(textState.getOverlined()); + prevOlState = textState.getOverlined(); + pia.setLineThrough(textState.getLineThrough()); + prevLTState = textState.getLineThrough(); if (ls != null) { Rectangle lr = new Rectangle(finalWidth + spaceWidth + diff --git a/src/org/apache/fop/layout/inline/InlineArea.java b/src/org/apache/fop/layout/inline/InlineArea.java index 5193b9752..c0dedb4b4 100644 --- a/src/org/apache/fop/layout/inline/InlineArea.java +++ b/src/org/apache/fop/layout/inline/InlineArea.java @@ -126,4 +126,20 @@ public abstract class InlineArea extends Area { return this.underlined; } + public void setOverlined(boolean ol) { + this.overlined = ol; + } + + public boolean getOverlined() { + return this.overlined; + } + + public void setLineThrough(boolean lt) { + this.lineThrough = lt; + } + + public boolean getLineThrough() { + return this.lineThrough; + } + } diff --git a/src/org/apache/fop/layout/inline/InlineSpace.java b/src/org/apache/fop/layout/inline/InlineSpace.java index 1e3b58001..235d3afdd 100644 --- a/src/org/apache/fop/layout/inline/InlineSpace.java +++ b/src/org/apache/fop/layout/inline/InlineSpace.java @@ -56,6 +56,12 @@ import org.apache.fop.layout.*; public class InlineSpace extends Space { private int size; // in millipoints private boolean resizeable = true; //to disallow size changes during justification of a line + + // Textdecoration + protected boolean underlined = false; + protected boolean overlined = false; + protected boolean lineThrough = false; + public InlineSpace(int amount) { this.size = amount; @@ -66,6 +72,33 @@ public class InlineSpace extends Space { this.size = amount; } + /** + * @param ul true if text should be underlined + */ + public void setUnderlined(boolean ul) { + this.underlined = ul; + } + + public boolean getUnderlined() { + return this.underlined; + } + + public void setOverlined(boolean ol) { + this.overlined = ol; + } + + public boolean getOverlined() { + return this.overlined; + } + + public void setLineThrough(boolean lt) { + this.lineThrough = lt; + } + + public boolean getLineThrough() { + return this.lineThrough; + } + public int getSize() { return size; } diff --git a/src/org/apache/fop/render/pdf/PDFRenderer.java b/src/org/apache/fop/render/pdf/PDFRenderer.java index d15d68058..21a8e3e7b 100644 --- a/src/org/apache/fop/render/pdf/PDFRenderer.java +++ b/src/org/apache/fop/render/pdf/PDFRenderer.java @@ -140,6 +140,20 @@ public class PDFRenderer implements Renderer { /** the current colour for use in svg */ private PDFColor currentColour = new PDFColor(0, 0, 0); + + // previous values used for text-decoration drawing + int prevUnderlineXEndPos; + int prevUnderlineYEndPos; + int prevUnderlineSize; + PDFColor prevUnderlineColor; + int prevOverlineXEndPos; + int prevOverlineYEndPos; + int prevOverlineSize; + PDFColor prevOverlineColor; + int prevLineThroughXEndPos; + int prevLineThroughYEndPos; + int prevLineThroughSize; + PDFColor prevLineThroughColor; /** * create the PDF renderer @@ -403,12 +417,16 @@ public class PDFRenderer implements Renderer { * @param area the block area to render */ public void renderBlockArea(BlockArea area) { + // KLease: Temporary test to fix block positioning + // Offset ypos by padding and border widths + // this.currentYPosition -= (area.getPaddingTop() + area.borderWidthTop); doFrame(area); Enumeration e = area.getChildren().elements(); while (e.hasMoreElements()) { Box b = (Box) e.nextElement(); b.render(this); } + // this.currentYPosition -= (area.getPaddingBottom() + area.borderWidthBottom); } /** @@ -632,8 +650,34 @@ public class PDFRenderer implements Renderer { pdf = pdf.append(") Tj\n"); if (area.getUnderlined()) { - addLine(rx, bl - size / 10, rx + area.getContentWidth(), - bl - size / 10, size / 14, theAreaColor); + int yPos = bl - size/10; + addLine(rx, yPos, rx + area.getContentWidth(), + yPos, size/14, theAreaColor); + // save position for underlining a following InlineSpace + prevUnderlineXEndPos = rx + area.getContentWidth(); + prevUnderlineYEndPos = yPos; + prevUnderlineSize = size/14; + prevUnderlineColor = theAreaColor; + } + + if (area.getOverlined()) { + int yPos = bl + area.getFontState().getAscender() + size/10; + addLine(rx, yPos, rx + area.getContentWidth(), + yPos, size/14, theAreaColor); + prevOverlineXEndPos = rx + area.getContentWidth(); + prevOverlineYEndPos = yPos; + prevOverlineSize = size/14; + prevOverlineColor = theAreaColor; + } + + if (area.getLineThrough()) { + int yPos = bl + area.getFontState().getAscender() * 3/8; + addLine(rx, yPos, rx + area.getContentWidth(), + yPos, size/14, theAreaColor); + prevLineThroughXEndPos = rx + area.getContentWidth(); + prevLineThroughYEndPos = yPos; + prevLineThroughSize = size/14; + prevLineThroughColor = theAreaColor; } currentStream.add(pdf.toString()); @@ -648,6 +692,28 @@ public class PDFRenderer implements Renderer { */ public void renderInlineSpace(InlineSpace space) { this.currentXPosition += space.getSize(); + if (space.getUnderlined()) { + if (prevUnderlineColor != null) { + addLine(prevUnderlineXEndPos, prevUnderlineYEndPos, + prevUnderlineXEndPos + space.getSize(), + prevUnderlineYEndPos, prevUnderlineSize, prevUnderlineColor); + } + } + if (space.getOverlined()) { + if (prevOverlineColor != null) { + addLine(prevOverlineXEndPos, prevOverlineYEndPos, + prevOverlineXEndPos + space.getSize(), + prevOverlineYEndPos, prevOverlineSize, prevOverlineColor); + } + } + if (space.getLineThrough()) { + if (prevLineThroughColor != null) { + addLine(prevLineThroughXEndPos, prevLineThroughYEndPos, + prevLineThroughXEndPos + space.getSize(), + prevLineThroughYEndPos, prevLineThroughSize, prevLineThroughColor); + } + } + } /** |