Here's some code to create an appearance stream for a highlight
annotation. Note that
- code is is Apache licensed
- works with 2.0.*
- will probably no longer needed in 2.1
- has only been tested with your file and another, i.e. it may not
handle all highlighting cases
- be careful when removing parts that seem to be "not needed", e.g. the
usage of java.util.Locale.US
- "curvy" highlight doesn't work on your file, because the curvy part is
outside of the rectangle
If you need help with different files, you'd need to upload the file so
that I can find the problem.
Good luck
Tilman
if (annotation.getAppearance() == null)
{
if (annotation instanceof PDAnnotationTextMarkup &&
PDAnnotationTextMarkup.SUB_TYPE_HIGHLIGHT.equals(annotation.getSubtype()))
{
PDAnnotationTextMarkup markupAnnotation =
(PDAnnotationTextMarkup) annotation;
PDAppearanceDictionary appearanceDictionary = new
PDAppearanceDictionary();
PDAppearanceStream appearanceStream = new
PDAppearanceStream(renderer.document);
PDPageContentStream cs = new
PDPageContentStream(renderer.document, appearanceStream);
PDRectangle bbox = new
PDRectangle(annotation.getRectangle().getWidth(),
annotation.getRectangle().getHeight());
appearanceStream.setBBox(bbox);
PDExtendedGraphicsState r0 = new PDExtendedGraphicsState();
PDExtendedGraphicsState r1 = new PDExtendedGraphicsState();
r0.setAlphaSourceFlag(false);
r0.setStrokingAlphaConstant(markupAnnotation.getConstantOpacity());
r0.setNonStrokingAlphaConstant(markupAnnotation.getConstantOpacity());
r1.setAlphaSourceFlag(false);
r1.getCOSObject().setItem(COSName.BM,
COSName.MULTIPLY); //TODO PDExtendedGraphicsState.setBlendMode() is missing
if (cs.getResources() == null)
{
if (appearanceStream.getResources() == null)
{
appearanceStream.setResources(new PDResources());
}
cs.setResources(appearanceStream.getResources()); // why not done by
default?
}
cs.setGraphicsStateParameters(r0);
cs.setGraphicsStateParameters(r1);
COSStream mwfoformStrm = new COSStream();
OutputStream os = mwfoformStrm.createOutputStream();
os.write("/Form Do".getBytes(Charsets.ISO_8859_1));
os.close();
PDFormXObject mwfofrm = new PDFormXObject(mwfoformStrm);
cs.drawForm(mwfofrm);
cs.close();
COSStream frmStrm2 = new COSStream();
PDFormXObject frm2 = new PDFormXObject(frmStrm2);
PDResources res = new PDResources();
mwfofrm.setBBox(bbox);
mwfofrm.setResources(res);
COSDictionary groupDict = new COSDictionary();
groupDict.setItem(COSName.S, COSName.TRANSPARENCY);
mwfofrm.getCOSObject().setItem(COSName.GROUP,
groupDict); //TODO PDFormXObject.setGroup() is missing
res.put(COSName.getPDFName("Form"), frm2);
frm2.setBBox(annotation.getRectangle());
frm2.setMatrix(Matrix.getTranslateInstance(-annotation.getRectangle().getLowerLeftX(),
-annotation.getRectangle().getLowerLeftY()).createAffineTransform());
os = frm2.getCOSObject().createOutputStream();
//TODO why can't we get a "classic" content stream?
PDColor color = annotation.getColor();
switch (color.getComponents().length)
{
case 1:
os.write(String.format(java.util.Locale.US,
"%.6f g\n", color.getComponents()[0]).getBytes(Charsets.ISO_8859_1));
break;
case 3:
os.write(String.format(java.util.Locale.US,
"%.6f %.6f %.6f rg\n", color.getComponents()[0],
color.getComponents()[1],
color.getComponents()[2]).getBytes(Charsets.ISO_8859_1));
break;
case 4:
os.write(String.format(java.util.Locale.US,
"%.6f %.6f %.6f %.6f k\n",
color.getComponents()[0],color.getComponents()[1],color.getComponents()[2],color.getComponents()[3]).getBytes(Charsets.ISO_8859_1));
break;
default:
break;
}
float[] qp = markupAnnotation.getQuadPoints();
int of = 0;
while (of + 7 < qp.length)
{
// quadpoints spec sequence is incorrect, correct
one is (4,5 0,1 2,3 6,7)
// for "curvy" highlighting, Bézier points are used
that seem to have a distance of about 1/4 of the height.
// note that curves may not appear if outside of
the rectangle
float delta = (qp[of+3] - qp[of+5]) / 4;
os.write(String.format(java.util.Locale.US, "%.4f
%.4f m\n", qp[of+4], qp[of+5]).getBytes(Charsets.ISO_8859_1));
os.write(String.format(java.util.Locale.US, "%.4f
%.4f %.4f %.4f %.4f %.4f c\n", qp[of+0] - delta, qp[of+5] + delta,
qp[of+0] - delta, qp[of+1] - delta, qp[of+0],
qp[of+1]).getBytes(Charsets.ISO_8859_1));
os.write(String.format(java.util.Locale.US, "%.4f
%.4f l\n", qp[of+2], qp[of+3]).getBytes(Charsets.ISO_8859_1));
os.write(String.format(java.util.Locale.US, "%.4f
%.4f %.4f %.4f %.4f %.4f c\n", qp[of+6]+delta, qp[of+3]-delta,
qp[of+6]+delta, qp[of+7]+delta, qp[of+6],
qp[of+7]).getBytes(Charsets.ISO_8859_1));
os.write("f\n".getBytes(Charsets.ISO_8859_1));
of += 8;
//TODO Adobe puts a "w" (line width). Why?
//TODO If quadpoints is not present or the
conforming reader does not recognize it, the region specified by the
Rect entry should be used. QuadPoints shall be ignored if any coordinate
in the array lies outside the region specified by Rect
}
os.close();
appearanceDictionary.setNormalAppearance(appearanceStream);
annotation.setAppearance(appearanceDictionary);
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]