Page 1 of 1

Watermark (w:pict/v:shape/v:imagedata)

PostPosted: Tue Apr 28, 2015 12:22 am
by Tantalus
Hello,

I'd like to add a watermark image to my docx and PDF files. I've added a paragraph (w:p/w:r/w:pict/v:shape/v:imagedata) to my w:hdr:

Code: Select all
   <w:p>
      <w:r>
         <w:pict>
            <v:shape type="#_x0000_t75" style="position:absolute;margin-left:0;margin-top:0;width:113.35pt;height:67.61475716064757pt;z-index:-251657216;mso-position-horizontal:center;mso-position-horizontal-relative:margin;mso-position-vertical:center;mso-position-vertical-relative:margin" o:hralign="left" o:allowincell="f" o:insetmode="custom" o:connectortype="straight">
               <v:imagedata o:title="watermark" r:id="rId3" gain="19661f" blacklevel="22938f"/>
            </v:shape>
         </w:pict>
      </w:r>
   </w:p>


Code: Select all
   @SuppressWarnings("deprecation")
   private P createWatermarkP(Watermark watermark, byte[] bytes, Part part) {
      try {
         BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(docPackage, part, bytes);
         
         // Width and height in pt
         ImageInfo imageInfo = imagePart.getImageInfo();
         if (imageInfo == null)
            return null;
         
         Dimension2D dimensionPt = imageInfo.getSize().getDimensionPt();
         double width = dimensionPt.getWidth();
         double height = dimensionPt.getHeight();
         
         if (watermark.getWidth() > 0) {
            height = twipsToPt(cmToTwips(watermark.getWidth())) * height / width;
            width = twipsToPt(cmToTwips(watermark.getWidth()));
         }
         
         // create XML structure
         // w:p/w:r/w:pict/v:shape/v:imagedata
         P p = objectFactory.createP();
         R r = objectFactory.createR();
         p.getContent().add(r);
         Pict pict = objectFactory.createPict();
         JAXBElement<Pict> pictWrapped = objectFactory
               .createRPict(pict);
         r.getContent().add(pictWrapped);

         org.docx4j.vml.ObjectFactory vmlObjectFactory = new org.docx4j.vml.ObjectFactory();
         CTShape shape = vmlObjectFactory.createCTShape();
         JAXBElement<org.docx4j.vml.CTShape> shapeWrapped = vmlObjectFactory
               .createShape(shape);
         pict.getAnyAndAny().add(shapeWrapped);
         shape.setStyle("position:absolute;margin-left:0;margin-top:0;width:" + width + "pt;height:" + height + "pt;z-index:-251657216;mso-position-horizontal:center;mso-position-horizontal-relative:margin;mso-position-vertical:center;mso-position-vertical-relative:margin");
         shape.setInsetmode(org.docx4j.vml.officedrawing.STInsetMode.CUSTOM);
         shape.setConnectortype(org.docx4j.vml.officedrawing.STConnectorType.STRAIGHT);
         CTImageData imagedata = vmlObjectFactory.createCTImageData();
         JAXBElement<CTImageData> imagedataWrapped = vmlObjectFactory
               .createImagedata(imagedata);
         shape.getEGShapeElements().add(imagedataWrapped);
         imagedata.setTitle("watermark");
         imagedata.setGain("19661f");
         imagedata.setBlacklevel("22938f");
         imagedata.setId(imagePart.getRelLast().getId());
         shape.setHralign(STHrAlign.LEFT);
         shape.setAllowincell(STTrueFalse.F);
         shape.setType("#_x0000_t75");

         return p;
      } catch (Exception e) {
         logger.log(Level.WARNING, "createWatermarkP(...): Failed to create watermark image", e);
         return null;
      }
   }



Which is working fine for .docx output. If I export my document to PDF the image is displayed without additional formatting options in my header (v:shape style attribute, v:imagedata gain/blacklevel). This means the image is missing the absolute positioning (horizontal/vertical center alignment) and transparency/fading effect.

Is there any way to draw an image with absolute positioning and transparency effect in PDF files?

Re: Watermark (w:pict/v:shape/v:imagedata)

PostPosted: Thu Apr 30, 2015 10:02 pm
by jason
All I have to offer you is a bit of a brain dump, for what its worth...

One way to do it in XSL FO: http://www.data2type.de/en/xml-xslt-xsl ... xample-17/

Note distinction between what you are doing, and w:background: http://stackoverflow.com/questions/1898 ... apache-poi

Regarding floats in docx4j, there is some code in org.docx4j.convert.out.fo.FOPictWriterAbstract

Note that despite its name, this currently only handles v:textbox. Images (ie ./v:shape/v:imagedata) are handled differently, by legacy code:

Syntax: [ Download ] [ Hide ]
Using xml Syntax Highlighting
<xsl:template match="w:pict">

        <xsl:choose>
                <xsl:when test="./v:shape/v:imagedata">

                        <xsl:variable name="wpict" select="."/>
                       
                        <xsl:copy-of select="java:org.docx4j.model.images.WordXmlPictureE10.createXslFoImgE10(
                        $conversionContext,
                        $wpict)" />

                </xsl:when>
                <xsl:when test="./v:shape/v:textbox">
                        <!--  from 3.0.1 -->
                        <xsl:variable name="childResults">
                                <xsl:apply-templates  select="./v:shape/v:textbox/w:txbxContent/*" />
                        </xsl:variable>
       
                        <xsl:variable name="currentNode" select="." />                         
       
                        <!--  Create the XSL FO table in Java -->
                        <xsl:copy-of select="java:org.docx4j.convert.out.common.XsltCommonFunctions.toNode(
                                $conversionContext,$currentNode, $childResults)"/>
                     
                       
                </xsl:when>
                <xsl:when test="./v:rect/v:textbox">
                        <!--  from 3.0.1 -->
                        <xsl:variable name="childResults">
                                <xsl:apply-templates  select="./v:rect/v:textbox/w:txbxContent/*" />
                        </xsl:variable>
       
                        <xsl:variable name="currentNode" select="." />                         
       
                        <!--  Create the XSL FO table in Java -->
                        <xsl:copy-of select="java:org.docx4j.convert.out.common.XsltCommonFunctions.toNode(
                                $conversionContext,$currentNode, $childResults)"/>
                     
                       
                </xsl:when>
                <xsl:otherwise>
                        <xsl:comment>TODO: handle w:pict containing other than ./v:shape/v:imagedata</xsl:comment>
                        <xsl:copy-of
                                select="java:org.docx4j.convert.out.common.XsltCommonFunctions.notImplemented($conversionContext,., ' without v:imagedata ' )" />                      
                </xsl:otherwise>
        </xsl:choose>                  

</xsl:template>
 
Parsed in 0.003 seconds, using GeSHi 1.0.8.4


Within the last 6 months or so, the FOP devs have been discussing / working on improved float support, for example:

thread "Funding for Float support in FOP?"

thread "[VOTE] merge branches/Temp_BasicSideFloats to trunk"

so there would probably be scope to take advantage of that in docx4j. Although my personal focus is now on Plutext's commercial PDF converter (which doesn't use this FO stuff at all), I'd still of course be happy to accept contributions which improve docx4j's FO output.

You'd have to check whether something floated that way could be behind your text...