if (afpFont.isEmbeddable()) {
try {
documentHandler.getResourceManager().embedFont(afpFont, charSet);
} catch (IOException ioe) {
throw new IFException("Error while embedding font resources", ioe);
}
}
AbstractPageObject page = getDataStream().getCurrentPage();
PresentationTextObject pto = page.getPresentationTextObject();
try {
pto.createControlSequences(new PtocaProducer() {
public void produce(PtocaBuilder builder) throws IOException {
Point p = getPaintingState().getPoint(coords[X], coords[Y]);
builder.setTextOrientation(getPaintingState().getRotation());
builder.absoluteMoveBaseline(p.y);
builder.absoluteMoveInline(p.x);
builder.setExtendedTextColor(state.getTextColor());
builder.setCodedFont((byte)fontReference);
int l = text.length();
int dxl = (dx != null ? dx.length : 0);
StringBuffer sb = new StringBuffer();
if (dxl > 0 && dx[0] != 0) {
int dxu = Math.round(unitConv.mpt2units(dx[0]));
builder.relativeMoveInline(-dxu);
}
//Following are two variants for glyph placement.
//SVI does not seem to be implemented in the same way everywhere, so
//a fallback alternative is preserved here.
final boolean usePTOCAWordSpacing = true;
if (usePTOCAWordSpacing) {
int interCharacterAdjustment = 0;
if (letterSpacing != 0) {
interCharacterAdjustment = Math.round(unitConv.mpt2units(
letterSpacing));
}
builder.setInterCharacterAdjustment(interCharacterAdjustment);
int spaceWidth = font.getCharWidth(CharUtilities.SPACE);
int fixedSpaceCharacterIncrement = Math.round(unitConv.mpt2units(
spaceWidth + letterSpacing));
int varSpaceCharacterIncrement = fixedSpaceCharacterIncrement;
if (wordSpacing != 0) {
varSpaceCharacterIncrement = Math.round(unitConv.mpt2units(
spaceWidth + wordSpacing + letterSpacing));
}
builder.setVariableSpaceCharacterIncrement(varSpaceCharacterIncrement);
boolean fixedSpaceMode = false;
for (int i = 0; i < l; i++) {
char orgChar = text.charAt(i);
float glyphAdjust = 0;
if (CharUtilities.isFixedWidthSpace(orgChar)) {
flushText(builder, sb, charSet);
builder.setVariableSpaceCharacterIncrement(
fixedSpaceCharacterIncrement);
fixedSpaceMode = true;
sb.append(CharUtilities.SPACE);
int charWidth = font.getCharWidth(orgChar);
glyphAdjust += (charWidth - spaceWidth);
} else {
if (fixedSpaceMode) {
flushText(builder, sb, charSet);
builder.setVariableSpaceCharacterIncrement(
varSpaceCharacterIncrement);
fixedSpaceMode = false;
}
char ch;
if (orgChar == CharUtilities.NBSPACE) {
ch = ' '; //converted to normal space to allow word spacing
} else {
ch = orgChar;
}
sb.append(ch);
}
if (i < dxl - 1) {
glyphAdjust += dx[i + 1];
}
if (glyphAdjust != 0) {
flushText(builder, sb, charSet);
int increment = Math.round(unitConv.mpt2units(glyphAdjust));
builder.relativeMoveInline(increment);
}
}
} else {
for (int i = 0; i < l; i++) {
char orgChar = text.charAt(i);
float glyphAdjust = 0;
if (CharUtilities.isFixedWidthSpace(orgChar)) {
sb.append(CharUtilities.SPACE);
int spaceWidth = font.getCharWidth(CharUtilities.SPACE);
int charWidth = font.getCharWidth(orgChar);
glyphAdjust += (charWidth - spaceWidth);
} else {
sb.append(orgChar);
}
if ((wordSpacing != 0) && CharUtilities.isAdjustableSpace(orgChar)) {
glyphAdjust += wordSpacing;
}
glyphAdjust += letterSpacing;
if (i < dxl - 1) {
glyphAdjust += dx[i + 1];
}
if (glyphAdjust != 0) {
flushText(builder, sb, charSet);
int increment = Math.round(unitConv.mpt2units(glyphAdjust));
builder.relativeMoveInline(increment);
}
}
}
flushText(builder, sb, charSet);
}
private void flushText(PtocaBuilder builder, StringBuffer sb,
final CharacterSet charSet) throws IOException {
if (sb.length() > 0) {
builder.addTransparentData(charSet.encodeChars(sb));
sb.setLength(0);
}
}
});
} catch (IOException ioe) {
throw new IFException("I/O error in drawText()", ioe);
}
}