Extending Flex Components for PDF Generation in XDP Format

In this section, you’ll learn how to enhance standard Flex UI components so that they can properly present themselves for rendering as PDF-friendly objects in the XML-based XDP format.

The ActionScript code snippet in Example 11-13 shows how you can present a checkbox as an element of the PDF form in XDP format (in XDP, a checkbox is called checkButton).

We’ll introduce a new interface, IXdpObject, and each of our enhanced UI components will implement it to return properly prepared XML to represent itself. This will allow you to turn the entire Flex view into a searchable PDF.

Example 11-13 is an example of implementing the getter xdpContent() defined in the IXdpObject interface to produce a CheckBox in the XDP format.

Example 11-13. Representing a CheckBox as an XDP checkButton

// IXdpObject interface implementation
public  function get xdpContent():Object {
 var o:XML =
      <field  x={convert(x)} w={convert(width)} h={convert(height)}>
   <ui>
     <checkButton  allowNeutral="1">
       <border>
         <edge stroke="lowered"/>
         <fill/>
       </border>
      </checkButton>
   </ui>
   <value>
     <text>{value}</text>
   </value>
   <para vAlign="middle" hAlign="center"/>

   <items>
     <text>{onValue}</text>
     <text>{offValue}</text>
     <text></text>
   </items>
   <caption placement="bottom"/>
   </field>;

 return o;
}

private function convert(value:Number) : String {
   return  XdpUtil.px2pt(value) + "pt";
}

This code snippet includes a getter, xdpContent, that returns the representation of our CheckBox in XDP format. It uses a helper function, convert(), to convert the value from pixels to points.

Note

Note that this code uses binding to insert the onValue and offValue variables that were introduced in Chapter  in Example 55.

To generate a PDF for a particular Flex view, you need to loop through its children (every UI control of each container) and get each one’s xdpContent. If it’s not null, add its value (XDP) to the output file. If it does not have xdpConent, just get an image snapshot of this child and add it to the output file.

At the end of this process, you’ll get a mix of images and XDP content. If this is a Flex application, send this content to the server-side Java Servlet, which will sandwich it between the PDF header and footer. Voilà! Your PDF file is ready.

Obsessed with the mantra “Developers must write less code,” we at Farata have already created a number of classes in the package com.farata.printing that allows Flex components to expose themselves in a form of XDP.

The sample application shown in Example 11-14 is a rewrite of Example 11-5. It’ll produce the same output as in Figure 11-2, but this time the document will be encoded in the XDP format.

Example 11-14. Saving data in XDP format: test_xdp2.mxml

<?xml version="1.0" encoding="utf-8"?>

<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
 xmlns:local="*"
 xmlns:printer="com.farata.printing.pdf.client.*" layout="vertical">

   <mx:Style source="main.css"/>
   <mx:Canvas id="canvas" width="100%" height="100%"
      backgroundColor="white">
      <mx:Label id="lbl1" text="Hello" x="10" y="10"/>
      <mx:Label id="lbl2" text="World" x="50" y="30"
         fontWeight="bold"/>
           <mx:Label id="lbl3" text="And" x="150" y="60"
          fontStyle="italic" enabled="false"/>

      <mx:Label id="lbl4" text="Happy" x="70" y="90" fontSize="16"
              textDecoration="underline"/>
      <mx:Label id="lbl5" text="New Year" x="50" y="140" fontSize="24"
              fontWeight="bold" color="green"/>
      <mx:Button id="btn1" label="Button1" x="70" y="240"/>
   </mx:Canvas>

    <mx:ApplicationControlBar width="100%">
    <mx:Label text="File name:"/>
     <mx:TextInput id="txtFileName" text="hw2.pdf"/>
    <mx:Button label="Save PDF" click="savePdf()"/>
   </mx:ApplicationControlBar>

   <mx:Script>
      <![CDATA[
      import com.farata.printing.PrintOptions;
        import com.farata.printing.pdf.xdp.XdpDocument;
        import com.farata.printing.pdf.buffered.PDFHelper;

     private function savePdf():void{
      saveToFile(txtFileName.text, createXdpContent());
      }

     private function createXdpContent ():ByteArray{

      var xdpDocument:XdpDocument=new XdpDocument();
      xdpDocument.init(new PrintOptions());
      var pdf:PDFHelper=new PDFHelper(xdpDocument);

      pdf.createPDFPrologue();
      pdf.createPage(canvas, PDFHelper.TYPE_PAGE);
      pdf.createPDFEpilogue();

        return pdf.pdfContent;
   }

   private function saveToFile (file:String, ba:ByteArray):void{

      var fs:FileStream=new FileStream();
      var f:File=File.desktopDirectory.resolvePath(file);
      fs.open(f, FileMode.WRITE);

      try {
        fs.writeBytes(ba);
      } catch(e:*){
             // Process I/O errors here
       }
        fs.close();
   }

      ]]>
   </mx:Script>
</mx:WindowedApplication>

When you open the generated file h2.pdf in a text editor, notice that it looks different than the file shown in Example 11-8. The small PDF header and the trailer are there, but the main content of this file is in XDP format, as shown in Example 11-15.

Example 11-15. A fragment of the h2.pdf content in XDP format

 %PDF-1.7
1 0 obj
<</Type /Catalog /StructTreeRoot 9 0 R /MarkInfo <</Marked true>> /Pages 15 0 R
/AcroForm 16 0 R /NeedsRendering true>>
endobj
2 0 obj
<</Type /Page /MediaBox [0 0 612 792] /Resources 5 0 R /Contents 4 0 R
/StructParent 0 /StructParents 0 /Parent 15 0 R>>
endobj
4 0 obj
<</Length 298>>
stream
BT
/Content <</MCID 0>> BDC
0.0 0.0 0.0 rg
/RelativeColorimetric ri
/T1_0 1.0 Tf
10.0 0.0 0.0 10.0 72.0 720.0 Tm
(Warning: This form is not supported at all with the current version of Acrobat or
Adobe Reader.) Tj
0.0 -1.8 Td
(Upgrade to the latest version for full support.) Tj
0.0 -1.8 Td
EMC
ET
endstream
endobj
5 0 obj
<</Font 8 0 R /ProcSet [/PDF /Text]>>
endobj
6 0 obj
<</Type /Encoding /BaseEncoding /WinAnsiEncoding>>
endobj
7 0 obj
<</Type /Font /Subtype /Type1 /BaseFont /Helvetica /Encoding 6 0 R>>
endobj
8 0 obj
<</T1_0 7 0 R>>
endobj
9 0 obj
<</Type /StructTreeRoot /K 10 0 R /ParentTree 13 0 R /ParentTreeNextKey 1 /RoleMap
14 0 R>>
endobj
10 0 obj
<</S /Document /P 9 0 R /K 11 0 R>>
endobj
11 0 obj
<</S /Div /P 10 0 R /K 12 0 R>>
endobj
12 0 obj
<</S /P /P 11 0 R /Pg 2 0 R /K 0>>
endobj
13 0 obj
<</Nums [0 [12 0 R]]>>
endobj
14 0 obj
<</Field /Div /Subform /Sect /Page /Part /Draw /Div>>
endobj
15 0 obj
<</Type /Pages /Kids [2 0 R] /Count 1>>
endobj
16 0 obj
<</Fields [] /XFA 17 0 R>>
endobj
17 0 obj
<< /Length 18 0 R >>
stream
<xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/">
  <template xmlns="http://www.xfa.org/schema/xfa-template/2.5/">
    <subform name="doc1" layout="tb" restoreState="auto" locale="en_US">
      <proto/>
      <desc>
        <text name="version">8.0.1291.1.339988.308172</text>
      </desc>
      <pageSet>
        <pageArea name="Page1" id="Page1">
          <contentArea x="8.47mm" y="8.47mm" w="262.43mm" h="198.94mm"/>
          <medium stock="custom" short="215.87mm" long="279.37mm"
                                              orientation="landscape"/>
        </pageArea>
      </pageSet>
    <subform layout="tb" name="Subform1">
  <subform name="Container1" x="6.35mm" y="6.35mm" w="119.58mm" h="70.9mm">
    <draw x="7.5pt" y="7.5pt" w="22.5pt" h="14.25pt">
      <ui>
        <textEdit hScrollPolicy="off" multiLine="0" vScrollPolicy="off"/>
      </ui>
      <value>
        <text>Hello</text>
      </value>
      <para hAlign="left"/>
      <font typeface="Arial" size="7.5pt" weight="normal" posture="normal"
                   underline="0">
        <fill>
          <color value="11,51,60"/>
        </fill>
      </font>
      <border>
        <edge presence="hidden"/>
        <edge presence="hidden"/>
        <edge presence="hidden"/>
        <edge presence="hidden"/>
      </border>
    </draw>
    <draw x="37.5pt" y="22.5pt" w="24.75pt" h="13.5pt">
      <ui>
        <textEdit hScrollPolicy="off" multiLine="0" vScrollPolicy="off"/>
      </ui>
      <value>
        <text>World</text>
      </value>
      <para hAlign="left"/>
      <font typeface="Arial" size="7.5pt" weight="bold" posture="normal"
                                                          underline="0">
        <fill>
          <color value="11,51,60"/>
        </fill>
      </font>
      <border>
        <edge presence="hidden"/>
        <edge presence="hidden"/>
        <edge presence="hidden"/>
        <edge presence="hidden"/>
      </border>
    </draw>
    <draw x="112.5pt" y="45pt" w="18pt" h="14.25pt">
      <ui>
        <textEdit hScrollPolicy="off" multiLine="0" vScrollPolicy="off"/>
      </ui>
      <value>
        <text>And</text>
      </value>
      <para hAlign="left"/>
      <font typeface="Arial" size="7.5pt" weight="normal" posture="italic"
                                                 underline="0">
        <fill>
          <color value="11,51,60"/>
        </fill>
      </font>
      <border>
        <edge presence="hidden"/>
        <edge presence="hidden"/>
        <edge presence="hidden"/>
        <edge presence="hidden"/>
      </border>
    </draw>
    <draw x="52.5pt" y="67.5pt" w="37.5pt" h="18pt">
      <ui>
        <textEdit hScrollPolicy="off" multiLine="0" vScrollPolicy="off"/>
      </ui>
      <value>
        <text>Happy</text>
      </value>
      <para hAlign="left"/>
      <font typeface="Arial" size="12pt" weight="normal" posture="normal"
                                              underline="1">
        <fill>
          <color value="11,51,60"/>
        </fill>
      </font>
      <border>
        <edge presence="hidden"/>
        <edge presence="hidden"/>
        <edge presence="hidden"/>
        <edge presence="hidden"/>
      </border>
    </draw>
    <draw x="37.5pt" y="105pt" w="83.25pt" h="26.25pt">
      <ui>
        <textEdit hScrollPolicy="off" multiLine="0" vScrollPolicy="off"/>
      </ui>
      <value>
        <text>New Year</text>
      </value>
      <para hAlign="left"/>
      <font typeface="Arial" size="18pt" weight="bold" posture="normal"
underline="0">
        <fill>
          <color value="0,128,0"/>
        </fill>
      </font>
      <border>
        <edge presence="hidden"/>
        <edge presence="hidden"/>
        <edge presence="hidden"/>
        <edge presence="hidden"/>
      </border>
    </draw>
    <draw x="18.52mm" y="63.49mm" w="16.67mm" h="5.82mm">
      <ui>
        <imageEdit/>
      </ui>
      <value>
        <image
contentType="image/png">iVBORw0KGgoAAAANSUhEUgAAAD8AAAAWCAYAAAB3/EQhAAABqElE
QVR42uWYTUsCURSGz76f07bfEtS2UkioqAgJKaMPERISQkJCqIggF2VItAsRi/5AhS11/BpH8YuT
rysb7jj35m7uhQfuOXPmnPvALGaGeLgaDZNz+cKIh6esZ4Ff4f1j5ItFvV6Ps88v/Pn1zeWywV5e
8IMnfOFNr7k85wtvPBgMtAG+8Kbr2zvu9/vaAW9KXd2MHgHdgDclL1Pc7Xa1A96UuEhyp9PRDnhT
/DzB7XZbmZnZuT/I1Iv20zBNH3hT7CzOlmUpg8GT4kn1brWy86fpA2+Knsa42Wwqg8GiWJR3QlTj
dJ/MLBXgTceRKJumqYz9cON5e509r1ovip1yssCbwodHw9e9hjIYLIpl8k57mT5uOVngTaH9MNfr
dWUwWBTL5J32Mn3ccrLAm4K7Ia7VasrYH3u3a057e/14zt5TdIb/nB3Am7Z3glytVrUD3rSxucWV
SkU74E2BtXUt5eFN/tUAG4ahHfCmpRXf8CO/rB3wpuOTCN+n01qJwxfeVCz+8LLPz4+ZDJdKJc8D
T/jCm/Bvy2q1eC98wPMLi54HnvDF+gUhlFFaqhacWgAAAABJRU5ErkJggg==</image>
      </value>
    </draw>
  </subform>
</subform></subform>
</template>

...

</xdp:xdp>
endstream
endobj
18 o obj

endobj
xref
0 19
0000000000 65535 f
0000000016 00000 n
0000000151 00000 n
0000000000 65535 f
0000000287 00000 n
0000000635 00000 n
0000000688 00000 n
0000000754 00000 n
0000000838 00000 n
0000000869 00000 n
0000000976 00000 n
0000001028 00000 n
0000001076 00000 n
0000001127 00000 n
0000001166 00000 n
0000001236 00000 n
0000001292 00000 n
0000001335 00000 n
trailer
<</Root 1 0 R  /Size 19>>
startxref
%%EOF

Note

The file templates/generic.xdp in com.farata.printing contains the generic template for XDP generation used for generation of h2.pdf and all other XDP samples from this chapter.

As you can see from Example 11-15, the values of the text fields (Hello, World, etc.) are represented as XML text fields, which makes this PDF searchable. Note that the binary image is also presented in the encoded form as one of the XML elements.

Note

If you are developing not AIR but Flex applications, the client-side code can generate the entire XML portion of the Flex view components and send this XML to the server, where, say, Java Servlet puts it between the required PDF header and trailer and returns the entire document back to the web browser for printing.

The entire process of generation of this PDF in the XDP format is done by the following code from Example 11-14:

var xdpDocument:XdpDocument=new XdpDocument();
xdpDocument.init(new PrintOptions());
var pdf:PDFHelper=new PDFHelper(xdpDocument);

pdf.createPDFPrologue();

pdf.createPage(canvas, PDFHelper.TYPE_PAGE);

pdf.createPDFEpilogue();

This code uses the helper components XdpDocument, PrintOptions, and PDFHelper, which are located in com.farata.printing.swc. The class PrintOptions is just a holder of such page parameters as orientation, margins, page size, and the like.

The MXML component XdpDocument implements a generic getter xdpContent, introduced in the beginning of this section. The source code of XDPDocument.mxml and a fragment of PDFHelper.as are shown in Examples 11-16 and 11-17, respectively. But these constitute just the tip of the iceberg, as they use uses dozens of supporting classes in the process of creation of the XDP content.

The good news is that unless the XDP format changes, you don’t need to learn all the nitty-gritty details, as we already did that tedious work of ensuring that the document is generated as required by the XDP specifications.

Example 11-16. Component XDPDocument.mxml

<?xml version="1.0" encoding="utf-8"?>

<xdp:XdpBaseObject
     xmlns:mx="http://www.adobe.com/2006/mxml"
     xmlns:xdp="com.farata.printing.pdf.xdp.*">

    <mx:XML id="xmlGen" source="/templates/generic.xdp"/>

<mx:Script><![CDATA[

import mx.core.UIComponent;

import com.farata.printing.pdf.buffered.PDFHelper;
    import com.farata.printing.geom.PNumber;
import mx.core.Container;
import com.farata.printing.geom.PSize;
import com.farata.printing.PrintOptions;
import com.farata.printing.geom.PRectangle;
import com.farata.printing.PaperSize;

public static var ns_xdp     : Namespace = new
Namespace("http://ns.adobe.com/xdp/");

public static var ns_xfat25  : Namespace = new Namespace(
                                          "http://www.xfa.org/schema/xfa-template/2.5/");

public static var ns_xci10   : Namespace = new
Namespace("http://www.xfa.org/schema/xci/1.0/");

public static var ns_xfals21 : Namespace = new
Namespace("http://www.xfa.org/schema/xfa-locale-set/2.1/");

public var paperSize   : PaperSize;
    public var margins     : PRectangle;
public var pageSize    : PSize;
public var orientation : String;
public var header:UIComponent;
public var footer:UIComponent;

public function get pages():Array{
   return children;
}

public override function get xdpContent():Object{

   var x:Object = xmlGen.copy();
   var f:Object = x..ns_xfat25::subform.(@name=="doc1")[0];
   var p:XML = <pageSet>
       <pageArea name="Page1" id="Page1">
      </pageArea>
   </pageSet>;

   var contentAreaX:Number = margins.left.px;
   var contentAreaY:Number = margins.top.px;
   var contentAreaH:Number = pageSize.height.px;
   var contentAreaW:Number = pageSize.width.px;

   if (header){
      var xdpHeader:XdpPage = new XdpPage();
      PDFHelper.createXdpPage(xdpHeader, header);

      xdpHeader.x = margins.left;
      xdpHeader.y = margins.top;
      contentAreaY = contentAreaY + header.height;
      contentAreaH = contentAreaH - header.height;

      p.pageArea.appendChild(xdpHeader.xdpContent);
   }



   if (footer){
      var xdpFooter:XdpContainer = new XdpContainer();
      PDFHelper.createXdpPage(xdpFooter, footer);
      xdpFooter.x = margins.left;
      var y:Number = pageSize.height.px + margins.top.px - footer.height;
      xdpFooter.y = new PNumber(y, PNumber.UNIT_PX);
      contentAreaH = contentAreaH - footer.height;

      p.pageArea.appendChild(xdpFooter.xdpContent);
   }

   p.pageArea.contentArea.@x = _pos(new PNumber(contentAreaX, PNumber.UNIT_PX));
   p.pageArea.contentArea.@y = _pos(new PNumber(contentAreaY, PNumber.UNIT_PX));
   p.pageArea.contentArea.@w = _pos(new PNumber(contentAreaW, PNumber.UNIT_PX));
   p.pageArea.contentArea.@h = _pos(new PNumber(contentAreaH, PNumber.UNIT_PX));

   p.pageArea.medium.@stock = "custom";
   p.pageArea.medium.@short = _pos(paperSize.width);
   p.pageArea.medium.@long  = _pos(paperSize.height);

   if( orientation==PrintOptions.ORIENTATION_LANDSCAPE )
      p.pageArea.medium.@orientation = "landscape";

   p.setNamespace(ns_xfat25);
   f.appendChild(p);
   f = applyStdData(f);

   return x;
}

public function addPage(p:XdpPage):void{

   addChild(p);
   p.pageNumber = pages.length;
   p.w = pageSize.width;
   p.h = pageSize.height;
}

public function init(opt:PrintOptions):void{

   paperSize = opt.paperSize.copy();
   margins = opt.margins.copy();

   pageSize = opt.pageSize;
   orientation = opt.orientation;
}
]]></mx:Script>

</xdp:XdpBaseObject>

The ActionScript class PDFHelper has about 300 lines of code; you can see some fragments of it in Example 11-17. We don’t provide code explanations here, as teaching the internals of the XDP protocol is not the goal of this chapter.

Example 11-17. Fragments of PDFHelper.as

package com.farata.printing.pdf.buffered{

   public class PDFHelper{


       private static var prefix : Array =[["\%PDF-1.7"+ "
"," 65535 f"],
         ["1 0 obj"+"
"+
         "<</Type /Catalog /StructTreeRoot 9 0 R /MarkInfo <</Marked true>> /Pages
15 0 R /AcroForm 16 0 R /NeedsRendering true>>"+"
"+
         "endobj"+"
", " 00000 n"],
         ["2 0 obj"+"
"+
         "<</Type /Page /MediaBox [0 0 612 792] /Resources 5 0 R /Contents 4 0 R
/StructParent 0 /StructParents 0 /Parent 15 0 R>>"+"
"+
         "endobj"+"
", " 00000 n"],
         [""," 65535 f"],
         ["4 0 obj"+"
"+
         "<</Length 298>>"+"
"+
         "stream"+"
"+
         "BT"+"
"+
         "/Content <</MCID 0>> BDC"+"
"+
         "0.0 0.0 0.0 rg"+"
"+
         "/RelativeColorimetric ri"+"
"+
         "/T1_0 1.0 Tf"+"
"+
         "10.0 0.0 0.0 10.0 72.0 720.0 Tm"+"
"+
         "(Warning: This form is not supported at all with the current version of
Acrobat or Adobe Reader.) Tj"+"
"+
         "0.0 -1.8 Td"+"
"+
         "(Upgrade to the latest version for full support.) Tj"+"
"+
         "0.0 -1.8 Td"+"
"+
         "EMC"+"
"+
         "ET"+"
"+
         "endstream"+"
"+
         "endobj"+"
", " 00000 n"],
         ["5 0 obj"+"
"+
         "<</Font 8 0 R /ProcSet [/PDF /Text]>>"+"
"+
         "endobj"+"
", " 00000 n"],
         ["6 0 obj"+"
"+
         "<</Type /Encoding /BaseEncoding /WinAnsiEncoding>>"+"
"+
         "endobj"+"
"," 00000 n"],
         ["7 0 obj"+"
"+
         "<</Type /Font /Subtype /Type1 /BaseFont /Helvetica /Encoding 6 0
R>>"+"
"+
         "endobj"+"
"," 00000 n"],
...

      private var ba:ByteArray = new ByteArray();
      public var xdpDocument:XdpDocument;

      public function PDFHelper(xdpDocument:XdpDocument) {
         this.xdpDocument = xdpDocument;
      }

      public function get pdfContent():ByteArray{
          return ba;
       }

      public function createPDFPrologue():void{
         //write pdf document prefix
         var xref:String ="";

         for (var i:int = 0; i < prefix.length; i++) {
            ba.writeMultiByte( prefix[i][0], "iso-8859-1");
            var str:String = padZeroes(ba.length, 10);
            xref = xref.concat(str + prefix[i][1] + " 
");
         }

         var s:String = xdpDocument.xdpContent.toString();
         s = s.substr(0, s.lastIndexOf("</subform>"));
         ba.writeMultiByte( s, "iso-8859-1");
       }
      public function createPage(obj:Object, type:int):void{
         var page:XdpPage = new XdpPage();
         createXdpPage(page, obj, type);
         ba.writeMultiByte(String(page.xdpContent), "iso-8859-1");
      }

     public function createPDFEpilogue():void{
         var xx:XML = xdpDocument.xdpContent as XML;
         ba.writeMultiByte( "</subform>"+"
"+"</template>"+"
", "iso-8859-1");
         ba.writeMultiByte( xx..ns_xci10::config[0].toString().replace("
xmlns:xdp="http://ns.adobe.com/xdp/"", "")+"
", "iso-8859-1");
         ba.writeMultiByte( xx..ns_xfals21::localeSet[0].toString().replace("
xmlns:xdp="http://ns.adobe.com/xdp/"", "")+"
", "iso-8859-1");
         ba.writeMultiByte( "</xdp:xdp>"+"
", "iso-8859-1");
         ba.writeMultiByte( "endstream"+"
", "iso-8859-1");
         ba.writeMultiByte( "endobj"+"
", "iso-8859-1");
         ba.writeMultiByte("18 o obj " +"
" + /*streamLength + */"
" +
"endobj"+"
",  "iso-8859-1");

         //the footer for the pdf document
          var end:String = "xref"+"
"+ "0 " + 19 +"
";
         var closing:String = end +
               "0000000000 65535 f"+"
"+
               "0000000016 00000 n"+"
"+
...
              "trailer"+"
"+
               "<</Root 1 0 R  /Size " + 19 +">>"+"
"+
               "startxref"+"
"+
               "%%EOF"+"
";
         ba.writeMultiByte(closing , "iso-8859-1");
       }

      public static function createXdpPage(root:XdpPage, obj:Object,
                type:int = 1):void{

         obj = resolveXdp(obj);
         if (obj is Container){

            var c:Container=obj as Container;
            var count:int=c.numChildren;
            if (type == TYPE_LIST) {
               var page:XdpPage = new XdpPage();
            } else {
               page = new XdpContainer();
            }

            page.x = new PNumber(c.x, PNumber.UNIT_PX);
            page.y = new PNumber(c.y, PNumber.UNIT_PX);
            page.h = new PNumber(c.height, PNumber.UNIT_PX);
            page.w = new PNumber(c.width, PNumber.UNIT_PX);

            root.addChild(page);

            if (obj is FormItem){
               var formItemLabel:Label = (obj as FormItem).itemLabel;
               createXdpPage(page, formItemLabel);
            }

            for(var i:int=0; i < count; i++){

               createXdpPage(page, c.getChildAt(i));
            }
         } else if (obj is IXdpObject){

            root.addChild(obj as IXdpObject);
         } else if (obj is UIComponent){

            var uiComp:UIComponent = obj as UIComponent;
            var xdp:XdpBaseObject = XdpImage.grab(uiComp);
            xdp.x = new PNumber(uiComp.x, PNumber.UNIT_PX);
            xdp.y = new PNumber(uiComp.y, PNumber.UNIT_PX);

            // set the width and hight of UIComponent (i.e. image)
            // for proper image scaling and conversion of pixels
            xdp.w = new PNumber(uiComp.width, PNumber.UNIT_PX);
            xdp.h = new PNumber(uiComp.height, PNumber.UNIT_PX);
            root.addChild(xdp);
         }
      }

}

Note

The code in Examples 11-16 and 11-17 is for illustration purposes only, because detailed coverage of the XDP generation is out of the scope of this book. Complete source code of com.farata.printing.swc, however, is available in the CVS repository of the Clear Toolkit project at SourceForge.

Example 11-18 shows the source code of test4_xdp.mxml, the modified version of text4.mxml, but this code generates a PDF in XDP format. The Flex window and PDF look the same as in Figure 11-3.

Example 11-18. AIR application test4_xdp.mxml

<?xml version="1.0" encoding="utf-8"?>

<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical"
creationComplete="onCreationComplete(event)">

   <mx:Style source="main.css"/>

   <mx:DataGrid id="dg" x="0" y="0" width="100%" height="100%">
       <mx:columns>
      <mx:DataGridColumn dataField="name" headerText="Name"/>
      <mx:DataGridColumn dataField="phone" headerText="Phone"/>
      <mx:DataGridColumn dataField="email" headerText="E-mail"/>
      </mx:columns>

        </mx:DataGrid>
   <mx:ApplicationControlBar width="100%">
     <mx:Label text="File name:"/>
     <mx:TextInput id="txtFileName" text="hw4.pdf"/>
     <mx:Button label="Save PDF" click="savePdf()"/>
   </mx:ApplicationControlBar>

   <mx:Script>
      <![CDATA[
      import com.farata.printing.PrintOptions;
      import com.farata.printing.pdf.xdp.XdpDocument;
      import com.farata.printing.pdf.buffered.PDFHelper;

      private function doSavePdf():void{
         saveToFile(txtFileName.text , createXdpContent());
      }
      private function createXdpContent():ByteArray {

         var xdpDocument:XdpDocument=new XdpDocument();
         xdpDocument.init(new PrintOptions());
         var pdf:PDFHelper=new PDFHelper(xdpDocument);

         pdf.createPDFPrologue();
         pdf.createPage(canvas, PDFHelper.TYPE_LIST);
         pdf.createPDFEpilogue();

         return  pdf.pdfContent;
      }

      private function saveToFile(file:String, ba:ByteArray):void{

         var fs:FileStream=new FileStream();
         var f:File=File.desktopDirectory.resolvePath(file);

         fs.open(f, FileMode.WRITE);
         try{
            fs.writeBytes(ba);
         }catch(e:*){
                     // Error processing goes here
         }

         fs.close();
      }

      private function onCreationComplete(evt:*):void{

      var array:Array=[];
      for(var i:int=1; i <= 300; i++){

         var obj:Object=new Object();
         obj.name="User " + i;
         obj.phone="555-219-227" + i;
           obj.email="user" + i + "@hello.world";
           obj.active=(i % 2) == 1;

         array.push(obj);
           }

      dg.dataProvider=arrat;
     }

   ]]>
   </mx:Script>
</mx:WindowedApplication>

Note

We decided to keep the name of the code sample as test4_xdp.mxml, and you can find all other samples (test1 to test5) in the Flash Builder project clientPdfAir.

The previous example illustrates the printing of 300 rows of data to demonstrate that the pagination works properly and each page in the PDF file shows the header of the DataGrid (Figure 11-4).

The second page of the generated PDF hw5.pdf

Figure 11-4. The second page of the generated PDF hw5.pdf

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.142.119.114