Letter-spacing / kerning between words in PDFRenderer

2003-03-12 Thread Joop Vriend
Hi,
To begin with: we use FOP 0.20.4, and this mail is about a partly fix 
for missing letter-spacing/kerning between words in PDF's.

In PDF's produced with FOP compared to PDF's from other an other source, 
we noticed that FOP doesn't apply kerning (letter-spacing) to spaces 
between words, most obviously at the end of sentences. I.e., no kerning 
is applied to the character pairs

word-characterspace  (for example, . ) and
spaceword-character  (for example,  V).
The cause, or in any case, the place where it can (partly?) be fixed, 
can be found in the method renderWordArea(WordArea area) in 
PDFRenderer.java.

The latter case (spaceword-character) I could easily fix. All I 
had to do was move the lines

String s;
if (area.getPageNumberID()
!= null) {// this text is a page number, so resolve it
s = idReferences.getPageNumber(area.getPageNumberID());
if (s == null) {
s = ;
}
} else {
s = area.getText();
}
int l = s.length();
up a few lines so they precede 'if (!textOpen || bl != prevWordY)',
and add the following lines in the else-part of
'if (!textOpen || bl != prevWordY)':
if (kerningAvailable  l  0) {
addKerning(pdf, (new Integer((int) ' ')),
 (new Integer((int) area.getFontState().mapChar(s.charAt(0,
   kerning, startText, endText);
}
I've attached the complete code of the method renderWordArea separately.
But..., that's only half of the solution! The first case 
(word-characterspace) is more difficult. I think that in 
renderWordArea we can not be sure that a space is following the word we 
just rendered - or can we? And we don't have the last character of the 
previous word available. Anyone has any ideas?

Regards, Joop Vriend.
/**
 * render inline area to PDF
 *
 * @param area  inline area to render
 */
public void renderWordArea(WordArea area) {
synchronized (_wordAreaPDF) {
StringBuffer pdf = _wordAreaPDF;
pdf.setLength(0);

Hashtable kerning = null;
boolean kerningAvailable = false;

kerning = area.getFontState().getKerning();
if (kerning != null  !kerning.isEmpty()) {
kerningAvailable = true;
}

String name = area.getFontState().getFontName();
int size = area.getFontState().getFontSize();

// This assumes that *all* CIDFonts use a /ToUnicode mapping
boolean useMultiByte = false;
Font f = (Font) area.getFontState().
getFontInfo().getFonts().get(name);
if (f instanceof LazyFont) {
if (((LazyFont) f).getRealFont() instanceof CIDFont) {
useMultiByte = true;
}
} else if (f instanceof CIDFont) {
useMultiByte = true;
}
// String startText = useMultiByte ? FEFF : (;
String startText = useMultiByte ?  : (;
String endText = useMultiByte ?   : ) ;

if ((!name.equals(this.currentFontName))
|| (size != this.currentFontSize)) {
closeText();

this.currentFontName = name;
this.currentFontSize = size;
pdf = pdf.append(/ + name +   + ((float)size / 1000) +  Tf\n);
}

//Do letter spacing (must be outside of [..] TJ)
float letterspacing =
((float) area.getFontState().getLetterSpacing()) / 1000;
if (letterspacing != this.currentLetterSpacing) {
this.currentLetterSpacing = letterspacing;
closeText();
pdf.append(letterspacing).append( Tc\n);
}

PDFColor areaColor = null;
if (this.currentFill instanceof PDFColor) {
areaColor = (PDFColor) this.currentFill;
}

if (areaColor == null || areaColor.red() != (double) area.getRed()
|| areaColor.green() != (double) area.getGreen()
|| areaColor.blue() != (double) area.getBlue()) {

areaColor = new PDFColor((double) area.getRed(),
(double) area.getGreen(),
(double) area.getBlue());

closeText();
this.currentFill = areaColor;
pdf.append(this.currentFill.getColorSpaceOut(true));
}

int rx = this.currentXPosition;
int bl = this.currentYPosition;

addWordLines(area, rx, bl, size, areaColor);

String s;
if (area.getPageNumberID() != null) {// this text is a page number, so 
resolve it
s = idReferences.getPageNumber(area.getPageNumberID());
if (s == null) {
s = ;
}
} else {
s = area.getText();
}

int l = s.length();

if (!textOpen || bl != prevWordY) {
closeText();

pdf.append(1 0 0 1  + (rx / 1000f) +   + (bl / 1000f)
+  Tm [ + startText);
prevWordY = bl;
textOpen = true;
} else {
// express the space between words in thousandths of an em

Re: Letter-spacing / kerning between words in PDFRenderer

2003-03-12 Thread J.Pietschmann
Joop Vriend wrote:
To begin with: we use FOP 0.20.4, and this mail is about a partly fix 
for missing letter-spacing/kerning between words in PDF's.
Well, thanks for the effort but this patch wont make it into FOP
soon, mainly because the layout core doesn't take kerning into
account at all, which needs to be fixed first.
Also, if I understand you correctly, kerning should also be applied
for the case (emDiff  -33000), and text decoration position as well
as the rx and word width should be compensated for the kerning.
But..., that's only half of the solution! The first case 
(word-characterspace) is more difficult.
Not really: keep the text of the last rendered word in lastWord
or something and add the kerning correction to the current rx
respective the space. The lastWord must be cleared if something
special like an image is rendered in between.
J.Pietschmann
-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]