/*
//
//   ADOBE SYSTEMS INCORPORATED
//   Copyright (C) 2000-2005 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.
//
*/
//
// PatternUtils.cpp : utility routines
//

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

#include "MyPDFLibUtils.h"
#include "PatternUtils.h"

#ifdef MAC_ENV                                                                   
               #include "macUtils.h"
#endif

void   s_SetContentToPage(PDPage  pdPage,  PDEContent  pdeContent)
{

        CosObj  cosPage =  PDPageGetCosObj(pdPage);
        CosDoc  cosDoc =  CosObjGetDoc(cosPage);
        CosObj  cosContents;
        CosObj  cosResources;

                PDEContentToCosObj(pdeContent,  kPDEContentToPage, 0, 0, cosDoc, 0,
                                             &cosContents, &cosResources);

                /* place content and resource objects into page             */
                CosDictPut(cosPage,  ASAtomFromString( "Contents" ), cosContents);
                CosDictPut(cosPage,  ASAtomFromString( "Resources" ), cosResources);
}


  void   s_SaveDoc(PDDoc  newDoc,  const   char * fileName)
{
                if ( fileName ==  NULL  ) 
                               fileName =  "out.pdf" ;

#if !MAC_ENV
                ASPathName  newPathName =  ASPathFromPlatformPath(( void *)fileName);
                PDDocSave(newDoc,  PDSaveFull  |  PDSaveCollectGarbage, newPathName,  ASGetDefaultFileSys(),  NULLNULL);
                ASFileSysReleasePath(0, newPathName);
#else
                ASPathName  macPath =  GetMacPath(fileName);
                PDDocSave(newDoc,  PDSaveFull,macPath ,  ASGetDefaultFileSys(),  NULLNULL);
                ASFileSysReleasePath(ASGetDefaultFileSys(),macPath);
#endif
}


  PDPage   s_CreateNewPage(PDDoc  newDoc)
{
        ASFixedRect  mediaBox;
       memset(&mediaBox, 0,  sizeof (ASFixedRect));
       mediaBox.bottom  =  FloatToASFixed(0.0);
       mediaBox.left  =  FloatToASFixed(0.0);
       mediaBox.top  =  FloatToASFixed(11.0 * 72.0);
       mediaBox.right  =  FloatToASFixed(8.5 * 72.0);

                PDPage  newPage =  PDDocCreatePage(newDoc,  PDBeforeFirstPage, mediaBox);

        return  newPage;
}

PDEPath   s_CreateBlackSquare()
{
        ASFixed  notused =  fixedZero;

        PDEPath  pdePath =  PDEPathCreate();
        PDEPathAddSegment(pdePath,  kPDEMoveTo,  fixedZerofixedZero, notused, notused, notused, notused);
        PDEPathAddSegment(pdePath,  kPDELineTo,  fixedZero,    fixedTen, notused, notused, notused, notused);
        PDEPathAddSegment(pdePath,  kPDELineTo,    fixedTen,    fixedTen, notused, notused, notused, notused);
        PDEPathAddSegment(pdePath,  kPDELineTo,    fixedTenfixedZero, notused, notused, notused, notused);
        PDEPathAddSegment(pdePath,  kPDEClosePath, notused, notused, notused, notused, notused, notused);
        PDEPathSetPaintOp(pdePath,  kPDEFill|kPDEStroke);

        PDEGraphicState  pdeGState;
        PDEDefaultGState(&pdeGState,  sizeof (PDEGraphicState));
        PDEElementSetGState((PDEElement)pdePath, &pdeGState,  sizeof (PDEGraphicState));
       
                if  (pdeGState.fillColorSpec.space
                                PDERelease((PDEObject) pdeGState.fillColorSpec.space);
        if  (pdeGState.strokeColorSpec.space)   
                                PDERelease((PDEObject) pdeGState.strokeColorSpec.space);

        return  pdePath;
}

  PDEPath   s_CreateSquare( double  scale,  double  angle,  double  offset_x,  double  offset_y)
{
        PDEPath  square =  s_CreateBlackSquare();

        double  sinR = sin( angle ) * scale;
        double  cosR = cos( angle ) * scale;

        ASDouble  x = offset_x*72.0;
        ASDouble  y = offset_y*72.0;

        ASDoubleMatrix  mtrx = { cosR, sinR, -sinR, cosR, x, y };
        PDEElementSetMatrixEx((PDEElement)square, &mtrx);

        return  square;
}

  PDEPath   s_CreateColorSquare( double  red,  double  green,  double  blue,
                                                                      double  scale,  double  angle,
                                                                      double  offset_x,  double  offset_y)
{
                // colors
        PDEGraphicState  gState;
       memset(&gState, 0,  sizeof (PDEGraphicState));

       gState.strokeColorSpec.space  =  PDEColorSpaceCreateFromName(ASAtomFromString( "DeviceRGB" ));
       gState.fillColorSpec.space  =  PDEColorSpaceCreateFromName(ASAtomFromString( "DeviceRGB" ));

       gState.miterLimit  =  fixedTen;
       gState.flatness  =  fixedOne;
       gState.lineWidth  =  FloatToASFixed(( float )0.5);
       gState.strokeColorSpec.value.color[0] =  FloatToASFixed(green);
       gState.strokeColorSpec.value.color[1] =  FloatToASFixed(blue);
       gState.strokeColorSpec.value.color[2] =  FloatToASFixed(red);

       gState.fillColorSpec.value.color[0] =  FloatToASFixed(red);
       gState.fillColorSpec.value.color[1] =  FloatToASFixed(green);
       gState.fillColorSpec.value.color[2] =  FloatToASFixed(blue);

                // create a black square
        PDEPath  pdePath =  s_CreateSquare(scale, angle, offset_x, offset_y);

                // add color to it
        PDEElementSetGState  ((PDEElement)pdePath, &gState,  sizeof (gState));

                if  (gState.strokeColorSpec.spacePDERelease((PDEObject) gState.strokeColorSpec.space);
                if  (gState.fillColorSpec.spacePDERelease((PDEObject)gState.fillColorSpec.space);
        return  pdePath;
}

PDEPattern   s_CreatePatternFromContent(CosDoc  cosDoc,  PDEContent  pdeContent)
{
        int  step = 60;
        CosObj  cosPattern;
        CosObj  cosResources;

                // convert the PDEContent to a COS object ( a PDF content ) 
                PDEContentToCosObj(pdeContent,  kPDEContentToForm|kPDEContentDoNotResolveForms, 0, 0, cosDoc, 0,
                                             &cosPattern, &cosResources);
               
                // fill data in the pattern dictionary

        // BBox
        CosObj  cosBBobj =  CosNewArray  (cosDoc,  false , 4);
        CosArrayPut  (cosBBobj, 0,  CosNewInteger(cosDoc,  false , 0));
        CosArrayPut  (cosBBobj, 1,  CosNewInteger(cosDoc,  false , 0));
        CosArrayPut  (cosBBobj, 2,  CosNewInteger(cosDoc,  false , step));
        CosArrayPut  (cosBBobj, 3,  CosNewInteger(cosDoc,  false , step));
        CosDictPut  (cosPattern,  ASAtomFromString( "BBox" ), cosBBobj);
               
                // PDF object type 
                CosDictPut  (cosPattern,  ASAtomFromString( "Type" ),  CosNewName(cosDoc,  false ,  ASAtomFromString  ( "Pattern" )));
       
                // PatternType = 1 for tiling pattern
                CosDictPut  (cosPattern,  ASAtomFromString( "PatternType" ),  CosNewInteger(cosDoc,  false , 1));
     
                // PaintType = 1 for colored tiling pattern
                CosDictPut  (cosPattern,  ASAtomFromString( "PaintType" ),  CosNewInteger(cosDoc,  false , 1));

                // TilingType = 1 for constent spacing
        CosDictPut  (cosPattern,  ASAtomFromString( "TilingType" ),  CosNewInteger(cosDoc,  false , 1));

                // horizontal spacing between pattern cells 
        CosDictPut  (cosPattern,  ASAtomFromString( "XStep" ),  CosNewInteger(cosDoc,  false , step));

                // vertical spacing between pattern cells 
        CosDictPut  (cosPattern,  ASAtomFromString( "YStep" ),  CosNewInteger(cosDoc,  false , step));

                // must put the resource COS object into the dictionary
        CosDictPut  (cosPattern,  ASAtomFromString( "Resources" ), cosResources);
       
                // now, create it!
        PDEPattern  pattern =  PDEPatternCreate(&cosPattern);

        return  pattern;
}

PDEPath   s_CreatePatternSquare(PDEPattern  pdePattern,
                                                                          double  scale,  double  angle,
                                                                          double  offset_x,  double  offset_y)
{
        PDEGraphicState  gState;
       memset(&gState, 0,  sizeof (PDEGraphicState));

        PDEColorSpaceStruct  pdeCSStruct;
       pdeCSStruct.patternbase  =  PDEColorSpaceCreateFromName(ASAtomFromString( "DeviceRGB" ));

                // note pattern is used here
       gState.fillColorSpec.space  =  PDEColorSpaceCreate(ASAtomFromString( "Pattern" ), &pdeCSStruct);
       gState.fillColorSpec.value.colorObj  = (PDEObject)pdePattern;

                // colors
       gState.strokeColorSpec.space  =  PDEColorSpaceCreateFromName(ASAtomFromString( "DeviceRGB" ));
       gState.strokeColorSpec.value.color[0] =  fixedZero;
       gState.strokeColorSpec.value.color[1] =  fixedZero;
       gState.strokeColorSpec.value.color[2] =  fixedZero;

       gState.miterLimit  =  fixedTen;
       gState.flatness  =  fixedOne;
       gState.lineWidth  =  FloatToASFixed(( float )0.25);

                // create a black square
        PDEPath  pdePath =  s_CreateSquare(scale, angle, offset_x, offset_y);

                // add color pattern to it
        PDEElementSetGState  ((PDEElement)pdePath, &gState,  sizeof (gState));

                if  (pdeCSStruct.patternbasePDERelease((PDEObject) pdeCSStruct.patternbase);
                if  (gState.fillColorSpec.spacePDERelease((PDEObject) gState.fillColorSpec.space);
                if  (gState.strokeColorSpec.space)    PDERelease((PDEObject) gState.strokeColorSpec.space);
        return  pdePath;
}

  PDEContent   s_CreateBoxesWithColors(PDDoc  pdDoc)
{
        // create the primary page content
        PDEContent  pdeContent =  PDEContentCreate();

                // a few colored squares will be create and add to the PDF content
                // They will make the graphics pattern cell.
        PDEPath  square = 0;
       square =  s_CreateColorSquare(0.9, 0.0, 0.0, 2.5, 0.1, 0.0, 0.1);
        PDEContentAddElem(pdeContent,  kPDEBeforeFirst, (PDEElement)square);
                if  (square)  PDERelease((PDEObject) square);

       square =  s_CreateColorSquare(0.0, 0.9, 0.0, 3.0, 2.5, 0.9, 0.3);
        PDEContentAddElem(pdeContent,  kPDEBeforeFirst, (PDEElement)square);
                if  (square)  PDERelease((PDEObject) square);

       square =  s_CreateColorSquare(0.0, 0.0, 0.9, 4.0, 1.2, 0.7, 0.2);
        PDEContentAddElem(pdeContent,  kPDEBeforeFirst, (PDEElement)square);
                if  (square)  PDERelease((PDEObject) square);

       square =  s_CreateColorSquare(0.9, 0.9, 0.0, 3.5, 2.2, 0.3, 0.6);
        PDEContentAddElem(pdeContent,  kPDEBeforeFirst, (PDEElement)square);
                if  (square)  PDERelease((PDEObject) square);

       square =  s_CreateColorSquare(0.0, 0.9, 0.9, 3.2, 1.0, 0.3, -0.2);
        PDEContentAddElem(pdeContent,  kPDEBeforeFirst, (PDEElement)square);
                if  (square)  PDERelease((PDEObject) square);

       square =  s_CreateColorSquare(0.9, 0.0, 0.9, 4.3, 1.3, 0.4, 0.5);
        PDEContentAddElem(pdeContent,  kPDEBeforeFirst, (PDEElement)square);
                if  (square)  PDERelease((PDEObject) square);

       square =  s_CreateColorSquare(0.9, 0.7, 0.5, 3.2, 1.0, 0.7, 0.6);
        PDEContentAddElem(pdeContent,  kPDEBeforeFirst, (PDEElement)square);
                if  (square)  PDERelease((PDEObject) square);

                return  pdeContent;
}
  PDEPattern   s_CreatePattern(PDDoc  pdDoc)
{
        CosDoc  cosDoc =  PDDocGetCosDoc(pdDoc);
        PDEContent  pdeContentBoxesWithColors =  s_CreateBoxesWithColors(pdDoc);
        PDEPattern  pdePattern =  s_CreatePatternFromContent(cosDoc, pdeContentBoxesWithColors);
                PDERelease((PDEObject)pdeContentBoxesWithColors);
        return  pdePattern;
}

PDEContent   s_CreateBoxesWithPatterns(PDDoc  pdDoc)
{
                // create a color tiling pattern 
        PDEPattern  pdePattern =  s_CreatePattern(pdDoc);

                // create page content
        PDEContent  pdeContent =  PDEContentCreate();

                // next, create and add 4 pattern squares using the tiling pattern created.
        PDEPath  pdePath = 0;
       pdePath =  s_CreatePatternSquare(pdePattern, 6.0, 2.4, 2.0, 2.0);
        PDEContentAddElem(pdeContent,  kPDEBeforeFirst, (PDEElement)pdePath);
                if  (pdePath)  PDERelease((PDEObject)pdePath);

       pdePath =  s_CreatePatternSquare(pdePattern, 8.0, 1.4, 4.0, 4.0);
        PDEContentAddElem(pdeContent,  kPDEBeforeFirst, (PDEElement)pdePath);
                if  (pdePath)  PDERelease((PDEObject)pdePath);

       pdePath =  s_CreatePatternSquare(pdePattern, 10.0, 0.0, 6.0, 6.0);
        PDEContentAddElem(pdeContent,  kPDEBeforeFirst, (PDEElement)pdePath);
                if  (pdePath)  PDERelease((PDEObject)pdePath);

       pdePath =  s_CreatePatternSquare(pdePattern, 14.0, 0.8, 2.0, 6.0);
        PDEContentAddElem(pdeContent,  kPDEBeforeFirst, (PDEElement)pdePath);
                if  (pdePath)  PDERelease((PDEObject)pdePath);

                PDERelease((PDEObject) pdePattern);

        return  pdeContent;
}