/*
//
//   ADOBE SYSTEMS INCORPORATED
//   Copyright (C) 2000-2003 Adobe Systems Incorporated
//   All rights reserved.
//
//   NOTICE: Adobe permits you to use, modify, and distribute this file
//   in accordance with the terms of the Adobe license agreement
//   accompanying it. If you have received this file from a source other
//   than Adobe, then your use, modification, or distribution of it
//   requires the prior written permission of Adobe.
//
*/
/*
// Acrobat PDF Library Sample printpdf
//
// This sample application demonstrates how to use the method PDFLPrintDoc to print
// a PDF document to both a printer and a PostScript File. For this sample to work
// you need to:
//
//                           Set IN_FILE and OUT_FILE to control input and destination
//                           Set EMIT_TO_FILE to 'true,' or 'false' if printing to printer
//                           On Windows:
//                                           specify the appropriate printer information for DEVICE_NAME and PORT_NAME
//                           On Mac:
//                                           If printing to printer, set SHOW_PRINT_DIALOG to 'true' or 'false'
//                                           NOTE: if the user chooses to print to file, there will be a 'Save File' 
//                                           dialog, which probably will be different than the defaults. 
*/


/* Some macros to control the sample*/
#define IN_FILE "../sources/printpdf.pdf"
#define OUT_FILE "out.ps"

/* On Windows define these */
#define DEVICE_NAME   "\\\\PCPRINT\\Brave-HP5m-w06513-q"
#define PORT_NAME   "Ne04"







#ifdef MAC_PLATFORM
#include <sys/types.h>
#include <sys/stat.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>


/* Acrobat Toolkit header files */
#include "PDFInit.h"
#include "CosCalls.h"
#include "CorCalls.h"
#include "ASCalls.h"
#include "PDCalls.h"

/* Printing Support */

#include "PDFLPrint.h"
#include "MyPDFLibUtils.h"

/* output to printer or file */
#define EMIT_TO_FILE 1
/* On Mac set SHOW_PRINT_DIALOG to true or false, but only if printing to printer */
#if (EMIT_TO_FILE == 0)
#define SHOW_PRINT_DIALOG false
#endif
/* from the utility directory */
#ifdef MAC_PLATFORM
#include "MacUtils.h"
#include "Cocoa/Cocoa.h"
#endif

extern  ACCB1  ASInt32   ACCB2   PrintstmWriteProc( char  *data,  ASInt32  nBytes, void  *clientData);
extern  ACCB1  ASInt32   ACCB2   PrintstmDestroyProc( void  *clientData);

void   PrintToFile(PDDoc  doc);
void   PrintToPrinter(PDDoc  doc);

void   SetupPDPrintParams(PDPrintParams psParams);
void   SetupPDFLPrintUserParams(PDFLPrintUserParams rec);

void   UnsetPDPrintParams(PDPrintParams psParams);
void   UnsetPDFLPrintUserParams(PDFLPrintUserParams rec);

int   MainProc();
int   MainProc()
{
                PDDoc  pdoc =  NULL;
                ASErrorCode  errCode = 0;

                /*
                 * All toolkit API calls MUST have a DURING HANDLER
                 * around them except PDFLInit() and PDFLTerm()
                 */
                DURING
#if MAC_PLATFORM
                                /* Set the working directory to where the application was launched from
                                 * This must be done after initializing the Toolkit
                                 */
                               OSErr err =  PDFLSetWorkDirToAppDir();
#endif
                                /* Open a document */
                               pdoc =  MyPDDocOpen(IN_FILE);

                                if  (pdoc)
                               {
#if (EMIT_TO_FILE == 1)
                                                PrintToFile(pdoc);
#else
                                                PrintToPrinter(pdoc);
#endif
                               }

                HANDLER
                                /* Error handling code.   You can use this to recover from an error
                                 * raised in the toolkit. 
                                 */
                                 errCode =  ERRORCODE;
                END_HANDLER;

                DisplayErrorAndWarnings(pdoc, errCode);

                if (pdoc)                PDDocClose(pdoc);

                return  0;
}

/*
               Setup the file to print to, and fill the print recs for printing to file
*/
void   PrintToFile(PDDoc  doc)
{
                ASFile  pFile =  NULL;
                ASStm  printStm =  NULL;

#ifdef MAC_PLATFORM
                ASPathName  path =  GetMacPath(OUT_FILE);
#else
                ASPathName  path =  ASFileSysCreatePathName(NULL,ASAtomFromString( "Cstring" ),OUT_FILE,NULL);
#endif

                /* Create   writeable ProcStm to handle the print stream */
                ASFileSysOpenFile  (NULL, path,  ASFILE_WRITE  |  ASFILE_CREATE, &pFile);
               printStm =  ASFileStmWrOpen  (pFile, 0);

                ASErrorCode  errCode = 0;
               
                if  (printStm)
               {
                               PDPrintParamsRec psParams;
                               PDFLPrintUserParamsRec rec;

                                SetupPDPrintParams(&psParams);                   
                                SetupPDFLPrintUserParams(&rec);
                               
                                /* if rec.emitToFile is false, then rec.emitToPrinter
                                 * is true by default and vice versa
                                 */
                               rec.emitToFile =  true ;
                               rec.emitToPrinter =  false ;

                       rec.printStm = printStm;        /* send output to a writeable stm*/
                       
                        /* connect the two structures */
                               rec.printParams = &psParams;
                               
                                DURING
                                               PDFLPrintDoc(doc, &rec);
                                HANDLER
                                               errCode =  ERRORCODE;
                                END_HANDLER;

                                ASStmClose(printStm);      /* remember to close the ProcStm or you
                                                                                                                                 * get an incomplete PS file */
#if MAC_PLATFORM
                                if (!errCode)
                               {
                                                /* Set the type and creator correctly for a PS file vs. an EPS file */
                                                if  (psParams.outputType == PDOutput_PS)
                                                                ASFileSysSetTypeAndCreator  (NULL, path,  'TEXT' ,  'DSTL' );
                                                else
                                                                ASFileSysSetTypeAndCreator  (NULL, path,  'EPSF' ,  'ART5' );
                               }
#endif   

                                UnsetPDPrintParams(&psParams);
                                UnsetPDFLPrintUserParams(&rec);
               }
               
                ASFileSysReleasePath(NULL, path);
                if (pFile)
                                ASFileClose(pFile);

                if (errCode)
                                ASRaise(errCode);
}

/*
               Fill the print recs for printing to printer
*/
void   PrintToPrinter(PDDoc  doc)
{
               PDPrintParamsRec psParams;           
               PDFLPrintUserParamsRec rec;
               
                SetupPDPrintParams(&psParams);
                SetupPDFLPrintUserParams(&rec);
               
       rec.emitToFile =  false ;
       rec.emitToPrinter =  true ;
       
        /* connect the two structures */
               rec.printParams = &psParams;

                ASErrorCode  errCode = 0;

#ifdef MAC_PLATFORM
/* set up dialog, and handle print settings */
#if (SHOW_PRINT_DIALOG == true)
               {
                               PMPrintSession printSession;
                               PMPrintSettings printSettings;
                               PMPageFormat pageFormat;
                               Boolean accepted =  true ;
                               
                               PMCreateSession(&printSession);

                               PMCreatePrintSettings(&printSettings);
                               PMSessionDefaultPrintSettings(printSession, printSettings);

                               PMCreatePageFormat(&pageFormat);
                               PMSessionDefaultPageFormat (printSession, pageFormat);

                               NSPrintInfo *thePrintInfo = [NSPrintInfo sharedPrintInfo];
             
               [NSApplication sharedApplication];
               NSPrintPanel *printPanel = [NSPrintPanel printPanel];
               NSInteger result = [printPanel runModalWithPrintInfo: thePrintInfo];
               printSession = (PMPrintSession)[thePrintInfo PMPrintSession];
               pageFormat = (PMPageFormat)[thePrintInfo PMPageFormat];
               printSettings = (PMPrintSettings)[thePrintInfo PMPrintSettings];
               
               rec.printSession = printSession;
                               rec.printSettings = printSettings;
                               rec.pageFormat = pageFormat;
                               UInt32 first, last, numCopies;
                               PMGetFirstPage(printSettings, &first);
                               rec.startPage = first-1;  /* mac defines first page as 1, PDFL as 0 */
                               PMGetLastPage(printSettings, &last);
                               rec.endPage = last;  /* endPage is not inclusive. */
                               PMGetCopies(printSettings, &numCopies);
                               rec.nCopies = numCopies;
                               
                                if (accepted)
                               {
#endif
#endif   
                                                DURING
                                                               PDFLPrintDoc(doc, &rec);               
                                                HANDLER
                                                               errCode =  ERRORCODE;
                                                END_HANDLER;
               
#ifdef MAC_PLATFORM
/* clean up printsettings */
#if (SHOW_PRINT_DIALOG == true)
                               }
                               
                               PMRelease(printSession);
                               PMRelease(printSettings);
                               PMRelease(pageFormat);   
               }
#endif
#endif

                UnsetPDPrintParams(&psParams);
                UnsetPDFLPrintUserParams(&rec);

                if (errCode)
                                ASRaise(errCode);
}

/*
               Set up PDPrintParams struct. 
               Set the same independent of platform or destination for printing.
               Contains options for indicating how a document should be printed.
*/
void   SetupPDPrintParams(PDPrintParams psParams)
{
                /* Initialize all PDPrintParams members to 0 or false or NULL */
               memset(psParams, 0,  sizeof (PDPrintParamsRec));

                /* Set up the PDPrintParamsRec */
               psParams->size =  sizeof (PDPrintParamsRec);

               psParams->numRanges = 1;                                                                /* ignored if ranges == NULL */
               psParams->ranges = (PDPageRange*)  ASmalloc  (psParams->numRanges *  sizeof (PDPageRange));
               psParams->ranges[0].startPage = 0;                            // These values of startPage, endPage and pageSpec 
               psParams->ranges[0].endPage = -1;                              // are used to print entire document */
               psParams->ranges[0].pageSpec =  PDAllPages;
                               
               psParams->printWhat =  PDPrintWhat_DOCUMENT_AND_COMMENTS
               psParams->printWhatAnnot = PDPrintWhatAnnot_NoExtras;
               psParams->emitPS =  true ;                                                                /* PostScript printing */
               psParams->psLevel = 3L;                                                                  /* PS Level - 1, 2, or 3 */
               psParams->outputType = PDOutput_PS;
                /* Valid choices for outputType:
               *           PDOutput_PS                         PS file
               *           PDOutput_EPSNoPrev           EPS file with no preview
               *           PDOutput_EPSMacStdPrev   EPS file with standard preview
               *           PDOutput_EPSMacExtPrev   EPS file with extended preview
               */

                /* Options controlling how/whether resources should be included in the
               * PostScript output file. NOTE: For fonts, the parameters are applied
               * in the order in which they are written here. E.g., an embedded Type 1
               * font follows the rule for embedded fonts, not the rule for Type 1
               * fonts. ALSO NOTE: "kIncludeNever" is not allowed for Type 3 fonts.
               */

                /* Valid choices for the inc* params:
               * kIncludeNever, kIncludeOncePerDoc, kIncludeOnEveryPage, kIncludeWhenNeeded and kIncludeByRange
               */
               psParams->incBaseFonts = kIncludeNever;

               psParams->incProcsets = kIncludeOncePerDoc;         

               psParams->fontPerDocVM = 500000;
               psParams->saveVM =  true ;
               
               psParams->emitShowpage =  true ;                    /* showpage emitted? */
               
               psParams->emitDSC =  true ;                    /* emit DSC comments? */
               psParams->setupProcsets =  true ;

                /* convert TT to Type42 (TTasT42) = true if psLevel >= 3, otherwise false. */
               psParams->TTasT42 = (psParams->psLevel >= 3);         

               psParams->scale = 100.0;                                                                                /* scaling factor for entire document */
               psParams->transparencyQuality = 100;     
               psParams->centerCropBox =  true ;

               psParams->emitPageClip =  true ;
               psParams->emitTransfer =  true ;

               psParams->hostBasedCM =  false ;
                //strcpy_safe(psParams->destProfile, "US web coated CMYK", sizeof(psParams->destProfile));

                /* Value of destCSAtom should be DeviceGray or DeviceRGB or DeviceCMYK, etc.
                 * based on the destination printer configuration. */
               psParams->destCSAtom =  ASAtomFromString( "DeviceCMYK" );

               psParams->bitmapResolution = 1200;
               psParams->gradientResolution = 300;
               psParams->useFullResolutionJP2KData =  true ;
               psParams->westernMarksStyle =  true ;

               psParams->numCollatedCopies = 1;
               psParams->emitFlatness =  true ;
               psParams->trapType = kPDPrintTrapNone;

                /* Emit TrueType fonts as CIDType2 (TTasCIDT2) = true if psLevel >= 3, 
                 * otherwise false (emit as CIDFontType0). */
               psParams->TTasCIDT2 = (psParams->psLevel >= 3);
               
               psParams->markStyle = kPDInDesignStyle;
               psParams->lineWidth = 0.25;
               psParams->mirrorprint = kPDPrintFlipNone;

#if EMIT_TO_FILE
               psParams->shrinkToFit =  false ;   
               psParams->rotateAndCenter =  false ;

               psParams->incEmbeddedFonts = kIncludeWhenNeeded;
               psParams->incType1Fonts = kIncludeNever;
               psParams->incType3Fonts = kIncludeNever;
               psParams->incTrueTypeFonts = kIncludeNever;
               psParams->incCIDFonts = kIncludeNever;

               psParams->incOtherResources = kIncludeOnEveryPage;

               psParams->optimizeForSpeed =  false ;

               psParams->setPageSize =  true ;                      /* Level 2 only, uses mediabox for PS files
                                                                                                                                                                 * and crop box for EPS files */
               psParams->emitDeviceExtGState =  true ;
               psParams->farEastFontOpt = PDPDFarEastFont_Download_None;
#else
               psParams->shrinkToFit =  true ;                     
               psParams->rotateAndCenter =  true ;

               psParams->incEmbeddedFonts = kIncludeByRange;
               psParams->incType1Fonts = kIncludeByRange;
               psParams->incType3Fonts = kIncludeOnEveryPage;
               psParams->incTrueTypeFonts = kIncludeByRange;
               psParams->incCIDFonts = kIncludeByRange;

               psParams->incOtherResources = kIncludeByRange;

               psParams->optimizeForSpeed =  true ;

               psParams->setPageSize =  false ;                    /* Level 2 only, uses mediabox for PS files
                                                                                                 * and crop box for EPS files */
               psParams->emitDeviceExtGState =  false ;
               psParams->farEastFontOpt = PDPDFarEastFont_Download_All;
#endif

                /* Flattening Info */
               psParams->flattenInfo = (PDFlatten)  ASmalloc  ( sizeof (PDFlattenRec));
               memset(psParams->flattenInfo, 0,  sizeof (PDFlattenRec));
               psParams->flattenInfo->size =  sizeof (PDFlattenRec);

#if EMIT_TO_FILE
               psParams->flattenInfo->allowShadingOutput =  false ;
               psParams->flattenInfo->allowLevel3ShadingOutput =  false ;
#else
               psParams->flattenInfo->allowShadingOutput =  true ;
               psParams->flattenInfo->allowLevel3ShadingOutput =  true ;
#endif
               
               psParams->flattenInfo->clipComplexRegions =  true ;
                // Default value of strokeToFill should be true.
               psParams->flattenInfo->strokeToFill =  true ; 
               psParams->flattenInfo->internalDPI = 300;
               psParams->flattenInfo->externalDPI = 1200;
               psParams->flattenInfo->pathDPI = 800;
               psParams->flattenInfo->tileSizePts = 250;
               psParams->flattenInfo->maxFltnrImageSize = 5243000;         
               psParams->flattenInfo->preserveOverprint =  true ;
}

void   UnsetPDPrintParams(PDPrintParams psParams)
{
                if (psParams->ranges)
                                ASfree(psParams->ranges);
               psParams->ranges =  NULL;

                if (psParams->flattenInfo)
                                ASfree(psParams->flattenInfo);
               psParams->flattenInfo =  NULL;

               memset(psParams, 0,  sizeof (PDPrintParamsRec));
}

/*
 * The PDFLPrintUserParamsRec is used to specify the types of parameters that
 * a user would usually specify in the print dialogue box. It is different for
 * each platform due to the different printing functionality available. The following
 * code uses conditional compilation so that the sample works on all platforms
 */
void   SetupPDFLPrintUserParams(PDFLPrintUserParams rec)
{
                /* Initialize the struct */
       memset(rec, 0,  sizeof (PDFLPrintUserParamsRec));

                /* Set up the platform independent parameters */
       rec->size =  sizeof (PDFLPrintUserParamsRec);

       rec->dontEmitListLen = 0;
       rec->dontEmitList =  NULL;
       
                /* cancelProc is called every 2000
                 * bytes. It should return false to
                 * cancel printing Most likely it will
                 * be used as a progress monitor
               */
       rec->cancelProc =  NULL;
       
       rec->clientData = ( void  *)  "printpdf" ;

       rec->paperWidth = 612;
       rec->paperHeight = 792;


        /* set up the Unix only parameter */
#ifdef UNIX_ENV
       rec->command =  "lp" ;
#endif  /*UNIX_ENV*/

        /* Set up the Windows only parameters */
#ifdef WIN_ENV
       rec->inFileName =  "Test" ;
       rec->outFileName =  NULL;
       rec->driverName =  "winspool" ;

/* For a list of the current print drivers available under WinNT, look at:
** HKEY_CURRENT_USER\Software\Microsoft\WindowsNT\CurrentVersion\Devices
*/
      /* PostScript printer */
     rec->deviceName =  DEVICE_NAME;
     rec->portName =  PORT_NAME;
#endif  /*WIN_ENV*/

#ifndef UNIX_ENV
                /* print one copy, and only the first page. */
     rec->nCopies = 1;
     rec->startPage = 0;
     rec->endPage = 1;
     
     rec->psLevel = 3;

#if EMIT_TO_FILE
     rec->shrinkToFit =  false ;
#else
     rec->shrinkToFit =  true ;
#endif

     rec->binaryOK = 0;
     rec->emitHalftones = 0;
#endif
}

void   UnsetPDFLPrintUserParams(PDFLPrintUserParams rec)
{
               memset(rec, 0,  sizeof (PDFLPrintUserParamsRec));
}

#define INCLUDE_MYPDFLIBAPP_CPP 1
#include "MyPDFLibApp.cpp"
#undef INCLUDE_MYPDFLIBAPP_CPP