<?PHP

#
#   Axis--PSDocument.php
#   PHP Objects for Generating PostScript and PDF Documents
#
#   Copyright 1999-2001 Axis Data
#   This code is free software that can be used or redistributed under the
#   terms of Version 2 of the GNU General Public License, as published by the
#   Free Software Foundation (http://www.fsf.org).
#
#   Author:  Edward Almasy (almasy@axisdata.com)
#
#   Part of the AxisPHP library v1.2.4
#   For more information see http://www.axisdata.com/AxisPHP/
#


class PSDocument {

    # ---- PUBLIC INTERFACE --------------------------------------------------

    # object constructor
    function PSDocument()
    {
        # print document header
        $this->PrintRaw("
                gsave
                ");

        # set default font for document
        $this->SetFont("Times-Roman", 12);

        # set reasonable default starting coordinates
        $this->MoveTo(100, 100);
    }

    function NextPage()
    {
        # increment our internal page number value
        $CurrentPageNumber = $this->PageNumber();
        $CurrentPageNumber++;
        $this->PageNumber($CurrentPageNumber++);
    }

    function NextLine()
    {
        $SpacingMultiplier = 1.35;

        if ($this->TextAngle == 0)
        {
            $this->YPos -= (int)($this->GetFontHeight() * $SpacingMultiplier);
        }
        elseif ($this->TextAngle == 90)
        {
            $this->XPos -= (int)($this->GetFontHeight() * $SpacingMultiplier);
        }
    }

    function MoveToX($NewXPos)
    {
        $this->XPos = $NewXPos;
    }

    function MoveToY($NewYPos)
    {
        $this->YPos = $NewYPos;
    }

    function MoveToRelX($NewXPos)
    {
        $this->XPos = $this->CurrentXPos() + $NewXPos;
    }

    function MoveToRelY($NewYPos)
    {
        $this->YPos = $this->CurrentYPos() + $NewYPos;
    }

    function MoveTo($NewXPos, $NewYPos)
    {
        $this->MoveToX($NewXPos);
        $this->MoveToY($NewYPos);
    }

    function CurrentXPos()
    {
        return $this->XPos;
    }

    function CurrentYPos()
    {
        return $this->YPos;
    }

    function WritePostscriptToFile($FileName)
    {
        # open output file
        $OutputFilePointer = fopen($FileName, "w+") or die("unable to open PostScript output file ".$FileName);

        # write out document header
        fwrite($OutputFilePointer, "%!PS-Adobe-2.0
                %%Creator: AxisPHP
                %%Orientation: Landscape
                %%EndComments
                /UseFont { findfont exch scalefont setfont } bind def
                %%EndProlog
                ");

        # for each page that has text
        for ($Index = 1;  $Index <= $this->HighestPageNumber;  $Index++)
        {
            # if there is text on the page
            if (strlen($this->PageText[$Index]) > 0)
            {
                # write out page text
                fwrite($OutputFilePointer, $this->PageText[$Index]);

                # write out page footer
                fwrite($OutputFilePointer, "
                        stroke
                        grestore
                        showpage
                        ");
            }
        }

        # write out document footer
        fwrite($OutputFilePointer, "
                %%Trailer
                %%EOF
                ");

        # close output file
        fclose($OutputFilePointer);
    }

    function WritePDFToFile($OutputFileName)
    {
        # create PostScript file
        $PSFileName = tempnam("/tmp", $FileNamePrefix) or die("unable to generate temporary file name for PostScript file for PDF generation");
        $this->WritePostscriptToFile($PSFileName);

        # build PostScript-to-PDF command string
        $Command = sprintf("cat %s | gs -q -sDEVICE=pdfwrite -sOutputFile=%s - ",
                $PSFileName, $OutputFileName);

        # run PostScript-to-PDF command
        system($Command);

        # remove PostScript file
        system(sprintf("rm %s", $PSFileName));
    }

    function SetPrintCommand($NewPrintCommand)
    {
        $this->PrintCommand = $NewPrintCommand;
    }

    function PrintDocument($FileNamePrefix = "PSDocument")
    {
        # generate file name
        $OutputFileName = tempnam("/tmp", $FileNamePrefix) or die("unable to generate temporary file name for PostScript file");

        # dump document to file
        $this->WritePostscriptToFile($OutputFileName);

        # substitute file name into print command
        $Command = str_replace("%f", $OutputFileName, $this->PrintCommand);

        # issue print command
        system(EscapeShellCmd($Command));

        # return file name to caller
        return $OutputFileName;
    }

    function SetPageSize($PointsHigh, $PointsWide)
    {
        $this->PageHeightInPoints = $PointsHigh;
        $this->PageWidthInPoints = $PointsWide;
    }

    function SetTextWrapLength($NewLength = 0)
    {
        $this->TextWrapLength = $NewLength;
    }

    function SetFont($FontName, $FontSize)
    {
        $this->PrintRaw(sprintf("
                %s /%s UseFont
                ", $FontSize, $FontName));

        $this->FontSize = $FontSize;
    }

    function GetFontHeight()
    {
        return (int)($this->FontSize * 0.8);   
    }

    function PageNumber($NewPageNumber = -1)
    {
        if ($NewPageNumber != -1)
        {
            $this->PageNumber = $NewPageNumber;

            if ($this->PageNumber > $this->HighestPageNumber)
            {
                $this->HighestPageNumber = $this->PageNumber;
            }
        }
        return $this->PageNumber;
    }

    function PrintText($TextToPrint)
    {
        # trim off any leading or trailing whitespace in string
        $TextToPrint = trim($TextToPrint);

        # split string into pieces delineated by newlines
        $TextArray = split("\n", $TextToPrint);

        # for each string in array
        for ($Index = 0;  $Index < count($TextArray);  $Index++)
        {
            # trim off any leading or trailing whitespace in string
            $Text = trim($TextArray[$Index]);

            # if string is not empty
            if (strlen($Text) > 0)
            {
                # if text wrap length is set and string is longer than that
                if (($this->TextWrapLength > 0) 
                        && (strlen($Text) > $this->TextWrapLength))
                {
                    # append portion of string beyond wrap len to next string
                    $TextArray[$Index + 1] = substr($Text, $this->TextWrapLength)
                            ." ".$TextArray[$Index + 1];

                    # trim off portion of string beyond wrap len
                    $Text = substr($Text, 0, $this->TextWrapLength);
                }

                # escape any Postscript delimiters in string
                $Text = str_replace("(", "\(", $Text);
                $Text = str_replace(")", "\)", $Text);

                # print string piece
                if ($this->TextAngle == 0)
                {
                    $this->PrintRaw(sprintf("%s %s moveto\n", 
                            (int)$this->XPos, 
                            (int)($this->YPos - $this->GetFontHeight())));
                }
                elseif ($this->TextAngle == 90)
                {
                    $this->PrintRaw(sprintf("%s %s moveto\n", 
                            (int)($this->XPos - $this->GetFontHeight()),
                            (int)$this->YPos));
                }
                if ($this->TextAngle != 0)
                {
                    $this->PrintRaw(sprintf("-%s rotate\n", 
                            (int)$this->TextAngle));
                }
                $this->PrintRaw(sprintf("(%s) show\n", $Text));
                if ($this->TextAngle != 0)
                {
                    $this->PrintRaw(sprintf("%s rotate\n", 
                            (int)$this->TextAngle));
                }
            }

            # if not last string
            if ($Index < (count($TextArray) - 1))
            {
                # move to next row
                $this->NextLine();
            }
        }
    }

    function PrintTextAt($XPos, $YPos, $TextToPrint)
    {
        $this->MoveTo($XPos, $YPos);
        $this->PrintText($TextToPrint);
    }

    function TextAngle($NewAngle = -1)
    {
        if ($NewAngle != -1)
        {
            $this->TextAngle = $NewAngle % 360;
        }

        return $this->TextAngle;
    }

    function UseLandscapeOrientation()
    {
        $this->PrintRaw(sprintf("
                90 rotate
                0 %s translate
                ", (0 - $this->PageWidthInPoints)));
    }

    function DefineStyle($StyleName, $FontName, $FontSize)
    {
        $this->StyleInfo[$StyleName]["FontName"] = $FontName;
        $this->StyleInfo[$StyleName]["FontSize"] = $FontSize;
    }

    function UseStyle($StyleName)
    {
        $this->PrintRaw(sprintf("
                %s /%s UseFont
                ", 
                $this->StyleInfo[$StyleName]["FontSize"], 
                $this->StyleInfo[$StyleName]["FontName"]));

        $this->FontSize = $this->StyleInfo[$StyleName]["FontSize"];
    }

    function PrintRaw($TextToPrint)
    {
        # add string to page text
        $this->PageText[$this->PageNumber] .= $TextToPrint;
    }


    # ---- PRIVATE INTERFACE -------------------------------------------------

    # array of text for each page
    var $PageText;

    # current print position
    var $XPos = 0;
    var $YPos = 0;

    # current page number
    var $PageNumber = 1;

    # highest page number with text on it
    var $HighestPageNumber = 1;

    # current text rotation angle
    var $TextAngle = 0;

    # values for last table printed
    var $TableXPos = 0;
    var $TableYPos = 0;
    var $TableRowHeight = 0;
    var $TableColWidth = 0;

    # values for last font set
    var $FontHeight = 12;

    # default to letter size (792x612)
    var $PageHeightInPoints = 792;
    var $PageWidthInPoints = 612;

    # printing command
    var $PrintCommand = "lpr %f";

    # font style settings
    var $StyleInfo;

    # current string wrap length
    var $TextWrapLength = 0;
}

?>
