1 /***************************************************************************
2  *   Copyright (C) 2006 by Dominik Seichter                                *
3  *   domseichter@web.de                                                    *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19  ***************************************************************************/
20 
21 #include <podofo.h>
22 #include <fontconfig/fontconfig.h>
23 #include <cstdio>
24 
25 using namespace PoDoFo;
26 
27 #define MIN_PAGES 100
28 
29 bool writeImmediately = true;
30 
AddPage(PdfDocument * pDoc,const char * pszFontName,const char * pszImagePath)31 void AddPage( PdfDocument* pDoc, const char* pszFontName, const char* pszImagePath )
32 {
33     PdfPainter painter;
34     PdfPage*   pPage;
35     PdfFont*   pFont;
36     PdfFont*   pArial;
37     PdfImage*  pImage;
38     PdfRect    rect;
39 
40     try {
41         pFont  = pDoc->CreateFont( pszFontName );
42     } catch ( PdfError & e ) {
43         e.PrintErrorMsg();
44         return;
45     }
46     pPage  = pDoc->CreatePage( PdfPage::CreateStandardPageSize( ePdfPageSize_A4 ) );
47     pArial = pDoc->CreateFont( "Arial" );
48     pImage = new PdfImage( pDoc );
49 
50     rect   = pPage->GetMediaBox();
51 
52     const char* pszText = "The red brown fox jumps over the lazy dog!";
53     double     dX       = rect.GetLeft() + 20.0;
54     double     dY       = rect.GetBottom() + rect.GetHeight() - 20.0;
55     double     dW, dH;
56 
57     pFont->SetFontSize( 16.0 );
58     pArial->SetFontSize( 24.0 );
59 
60     painter.SetPage( pPage );
61     painter.SetFont( pFont );
62 
63     dW = pFont->GetFontMetrics()->StringWidth( pszText );
64     dH = -pFont->GetFontMetrics()->GetDescent(); // GetDescent is usually negative!
65 
66     pFont->SetFontSize( 24.0 );
67     dH += pFont->GetFontMetrics()->GetLineSpacing() * 2.0;
68 
69     painter.Rectangle( dX, dY, dW, dH );
70     painter.Stroke();
71 
72     dY -= pFont->GetFontMetrics()->GetLineSpacing();
73     painter.DrawText( dX, dY, "Hello World!" );
74     dY -= pFont->GetFontMetrics()->GetLineSpacing();
75     pFont->SetFontSize( 16.0 );
76     painter.DrawText( dX, dY, pszText );
77 
78     painter.SetFont( pArial );
79     dY -= pArial->GetFontMetrics()->GetLineSpacing();
80     painter.DrawText( dX, dY, "The font used in this example is:" );
81     dY -= pArial->GetFontMetrics()->GetLineSpacing();
82     painter.DrawText( dX, dY, pszFontName );
83     dY -= pArial->GetFontMetrics()->GetLineSpacing();
84 
85 #if defined PODOFO_HAVE_JPEG_LIB || defined PODOFO_HAVE_TIFF_LIB
86     try {
87         pImage->LoadFromFile( pszImagePath );
88     }
89     catch( PdfError & e )
90     {
91         e.PrintErrorMsg();
92     }
93 
94     dY -= (pImage->GetHeight() * 0.5);
95     dX = ((rect.GetWidth() - (pImage->GetWidth()*0.5))/2.0);
96     painter.DrawImage( dX, dY, pImage, 0.5, 0.5 );
97     delete pImage; // delete image right after drawing
98 #endif
99 
100     painter.FinishPage();
101 }
102 
CreateLargePdf(const char * pszFilename,const char * pszImagePath)103 void CreateLargePdf( const char* pszFilename, const char* pszImagePath )
104 {
105     PdfDocument*         pDoc = NULL;
106     FcObjectSet*         pObjectSet;
107     FcFontSet*           pFontSet;
108     FcPattern*           pPattern;
109 
110     if( !FcInit() )
111     {
112         fprintf( stderr, "Cannot load fontconfig!\n");
113         return;
114     }
115 
116     pPattern   = FcPatternCreate();
117     pObjectSet = FcObjectSetBuild( FC_FAMILY, FC_STYLE, NULL );
118     pFontSet   = FcFontList( 0, pPattern, pObjectSet );
119 
120     FcObjectSetDestroy( pObjectSet );
121     FcPatternDestroy( pPattern );
122 
123     if( writeImmediately )
124         pDoc = new PdfStreamedDocument( pszFilename );
125     else
126         pDoc = new PdfMemDocument();
127 
128     if( pFontSet )
129     {
130         for( int i=0; i< (pFontSet->nfont > MIN_PAGES ? MIN_PAGES : pFontSet->nfont );i++ )
131         {
132             FcValue v;
133 
134             //FcPatternPrint( pFontSet->fonts[i] );
135             FcPatternGet( pFontSet->fonts[i], FC_FAMILY, 0, &v );
136             //font = FcNameUnparse( pFontSet->fonts[i] );
137             printf(" -> Drawing with font: %s\n", reinterpret_cast<const char*>(v.u.s) );
138             AddPage( pDoc, reinterpret_cast<const char*>(v.u.s), pszImagePath );
139         }
140 
141         FcFontSetDestroy( pFontSet );
142     }
143 
144 
145     if( writeImmediately )
146         static_cast<PdfStreamedDocument*>(pDoc)->Close();
147     else
148         static_cast<PdfMemDocument*>(pDoc)->Write( pszFilename );
149     delete pDoc;
150 }
151 
usage()152 void usage()
153 {
154     printf("Usage: LargetTest [-m] output_filename image_file\n"
155            "       output_filename: filename to write produced pdf to\n"
156            "       image_file:      An image to embed in the PDF file\n"
157            "Options:\n"
158            "       -m               Build entire document in memory before writing\n"
159            "\n"
160            "Note that output should be the same with and without the -m option.\n");
161 }
162 
main(int argc,char * argv[])163 int main( int argc, char* argv[] )
164 {
165     if( argc < 3 || argc > 4 )
166     {
167         usage();
168         return 1;
169     }
170     else if ( argc == 4)
171     {
172         // Handle options
173         // Is this argument an option?
174         if (argv[1][0] != '-')
175         {
176             usage();
177             return 1;
178         }
179         // Is it a recognised option?
180         if (argv[1][1] == 'm')
181         {
182             // User wants us to build the whole doc in RAM before writing it out.
183             writeImmediately = false;
184             ++argv;
185         }
186         else
187         {
188             printf("Unrecognised argument: %s", argv[1]);
189             usage();
190             return 1;
191         }
192     }
193 
194     try {
195         CreateLargePdf( argv[1], argv[2] );
196 
197         printf("\nWrote the PDF file %s successfully\n", argv[1] );
198 
199     } catch( PdfError & e ) {
200         e.PrintErrorMsg();
201         return e.GetError();
202     }
203 
204     return 0;
205 }
206