You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by ti...@apache.org on 2018/07/05 17:15:51 UTC
svn commit: r1835157 -
/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/annotation/handlers/PDFreeTextAppearanceHandler.java
Author: tilman
Date: Thu Jul 5 17:15:51 2018
New Revision: 1835157
URL: http://svn.apache.org/viewvc?rev=1835157&view=rev
Log:
PDFBOX-3353: Add clipping rect; remove "factor" which was just a guess; draw text in cloudy annotation as if the rectangle hadn't changed for the clouds; fix bug with /RD and non cloudy
Modified:
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/annotation/handlers/PDFreeTextAppearanceHandler.java
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/annotation/handlers/PDFreeTextAppearanceHandler.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/annotation/handlers/PDFreeTextAppearanceHandler.java?rev=1835157&r1=1835156&r2=1835157&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/annotation/handlers/PDFreeTextAppearanceHandler.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/annotation/handlers/PDFreeTextAppearanceHandler.java Thu Jul 5 17:15:51 2018
@@ -160,6 +160,11 @@ public class PDFreeTextAppearanceHandler
PDBorderEffectDictionary borderEffect = annotation.getBorderEffect();
if (borderEffect != null && borderEffect.getStyle().equals(PDBorderEffectDictionary.STYLE_CLOUDY))
{
+ // Adobe draws the text with the original rectangle in mind.
+ // but if there is an /RD, then writing area get smaller.
+ // do this here because /RD is overwritten in a few lines
+ borderBox = applyRectDifferences(getRectangle(), annotation.getRectDifferences());
+
//TODO this segment was copied from square handler. Refactor?
CloudyBorder cloudyBorder = new CloudyBorder(cs,
borderEffect.getIntensity(), ab.width, getRectangle());
@@ -167,8 +172,7 @@ public class PDFreeTextAppearanceHandler
annotation.setRectangle(cloudyBorder.getRectangle());
annotation.setRectDifference(cloudyBorder.getRectDifference());
PDAppearanceStream appearanceStream = annotation.getNormalAppearanceStream();
- borderBox = cloudyBorder.getBBox();
- appearanceStream.setBBox(borderBox);
+ appearanceStream.setBBox(cloudyBorder.getBBox());
appearanceStream.setMatrix(cloudyBorder.getMatrix());
}
else
@@ -180,62 +184,65 @@ public class PDFreeTextAppearanceHandler
// - if /RD is set the border box is the /Rect entry inset by the respective
// border difference.
// - if /RD is not set then we don't touch /RD etc because Adobe doesn't either.
- float[] rectDifferences = annotation.getRectDifferences();
- if (rectDifferences.length == 0)
- {
- borderBox = getRectangle();
- }
- else
- {
- borderBox = applyRectDifferences(getRectangle(), rectDifferences);
- annotation.getNormalAppearanceStream().setBBox(borderBox);
- }
- borderBox = getPaddedRectangle(borderBox, ab.width / 2);
- cs.addRect(borderBox.getLowerLeftX(), borderBox.getLowerLeftY(),
- borderBox.getWidth(), borderBox.getHeight());
+ borderBox = applyRectDifferences(getRectangle(), annotation.getRectDifferences());
+ annotation.getNormalAppearanceStream().setBBox(borderBox);
+
+ // note that borderBox is not modified
+ PDRectangle paddedRectangle = getPaddedRectangle(borderBox, ab.width / 2);
+ cs.addRect(paddedRectangle.getLowerLeftX(), paddedRectangle.getLowerLeftY(),
+ paddedRectangle.getWidth(), paddedRectangle.getHeight());
}
cs.drawShape(ab.width, hasStroke, hasBackground);
// rotation is an undocumented feature, but Adobe uses it. Examples can be found
- // in pdf_commenting_new.pdf file.
+ // in pdf_commenting_new.pdf file, page 3.
int rotation = annotation.getCOSObject().getInt(COSName.ROTATE, 0);
cs.transform(Matrix.getRotateInstance(Math.toRadians(rotation), 0, 0));
float xOffset;
float yOffset;
- float width = rotation == 90 || rotation == 270 ? borderBox.getHeight(): borderBox.getWidth();
- // somewhat inspired by AppearanceGeneratorHelper.insertGeneratedAppearance()
- cs.beginText();
+ float width = rotation == 90 || rotation == 270 ? borderBox.getHeight() : borderBox.getWidth();
+ // strategy to write formatted text is somewhat inspired by
+ // AppearanceGeneratorHelper.insertGeneratedAppearance()
PDFont font = PDType1Font.HELVETICA;
- int factor = 1;
- if (borderEffect != null && borderEffect.getStyle().equals(PDBorderEffectDictionary.STYLE_CLOUDY))
- {
- //TODO cloudy needs to be reviewed too.
- factor = 2;
- }
+ float clipY;
+ float clipWidth = width - ab.width * 4;
+ float clipHeight = rotation == 90 || rotation == 270 ?
+ borderBox.getWidth() - ab.width * 4 : borderBox.getHeight() - ab.width * 4;
float fontSize = extractFontSize(annotation);
- // used by Adobe, no idea where it comes from, actual font bbox max y is 0.931
+
+ // value used by Adobe, no idea where it comes from, actual font bbox max y is 0.931
// gathered by creating an annotation with width 0.
float yDelta = 0.7896f;
switch (rotation)
{
case 180:
- xOffset = - borderBox.getUpperRightX() + ab.width * 2 * factor;
- yOffset = - borderBox.getLowerLeftY() - ab.width * 2 * factor - yDelta * fontSize * factor;
+ xOffset = - borderBox.getUpperRightX() + ab.width * 2;
+ yOffset = - borderBox.getLowerLeftY() - ab.width * 2 - yDelta * fontSize;
+ clipY = - borderBox.getUpperRightY() + ab.width * 2;
break;
case 90:
- xOffset = borderBox.getLowerLeftY() + ab.width * 2 * factor;
- yOffset = - borderBox.getLowerLeftX() - ab.width * 2 * factor - yDelta * fontSize * factor;
+ xOffset = borderBox.getLowerLeftY() + ab.width * 2;
+ yOffset = - borderBox.getLowerLeftX() - ab.width * 2 - yDelta * fontSize;
+ clipY = - borderBox.getUpperRightX() + ab.width * 2;
break;
case 270:
- xOffset = - borderBox.getUpperRightY() + ab.width * 2 * factor;
- yOffset = borderBox.getUpperRightX() - ab.width * 2 * factor - yDelta * fontSize * factor;
+ xOffset = - borderBox.getUpperRightY() + ab.width * 2;
+ yOffset = borderBox.getUpperRightX() - ab.width * 2 - yDelta * fontSize;
+ clipY = borderBox.getLowerLeftX() + ab.width * 2;
break;
case 0:
default:
- xOffset = borderBox.getLowerLeftX() + ab.width * 2 * factor;
- yOffset = borderBox.getUpperRightY() - ab.width * 2 * factor - yDelta * fontSize * factor;
+ xOffset = borderBox.getLowerLeftX() + ab.width * 2;
+ yOffset = borderBox.getUpperRightY() - ab.width * 2 - yDelta * fontSize;
+ clipY = borderBox.getLowerLeftY() + ab.width * 2;
break;
}
+
+ // clip writing area
+ cs.addRect(xOffset, clipY, clipWidth, clipHeight);
+ cs.clip();
+
+ cs.beginText();
cs.setFont(font, fontSize);
cs.setNonStrokingColor(strokingColor.getComponents());
AppearanceStyle appearanceStyle = new AppearanceStyle();
@@ -244,9 +251,8 @@ public class PDFreeTextAppearanceHandler
PlainTextFormatter formatter = new PlainTextFormatter.Builder(cs)
.style(appearanceStyle)
.text(new PlainText(annotation.getContents()))
- .width(width - ab.width * factor * 4)
+ .width(width - ab.width * 4)
.wrapLines(true)
- //TODO some reverse engineering needed to find out padding
.initialOffset(xOffset, yOffset)
// Adobe ignores the /Q
//.textAlign(annotation.getQ())