Using AlivePDF to print from AIR Javascript via ActionScript3 – part 2

For the background to this post, and how to use the following code, see Part 1

In this section I will describe the “solution” I found to the problem of the lack of adequate printing capability in AIR apps. My solution is to use ActionScript to create a PDF on the fly on the client-side. In this case, I am creating it from Javascript since I develop HTML/Javascript apps (using the EXTJS library). This solution does NOT require EXTJS or any other JS library.

I found two AS libraries that create PDF files client-side – AlivePDF and purePDF. The latter interested me particularly becuase it is a port of iText java library which I was already familiar with. However, as discussed in my forum post here, I was unable to get purePDF to work  so I switched to AlivePDF which was more successful. It is highly likely that my problems with purePDF we of my own making. However I was unable to get any help to work out what, if anything, I was doing wrong.

Now, this is really the start of the solution and very much a work in progress. I would value feedback about the overall approach and architecture I am proposing. Since I really wanted to use purePDF instead of AlivePDF, I elected to make the JS class as a layer so that it would be easier to create a version for purePDF if I ever get it to work!

So, here is the “proof of concept” source code.

First, the ActionScript class that exposes Javascript-friendly methods. Compile this as per Part 1 of this article.

package {

    import flash.display.DisplayObject;
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;

    import org.alivepdf.pdf.PDF;
    import org.alivepdf.saving.Method;
    import org.alivepdf.fonts.* ;
    import org.alivepdf.pages.Page;
    import org.alivepdf.display.Display;
    import org.alivepdf.layout.* ;
    import org.alivepdf.links.* ;

    import mx.utils.UIDUtil;

    import flash.filesystem.FileStream;
    import flash.filesystem.File;
    import flash.filesystem.FileMode;

    import flash.utils.ByteArray;

    public class alivePDFWrapper extends Sprite {
        private
        var pdf: PDF;
        private
        var file: File;

        public function alivePDFWrapper() {}

        // The translate methods convert the integers passed from the javascript to
        // whatever correct data types AlivePDF uses
        private function translateSize(size: int): Size {
            var s: Size = Size.A4;
            switch (size) {
            case 0:
                s = Size.A3;
                break;
            case 1:
                s = Size.A4;
                break;
            case 2:
                s = Size.A5;
                break;
            case 3:
                s = Size.LEGAL;
                break;
            case 4:
                s = Size.LETTER;
                break;
            case 5:
                s = Size.TABLOID;
                break;
            }
            return s;
        }

        private function translateOrientation(orientation: int): String {
            var o: String = Orientation.PORTRAIT;
            switch (orientation) {
            case 0:
                o = Orientation.PORTRAIT;
                break;
            case 1:
                o = Orientation.LANDSCAPE;
                break;
            }
            return o;
        }

        private function translateUnit(unit: int): String {
            var u: String = Unit.MM;
            switch (unit) {
            case 0:
                u = Unit.MM;
                break;
            case 1:
                u = Unit.CM;
                break;
            case 2:
                u = Unit.INCHES;
                break;
            case 3:
                u = Unit.POINT;
                break;
            }
            return u;
        }

        private function translateDisplayZoom(dzoom: int): String {
            var dz: String = Display.FULL_PAGE;
            switch (dzoom) {
            case 0:
                dz = Display.DEFAULT;
                break;
            case 1:
                dz = Display.FULL_PAGE;
                break;
            case 2:
                dz = Display.FULL_WIDTH;
                break;
            case 3:
                dz = Display.REAL;
                break;
            }
            return dz;
        }

        private function translateDisplayLayout(dlayout: int): String {
            var dl: String = Layout.SINGLE_PAGE;
            switch (dlayout) {
            case 0:
                dl = Layout.SINGLE_PAGE;
                break;
            case 1:
                dl = Layout.ONE_COLUMN;
                break;
            case 2:
                dl = Layout.TWO_COLUMN_LEFT;
                break;
            case 3:
                dl = Layout.TWO_COLUMN_RIGHT;
                break;
            }
            return dl;
        }

        public function newPDF(size: int, orientation: int, unit: int): void {
            var s: Size = translateSize(size);
            var o: String = translateOrientation(orientation);
            var u: String = translateUnit(unit);

            pdf = new PDF(o, u, s);

            //var myCoreFont:IFont = new CoreFont ( FontFamily.HELVETICA_BOLD );
            var myCoreFont: IFont = new CoreFont(FontFamily.HELVETICA);
            pdf.setFont(myCoreFont, 12);

        }

        public function setDisplayMode(displayZoom: int, displayLayout: int): void {
            var dz: String = translateDisplayZoom(displayZoom);
            var dl: String = translateDisplayLayout(displayLayout);

            pdf.setDisplayMode(dz, dl);
        }

        public function newPage(size: int, orientation: int,unit: int): void {
            var s: Size = translateSize(size);
            var o: String = translateOrientation(orientation);
            var u: String = translateUnit(unit);
            var newPage: Page = new Page(o, u, s);
            pdf.addPage(newPage);
        }

        public function addPage(): void {
            pdf.addPage();
        }

        public function writeText(lineHeight: Number, text: String, link: ILink = null): void {
            pdf.writeText(lineHeight, text, link);
        }

        public function saveToFileAIR(fname: String): void {
            // Save to file for AIR
            var fs: FileStream = new FileStream();
            file = new File(fname);
            fs.open(file, FileMode.WRITE);
            var bytes: ByteArray = pdf.save(Method.LOCAL);
            fs.writeBytes(bytes);
            fs.close();
        }

    }
}

The Javascript interface (so far). Save this to /js folder in your AIR app.

function jsPDF() {
    // Define constants
    this.size = {
        A3: 0,
        A4: 1,
        A5: 2,
        LEGAL: 3,
        LETTER: 4,
        TABLOID: 5
    }
    this.unit = {
        MM: 0,
        CM: 1,
        INCHES: 2,
        POINT: 3
    }
    this.orientation = {
        PORTRAIT: 0,
        LANDSCAPE: 1
    }
    this.displayZoom = {
        DEFAULT: 0,
        FULL_PAGE: 1,
        FULL_WIDTH: 2,
        REAL: 3
    }
    this.displayLayout = {
        SINGLE_PAGE: 0,
        ONE_COLUMN: 1,
        TWO_COLUMN_LEFT: 2,
        TWO_COLUMN_RIGHT: 3
    }

    // Load the ActionScript Library (ie alivePDF + wrapper class)
    this.ASlib = new window.runtime.alivePDFWrapper();

    // Create a new PDF instance
    this.newPDF = function (size, orientation, unit) {
        this.ASlib.newPDF(size, orientation, unit);
    }
    // Set the display mode for the PDF when displayed in the reader
    this.setDisplayMode = function (displayZoom, displayLayout) {
        this.ASlib.setDisplayMode(displayZoom, displayLayout);
    }
    // Create a new page and add it to the pdf document
    this.newPage = function (size, orientation, unit) {
        this.ASlib.newPage(size, orientation, unit);
    }

    this.addPage = function () {
        this.ASlib.addPage();
    }

    this.writeText = function (lineHeight, text, link) {
        this.ASlib.writeText(lineHeight, text, link);
    }

    this.saveToFileAIR = function (fname) {
        this.ASlib.saveToFileAIR(fname);
    }
}

The AIR app:

<html>
    
    <head>
        <title>
            Test alivePDF
        </title>
        <script type="text/javascript" src="lib/air/AIRAliases.js"></script>
        <script src="lib/alivePDFWrapper.swf" type="application/x-shockwave-flash"></script>
        <script src="js/jspdf.js"></script>

        <script>

            var mypdf = new jsPDF();

            mypdf.newPDF(mypdf.size.A4, mypdf.orientation.PORTRAIT, mypdf.unit.MM);

            //mypdf.setDisplayMode(mypdf.displayZoom.FULL_PAGE,mypdf.displayLayout.SINGLE_PAGE);
            mypdf.setDisplayMode(mypdf.displayZoom.FULL_PAGE, mypdf.displayLayout.TWO_COLUMN_LEFT);

            mypdf.newPage(mypdf.size.A4, mypdf.orientation.LANDSCAPE, mypdf.unit.MM);

            mypdf.writeText(10, "Just one line on the first page!");

            mypdf.newPage(mypdf.size.A5, mypdf.orientation.PORTRAIT, mypdf.unit.MM);

            mypdf.writeText(10, "Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n\nPraesent vel lectus lorem. Phasellus convallis, tortor a venenatis mattis, erat mi euismod tellus, in fermentum sapien nibh sit amet urna. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Praesent tellus libero, lacinia ac egestas eget, interdum quis purus. Donec ut nisl metus, sit amet viverra turpis. Mauris ultrices dapibus lacus non ultrices. Cras elementum luctus mauris, vitae eleifend diam accumsan ut. Aliquam erat volutpat. Suspendisse placerat nibh in libero tincidunt a elementum mi vehicula. Donec lobortis magna vel nibh mollis tempor. Maecenas et elit nunc. Nam non auctor orci. Aliquam vel velit vel mi adipiscing semper in ac orci. Vestibulum commodo sem eget tortor lobortis semper. Ut sit amet sapien non velit rutrum egestas sollicitudin in elit. Fusce laoreet leo a sem mattis iaculis");

            mypdf.saveToFileAIR("C:/CFusionMX7/wwwroot/Sites/TestAS/test2.pdf"); // Set YOUR path here

        </script>
    </head>
    
    <body>
    </body>

</html>

I will continue to add functionality and test the AS and JS classes above. I will update the code above as I do. I am very interested to see if others find this idea has potential.

Advertisements

5 thoughts on “Using AlivePDF to print from AIR Javascript via ActionScript3 – part 2

  1. Murray:

    This is an excellent series of posts. I have a similar requirement, working to figure out a way to take a ByteArray from a pdf that was created either client side or retrieved from the server, then pass that to a PrintJob and then call start2(). The reason I want to call start2() is because it is not required to actually require a user to select the printer, it can be automated.

    Curious if you know of a way to take a PDF and pass it to a PrintJob.

    Thoughts?

    Adam

    • Hi Adam,

      Sorry for the non-response – I only noticed your post when i was approving another.

      @Adam and @pWEN

      Circumstances took me away from continuing down this path and I am sorry to say I have no more info that I can give. I am not working in this area at present, althouh may return in the future (I hope).

      If you discover anything please post back here so others may benefit.

  2. Hello, I was wondering if you could help me with using AlivePDF in Flash Pro 5.5 (not AIR). I’m trying to create a very simple PDF and display it in the browser, but when I open it, it is gibberish text, like:

    Index of file:////Volumes/Macintosh HD/Users/noobie/Documents/Adobe Flash Builder 4.5/testquiz/src/?name=testInline.pdf&method=inline?%PDF-1.5 1 0 obj <> endobj 3 0 obj <> endobj 4 0 obj <> stream BT /F1 9.00 Tf ET BT 1800.00 -958.11 Td (blah blah blah) Tj ET endstream endobj 5 0 obj <</Type /OCG /Name (print) /Usage <</Print <> /View <>>>>> endobj 6 0 obj <</Type /OCG /Name (view) /Usage <</Print…..

    If I try saving locally, it gives me a blank PDF document. I'm using Flash Pro 5.5, ActionScript 3, and compiling for Flash Player 10. I am not making an AIR or Flex application. Would you be able to help me?

  3. Using AlivePDF to print from AIR Javascript via ActionScript3 ..
    Where is it showing how to print PDF from AIR? What am I missing here?

    • The example doesnt actually open the pdf you created. The line
      mypdf.saveToFileAIR("C:/CFusionMX7/wwwroot/Sites/TestAS/test2.pdf"); // Set YOUR path here
      generates the pdf then you would need to provide a link to it to allow the user to open it. You may also be able to stream it to an AIR window but I am too braindead to think how to do that right now. I have been away from AIR for a while.

      Thanks,
      Murray

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s