git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@194007 13f79535-47bb-0310-9956-ffa450edef68tags/fop-0_17_0
@@ -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> |
@@ -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> |
@@ -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) { | |||
@@ -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); | |||
} | |||
@@ -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); | |||
} | |||
} |
@@ -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(); |
@@ -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; | |||
} |
@@ -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 + |
@@ -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; | |||
} | |||
} |
@@ -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; | |||
} |
@@ -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); | |||
} | |||
} | |||
} | |||
/** |