/* $Id: FOText.java,v 1.19 2001/05/19 00:59:17 arved Exp $
* 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.fo;
// FOP
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.*;
import org.apache.fop.datatypes.*;
import org.apache.fop.fo.properties.*;
import org.apache.fop.apps.FOPException;
import org.apache.fop.system.BufferManager;
/**
* a text node in the formatting object tree
*/
public class FOText extends FONode {
// protected char[] ca;
protected int start;
protected int length;
FontState fs;
float red;
float green;
float blue;
int wrapOption;
int whiteSpaceCollapse;
int verticalAlign;
// Textdecoration
protected boolean underlined = false;
protected boolean overlined = false;
protected boolean lineThrough = false;
TextState ts;
public FOText(char[] chars, int s, int e, FObj parent) {
super(parent);
this.start = 0;
char ca[] = new char[e - s];
for (int i = s; i < e; i++)
ca[i - s] = chars[i];
this.length = e - s;
this.bufferManager = parent.bufferManager;
if (this.bufferManager != null) {
bufferManager.writeBuffer((Object) this, ca);
}
else {
System.out.println("abnormal exit");
System.exit(0);
}
}
public void setUnderlined(boolean ul) {
this.underlined = ul;
}
public void setOverlined(boolean ol) {
this.overlined = ol;
}
public void setLineThrough(boolean lt) {
this.lineThrough = lt;
}
public boolean willCreateArea()
{
char ca[] = this.bufferManager.readBuffer((Object) this);
this.whiteSpaceCollapse = this.parent.properties.get(
"white-space-collapse").getEnum();
if(this.whiteSpaceCollapse == WhiteSpaceCollapse.FALSE && length > 0) {
return true;
}
for (int i = start; i < start + length; i++) {
char ch = ca[i];
if (!((ch == ' ') || (ch == '\n') || (ch == '\r') ||
(ch == '\t'))) { // whitespace
return true;
}
}
return false;
}
public Status layout(Area area) throws FOPException {
char ca[] = this.bufferManager.readBuffer((Object) this);
if (!(area instanceof BlockArea)) {
MessageHandler.errorln("WARNING: text outside block area" +
new String(ca, start, length));
return new Status(Status.OK);
}
if (this.marker == START) {
String fontFamily =
this.parent.properties.get("font-family").getString();
String fontStyle =
this.parent.properties.get("font-style").getString();
String fontWeight =
this.parent.properties.get("font-weight").getString();
int fontSize = this.parent.properties.get(
"font-size").getLength().mvalue();
// font-variant support
// added by Eric SCHAEFFER
int fontVariant = this.parent.properties.get("font-variant").getEnum();
this.fs = new FontState(area.getFontInfo(), fontFamily,
fontStyle, fontWeight, fontSize, fontVariant);
ColorType c =
this.parent.properties.get("color").getColorType();
this.red = c.red();
this.green = c.green();
this.blue = c.blue();
this.verticalAlign = this.parent.properties.get("vertical-align").getEnum();
this.wrapOption =
this.parent.properties.get("wrap-option").getEnum();
this.whiteSpaceCollapse = this.parent.properties.get(
"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 = addText((BlockArea)area, fs, red, green, blue,
wrapOption, this.getLinkSet(), whiteSpaceCollapse, ca,
this.marker, length, ts, verticalAlign);
if (this.marker == -1) {
// commented out by Hani Elabed, 11/28/2000
// if this object has been laid out
// successfully, leave it alone....
// Now, to prevent the array index out of
// bound of LineArea.addText(), I have added
// the following test at the beginning of that method.
// if( start == -1 ) return -1;
// see LineArea.addText()
//this.marker = 0;
return new Status(Status.OK);
} else if (this.marker != orig_start) {
return new Status(Status.AREA_FULL_SOME);
} else {
return new Status(Status.AREA_FULL_NONE);
}
}
// font-variant support : addText is a wrapper for addRealText
// added by Eric SCHAEFFER
public static int addText(BlockArea ba, FontState fontState, float red, float green,
float blue, int wrapOption, LinkSet ls,
int whiteSpaceCollapse, char data[], int start, int end,
TextState textState, int vAlign) {
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 = addRealText(ba, fontStateToUse, red, green, blue, wrapOption, ls,
whiteSpaceCollapse, data, caseStart, i, textState, vAlign);
if (index != -1) {
return index;
}
}
return -1;
}
// font-variant normal
return addRealText(ba, fontState, red, green, blue, wrapOption, ls,
whiteSpaceCollapse, data, start, end, textState, vAlign);
}
protected static int addRealText(BlockArea ba, FontState fontState, float red, float green,
float blue, int wrapOption, LinkSet ls,
int whiteSpaceCollapse, char data[], int start, int end,
TextState textState, int vAlign) {
int ts, te;
char[] ca;
ts = start;
te = end;
ca = data;
LineArea la = ba.getCurrentLineArea();
if (la == null) {
return start;
}
la.changeFont(fontState);
la.changeColor(red, green, blue);
la.changeWrapOption(wrapOption);
la.changeWhiteSpaceCollapse(whiteSpaceCollapse);
la.changeVerticalAlign(vAlign);
// la.changeHyphenation(language, country, hyphenate,
// hyphenationChar, hyphenationPushCharacterCount,
// hyphenationRemainCharacterCount);
ba.setupLinkSet(ls);
ts = la.addText(ca, ts, te, ls, textState);
// this.hasLines = true;
while (ts != -1) {
la = ba.createNextLineArea();
if (la == null) {
return ts;
}
la.changeFont(fontState);
la.changeColor(red, green, blue);
la.changeWrapOption(wrapOption);
la.changeWhiteSpaceCollapse(
whiteSpaceCollapse);
// la.changeHyphenation(language, country, hyphenate,
// hyphenationChar, hyphenationPushCharacterCount,
// hyphenationRemainCharacterCount);
ba.setupLinkSet(ls);
ts = la.addText(ca, ts, te, ls, textState);
}
return -1;
}
}