Author: tilman Date: Sun Jun 3 18:39:07 2018 New Revision: 1832782 URL: http://svn.apache.org/viewvc?rev=1832782&view=rev Log: PDFBOX-3353: draw text box
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=1832782&r1=1832781&r2=1832782&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 Sun Jun 3 18:39:07 2018 @@ -23,10 +23,13 @@ import org.apache.fontbox.util.Charsets; import org.apache.pdfbox.contentstream.operator.Operator; import org.apache.pdfbox.cos.COSArray; import org.apache.pdfbox.cos.COSBase; +import org.apache.pdfbox.cos.COSNumber; import org.apache.pdfbox.cos.COSObject; import org.apache.pdfbox.pdfparser.PDFStreamParser; import org.apache.pdfbox.pdmodel.PDAppearanceContentStream; import org.apache.pdfbox.pdmodel.common.PDRectangle; +import org.apache.pdfbox.pdmodel.font.PDFont; +import org.apache.pdfbox.pdmodel.font.PDType1Font; import org.apache.pdfbox.pdmodel.graphics.color.PDColor; import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceCMYK; import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceGray; @@ -37,6 +40,9 @@ import static org.apache.pdfbox.pdmodel. import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceStream; import org.apache.pdfbox.pdmodel.interactive.annotation.PDBorderEffectDictionary; import static org.apache.pdfbox.pdmodel.interactive.annotation.handlers.PDAbstractAppearanceHandler.SHORT_STYLES; +import org.apache.pdfbox.pdmodel.interactive.annotation.layout.AppearanceStyle; +import org.apache.pdfbox.pdmodel.interactive.annotation.layout.PlainText; +import org.apache.pdfbox.pdmodel.interactive.annotation.layout.PlainTextFormatter; import org.apache.pdfbox.util.Matrix; public class PDFreeTextAppearanceHandler extends PDAbstractAppearanceHandler @@ -191,6 +197,35 @@ public class PDFreeTextAppearanceHandler cs.drawShape(ab.width, hasStroke, hasBackground); + // somewhat inspired by AppearanceGeneratorHelper.insertGeneratedAppearance() + cs.beginText(); + PDFont font = PDType1Font.HELVETICA; + int factor = 1; + if (borderEffect != null && borderEffect.getStyle().equals(PDBorderEffectDictionary.STYLE_CLOUDY)) + { + factor = 2; + } + float fontSize = extractFontSize(annotation); + cs.setFont(font, fontSize); + cs.setNonStrokingColor(strokingColor); + AppearanceStyle appearanceStyle = new AppearanceStyle(); + appearanceStyle.setFont(font); + appearanceStyle.setFontSize(fontSize); + PlainTextFormatter formatter = new PlainTextFormatter.Builder(cs) + .style(appearanceStyle) + .text(new PlainText(annotation.getContents())) + .width(getRectangle().getWidth()) + .wrapLines(true) + //TODO some reverse engineering needed to find out padding + //TODO fat cloudy rectangle in CTAN file has "the" incomplete + .initialOffset(getRectangle().getLowerLeftX() + fontSize / 2 * factor, + getRectangle().getUpperRightY() - font.getBoundingBox().getHeight() * fontSize / 1000 * factor) + // Adobe ignores the /Q + //.textAlign(annotation.getQ()) + .build(); + formatter.format(); + cs.endText(); + if (pathsArray.length > 0) { @@ -300,6 +335,60 @@ public class PDFreeTextAppearanceHandler return strokingColor; } + //TODO extractNonStrokingColor and extractFontSize + // might somehow be replaced with PDDefaultAppearanceString, + // which is quite similar. + private float extractFontSize(PDAnnotationFreeText annotation) + { + String defaultAppearance = annotation.getDefaultAppearance(); + if (defaultAppearance == null) + { + return 10; + } + + try + { + // not sure if charset is correct, but we only need numbers and simple characters + PDFStreamParser parser = new PDFStreamParser(defaultAppearance.getBytes(Charsets.US_ASCII)); + COSArray arguments = new COSArray(); + COSArray fontArguments = new COSArray(); + for (Object token = parser.parseNextToken(); token != null; token = parser.parseNextToken()) + { + if (token instanceof COSObject) + { + arguments.add(((COSObject) token).getObject()); + } + else if (token instanceof Operator) + { + Operator op = (Operator) token; + String name = op.getName(); + if ("Tf".equals(name)) + { + fontArguments = arguments; + } + arguments = new COSArray(); + } + else + { + arguments.add((COSBase) token); + } + } + if (fontArguments.size() >= 2) + { + COSBase base = fontArguments.get(1); + if (base instanceof COSNumber) + { + return ((COSNumber) base).floatValue(); + } + } + } + catch (IOException ex) + { + LOG.warn("Problem parsing /DA, will use default 10", ex); + } + return 10; + } + @Override public void generateRolloverAppearance() {