Build, Write and Embed Elements in PDF - PHP Sample Code

Sample code to use Apryse SDK's page writing API to generate new pages, embed fonts & images, and copy graphical elements from one page to another. Sample code provided in Python, C++, C#, Java, Node.js (JavaScript), PHP, Ruby and VB.

Learn more about our Server SDK and PDF Editing & Manipulation Library.

1<?php
2#---------------------------------------------------------------------------------------
3# Copyright (c) 2001-2023 by Apryse Software Inc. All Rights Reserved.
4# Consult LICENSE.txt regarding license information.
5#---------------------------------------------------------------------------------------
6if(file_exists("../../../PDFNetC/Lib/PDFNetPHP.php"))
7include("../../../PDFNetC/Lib/PDFNetPHP.php");
8include("../../LicenseKey/PHP/LicenseKey.php");
9
10# This sample illustrates how to edit existing text strings.
11
12# Relative path to the folder containing the test files.
13$input_path = getcwd()."/../../TestFiles/";
14$output_path = $input_path."Output/";
15
16 PDFNet::Initialize($LicenseKey);
17 PDFNet::GetSystemFontList(); // Wait for fonts to be loaded if they haven't already. This is done because PHP can run into errors when shutting down if font loading is still in progress.
18 $doc = new PDFDoc();
19 $builder = new ElementBuilder(); // ElementBuilder is used to build new Element objects
20 $writer = new ElementWriter(); // ElementWriter is used to write Elements to the page
21
22 // Start a new page ------------------------------------
23 $page = $doc->PageCreate(new Rect(0.0, 0.0, 612.0, 794.0));
24
25 $writer->Begin($page); // begin writing to the page
26
27 // Create an Image that can be reused in the document or on the same page.
28 $img = Image::Create($doc->GetSDFDoc(), $input_path."peppers.jpg");
29
30 $element = $builder->CreateImage($img, new Matrix2D((double)($img->GetImageWidth()/2), -145.0, 20.0, (double)($img->GetImageHeight()/2), 200.0, 150.0));
31 $writer->WritePlacedElement($element);
32 $gstate = $element->GetGState(); // use the same image (just change its matrix)
33 $gstate->SetTransform(200.0, 0.0, 0.0, 300.0, 50.0, 450.0);
34 $writer->WritePlacedElement($element);
35
36 // use the same image again (just change its matrix).
37 $writer->WritePlacedElement($builder->CreateImage($img, 300.0, 600.0, 200.0, -150.0));
38
39 $writer->End(); // save changes to the current page
40 $doc->PagePushBack($page);
41
42 // Start a new page ------------------------------------
43 // Construct and draw a path object using different styles
44 $page = $doc->PageCreate(new Rect(0.0, 0.0, 612.0, 794.0));
45
46 $writer->Begin($page); // begin writing to this page
47 $builder->Reset(); // Reset the GState to default
48
49 $builder->PathBegin(); // start constructing the path
50 $builder->MoveTo(306, 396);
51 $builder->CurveTo(681, 771, 399.75, 864.75, 306, 771);
52 $builder->CurveTo(212.25, 864.75, -69, 771, 306, 396);
53 $builder->ClosePath();
54 $element = $builder->PathEnd(); // the path is now finished
55 $element->SetPathFill(true); // the path should be filled
56
57 // Set the path color space and color
58 $gstate = $element->GetGState();
59 $gstate->SetFillColorSpace(ColorSpace::CreateDeviceCMYK());
60 $gstate->SetFillColor(new ColorPt(1.0, 0.0, 0.0, 0.0)); // cyan
61 $gstate->SetTransform(0.5, 0.0, 0.0, 0.5, -20.0, 300.0);
62 $writer->WritePlacedElement($element);
63
64 // Draw the same path using a different stroke color
65 $element->SetPathStroke(true); // this path is should be filled and stroked
66 $gstate->SetFillColor(new ColorPt(0.0, 0.0, 1.0, 0.0)); // yellow
67 $gstate->SetStrokeColorSpace(ColorSpace::CreateDeviceRGB());
68 $gstate->SetStrokeColor(new ColorPt(1.0, 0.0, 0.0)); // red
69 $gstate->SetTransform(0.5, 0.0, 0.0, 0.5, 280.0, 300.0);
70 $gstate->SetLineWidth(20.0);
71 $writer->WritePlacedElement($element);
72
73 // Draw the same path with with a given dash pattern
74 $element->SetPathFill(false); // this path is should be only stroked
75
76 $gstate->SetStrokeColor(new ColorPt(0.0, 0.0, 1.0)); // blue
77 $gstate->SetTransform(0.5, 0.0, 0.0, 0.5, 280.0, 0.0);
78 $gstate->SetDashPattern(array(30.0), 0);
79 $writer->WritePlacedElement($element);
80
81 // Use the path as a clipping path
82 $writer->WriteElement($builder->CreateGroupBegin()); // Save the graphics state
83 // Start constructing the new path (the old path was lost when we created
84 // a new Element using CreateGroupBegin()).
85 $builder->PathBegin();
86 $builder->MoveTo(306, 396);
87 $builder->CurveTo(681, 771, 399.75, 864.75, 306, 771);
88 $builder->CurveTo(212.25, 864.75, -69, 771, 306, 396);
89 $builder->ClosePath();
90 $element = $builder->PathEnd(); // path is now constructed
91 $element->SetPathClip(true); // this path is a clipping path
92 $element->SetPathStroke(true); // this path should be filled and stroked
93 $gstate = $element->GetGState();
94 $gstate->SetTransform(0.5, 0.0, 0.0, 0.5, -20.0, 0.0);
95
96 $writer->WriteElement($element);
97
98 $writer->WriteElement($builder->CreateImage($img, 100.0, 300.0, 400.0, 600.0));
99
100 $writer->WriteElement($builder->CreateGroupEnd()); // Restore the graphics state
101
102 $writer->End(); // save changes to the current page
103 $doc->PagePushBack($page);
104
105 // Start a new page ------------------------------------
106 $page = $doc->PageCreate(new Rect(0.0, 0.0, 612.0, 794.0));
107
108 $writer->Begin($page); // begin writing to this page
109 $builder->Reset(); // Reset the GState to default
110
111 // Begin writing a block of text
112 $element = $builder->CreateTextBegin(Font::Create($doc->GetSDFDoc(), Font::e_times_roman), 12.0);
113 $writer->WriteElement($element);
114
115 $element = $builder->CreateTextRun("Hello World!");
116 $element->SetTextMatrix(10.0, 0.0, 0.0, 10.0, 0.0, 600.0);
117 $element->GetGState()->SetLeading(15); // Set the spacing between lines
118 $writer->WriteElement($element);
119
120 $writer->WriteElement($builder->CreateTextNewLine()); // New line
121
122 $element = $builder->CreateTextRun("Hello World!");
123 $gstate = $element->GetGState();
124 $gstate->SetTextRenderMode(GState::e_stroke_text);
125 $gstate->SetCharSpacing(-1.25);
126 $gstate->SetWordSpacing(-1.25);
127 $writer->WriteElement($element);
128
129 $writer->WriteElement($builder->CreateTextNewLine()); // New line
130
131 $element = $builder->CreateTextRun("Hello World!");
132 $gstate = $element->GetGState();
133 $gstate->SetCharSpacing(0);
134 $gstate->SetWordSpacing(0);
135 $gstate->SetLineWidth(3);
136 $gstate->SetTextRenderMode(GState::e_fill_stroke_text);
137 $gstate->SetStrokeColorSpace(ColorSpace::CreateDeviceRGB());
138 $gstate->SetStrokeColor(new ColorPt(1.0, 0.0, 0.0)); // red
139 $gstate->SetFillColorSpace(ColorSpace::CreateDeviceCMYK());
140 $gstate->SetFillColor(new ColorPt(1.0, 0.0, 0.0, 0.0)); // cyan
141 $writer->WriteElement($element);
142
143 $writer->WriteElement($builder->CreateTextNewLine()); // New line
144
145 // Set text as a clipping path to the image.
146 $element = $builder->CreateTextRun("Hello World!");
147 $gstate = $element->GetGState();
148 $gstate->SetTextRenderMode(GState::e_clip_text);
149 $writer->WriteElement($element);
150
151 // Finish the block of text
152 $writer->WriteElement($builder->CreateTextEnd());
153
154 // Draw an image that will be clipped by the above text
155 $writer->WriteElement($builder->CreateImage($img, 10.0, 100.0, 1300.0, 720.0));
156
157 $writer->End(); // save changes to the current page
158 $doc->PagePushBack($page);
159
160 // Start a new page ------------------------------------
161 //
162 // The example illustrates how to embed the external font in a PDF document.
163 // The example also shows how ElementReader can be used to copy and modify
164 // Elements between pages.
165
166 $reader = new ElementReader();
167
168 // Start reading Elements from the last page. We will copy all Elements to
169 // a new page but will modify the font associated with text.
170 $reader->Begin($doc->GetPage($doc->GetPageCount()));
171
172 $page = $doc->PageCreate(new Rect(0.0, 0.0, 1300.0, 794.0));
173
174 $writer->Begin($page); // begin writing to this page
175 $builder->Reset(); // Reset the GState to default
176
177 // Embed an external font in the document.
178 $font = Font::CreateTrueTypeFont($doc->GetSDFDoc(), $input_path."font.ttf");
179
180 while (($element = $reader->Next()) != null) // Read page contents
181 {
182 if ($element->GetType() == Element::e_text)
183 {
184 $element->GetGState()->SetFont($font, 12);
185 }
186 $writer->WriteElement($element);
187 }
188
189 $reader->End();
190 $writer->End(); // save changes to the current page
191
192 $doc->PagePushBack($page);
193
194
195 // Start a new page ------------------------------------
196 //
197 // The example illustrates how to embed the external font in a PDF document.
198 // The example also shows how ElementReader can be used to copy and modify
199 // Elements between pages.
200
201 // Start reading Elements from the last page. We will copy all Elements to
202 // a new page but will modify the font associated with text.
203 $reader->Begin($doc->GetPage($doc->GetPageCount()));
204
205 $page = $doc->PageCreate(new Rect(0.0, 0.0, 1300.0, 794.0));
206
207 $writer->Begin($page); // begin writing to this page
208 $builder->Reset(); // Reset the GState to default
209
210 // Embed an external font in the document.
211 $font2 = Font::CreateType1Font($doc->GetSDFDoc(), $input_path."Misc-Fixed.pfa");
212
213 while (($element = $reader->Next())) // Read page contents
214 {
215 if ($element->GetType() == Element::e_text)
216 {
217 $element->GetGState()->SetFont($font2, 12);
218 }
219
220 $writer->WriteElement($element);
221 }
222
223 $reader->End();
224 $writer->End(); // save changes to the current page
225 $doc->PagePushBack($page);
226
227 // Start a new page ------------------------------------
228 $page = $doc->PageCreate();
229 $writer->Begin($page); // begin writing to this page
230 $builder->Reset(); // Reset the GState to default
231
232 // Begin writing a block of text
233 $element = $builder->CreateTextBegin(Font::Create($doc->GetSDFDoc(), Font::e_times_roman), 12.0);
234 $element->SetTextMatrix(1.5, 0.0, 0.0, 1.5, 50.0, 600.0);
235 $element->GetGState()->SetLeading(15); // Set the spacing between lines
236 $writer->WriteElement($element);
237
238 $para = "A PDF text object consists of operators that can show ".
239 "text strings, move the text position, and set text state and certain ".
240 "other parameters. In addition, there are three parameters that are ".
241 "defined only within a text object and do not persist from one text ".
242 "object to the next: Tm, the text matrix, Tlm, the text line matrix, ".
243 "Trm, the text rendering matrix, actually just an intermediate result ".
244 "that combines the effects of text state parameters, the text matrix ".
245 "(Tm), and the current transformation matrix";
246
247 $para_end = strlen($para);
248 $text_run = 0;
249
250 $para_width = 300;
251 $cur_width = 0;
252
253 while ($text_run < $para_end)
254 {
255 $text_run_end = strpos($para, ' ', $text_run);
256 if (!$text_run_end) $text_run_end = $para_end;
257
258 $text = substr($para, $text_run, $text_run_end-$text_run+1);
259 $element = $builder->CreateTextRun($text);
260 if ($cur_width + $element->GetTextLength() < $para_width)
261 {
262 $writer->WriteElement($element);
263 $cur_width += $element->GetTextLength();
264 }
265 else
266 {
267 $writer->WriteElement($builder->CreateTextNewLine()); // New line
268 $element = $builder->CreateTextRun($text);
269 $cur_width = $element->GetTextLength();
270 $writer->WriteElement($element);
271 }
272
273 $text_run = $text_run_end+1;
274 }
275
276 // -----------------------------------------------------------------------
277 // The following code snippet illustrates how to adjust spacing between
278 // characters (text runs).
279 $element = $builder->CreateTextNewLine();
280 $writer->WriteElement($element); // Skip 2 lines
281 $writer->WriteElement($element);
282
283 $writer->WriteElement($builder->CreateTextRun("An example of space adjustments between inter-characters:"));
284 $writer->WriteElement($builder->CreateTextNewLine());
285
286 // Write string "AWAY" without space adjustments between characters.
287 $element = $builder->CreateTextRun("AWAY");
288 $writer->WriteElement($element);
289
290 $writer->WriteElement($builder->CreateTextNewLine());
291
292 // Write string "AWAY" with space adjustments between characters.
293 $element = $builder->CreateTextRun("A");
294 $writer->WriteElement($element);
295
296 $element = $builder->CreateTextRun("W");
297 $element->SetPosAdjustment(140);
298 $writer->WriteElement($element);
299
300 $element = $builder->CreateTextRun("A");
301 $element->SetPosAdjustment(140);
302 $writer->WriteElement($element);
303
304 $element = $builder->CreateTextRun("Y again");
305 $element->SetPosAdjustment(115);
306 $writer->WriteElement($element);
307
308 // Draw the same strings using direct content output...
309 $writer->Flush(); // flush pending Element writing operations.
310
311 // You can also write page content directly to the content stream using
312 // ElementWriter.WriteString(...) and ElementWriter.WriteBuffer(...) methods.
313 // Note that if you are planning to use these functions you need to be familiar
314 // with PDF page content operators (see Appendix A in PDF Reference Manual).
315 // Because it is easy to make mistakes during direct output we recommend that
316 // you use ElementBuilder and Element interface instead.
317
318 $writer->WriteString("T* T* "); // Skip 2 lines
319 $writer->WriteString("(Direct output to PDF page content stream:) Tj T* ");
320 $writer->WriteString("(AWAY) Tj T* ");
321 $writer->WriteString("[(A)140(W)140(A)115(Y again)] TJ ");
322
323 // Finish the block of text
324 $writer->WriteElement($builder->CreateTextEnd());
325
326 $writer->End(); // save changes to the current page
327 $doc->PagePushBack($page);
328
329 // Start a new page ------------------------------------
330
331 // Image Masks
332 //
333 // In the opaque imaging model, images mark all areas they occupy on the page as
334 // if with opaque paint. All portions of the image, whether black, white, gray,
335 // or color, completely obscure any marks that may previously have existed in the
336 // same place on the page.
337 // In the graphic arts industry and page layout applications, however, it is common
338 // to crop or 'mask out' the background of an image and then place the masked image
339 // on a different background, allowing the existing background to show through the
340 // masked areas. This sample illustrates how to use image masks.
341
342 $page = $doc->PageCreate();
343 $writer->Begin($page); // begin writing to the page
344
345 // Create the Image Mask
346 $imgf = new MappedFile($input_path."imagemask.dat");
347 $mask_read = new FilterReader($imgf);
348
349 $device_gray = ColorSpace::CreateDeviceGray();
350 $mask = Image::Create($doc->GetSDFDoc(), $mask_read, 64, 64, 1, $device_gray, Image::e_ascii_hex);
351
352 $mask->GetSDFObj()->PutBool("ImageMask", true);
353
354 $element = $builder->CreateRect(0, 0, 612, 794);
355 $element->SetPathStroke(false);
356 $element->SetPathFill(true);
357 $element->GetGState()->SetFillColorSpace($device_gray);
358 $element->GetGState()->SetFillColor(new ColorPt(0.8));
359 $writer->WritePlacedElement($element);
360
361 $element = $builder->CreateImage($mask, new Matrix2D(200.0, 0.0, 0.0, -200.0, 40.0, 680.0));
362 $element->GetGState()->SetFillColor(new ColorPt(0.1));
363 $writer->WritePlacedElement($element);
364
365 $element->GetGState()->SetFillColorSpace(ColorSpace::CreateDeviceRGB());
366 $element->GetGState()->SetFillColor(new ColorPt(1.0, 0.0, 0.0));
367 $element = $builder->CreateImage($mask, new Matrix2D(200.0, 0.0, 0.0, -200.0, 320.0, 680.0));
368 $writer->WritePlacedElement($element);
369
370 $element->GetGState()->SetFillColor(new ColorPt(0.0, 1.0, 0.0));
371 $element = $builder->CreateImage($mask, new Matrix2D(200.0, 0.0, 0.0, -200.0, 40.0, 380.0));
372 $writer->WritePlacedElement($element);
373
374 // This sample illustrates Explicit Masking.
375 $img = Image::Create($doc->GetSDFDoc(), $input_path."peppers.jpg");
376
377 // mask is the explicit mask for the primary (base) image
378 $img->SetMask($mask);
379
380 $element = $builder->CreateImage($img, new Matrix2D(200.0, 0.0, 0.0, -200.0, 320.0, 380.0));
381 $writer->WritePlacedElement($element);
382
383 $writer->End(); // save changes to the current page
384 $doc->PagePushBack($page);
385
386 // Transparency sample ----------------------------------
387
388 // Start a new page -------------------------------------
389 $page = $doc->PageCreate();
390 $writer->Begin($page); // begin writing to this page
391 $builder->Reset(); // Reset the GState to default
392
393 // Write some transparent text at the bottom of the page.
394 $element = $builder->CreateTextBegin(Font::Create($doc->GetSDFDoc(), Font::e_times_roman), 100.0);
395
396 // Set the text knockout attribute. Text knockout must be set outside of
397 // the text group.
398 $gstate = $element->GetGState();
399 $gstate->SetTextKnockout(false);
400 $gstate->SetBlendMode(GState::e_bl_difference);
401 $writer->WriteElement($element);
402
403 $element = $builder->CreateTextRun("Transparency");
404 $element->SetTextMatrix(1.0, 0.0, 0.0, 1.0, 30.0, 30.0);
405 $gstate = $element->GetGState();
406 $gstate->SetFillColorSpace(ColorSpace::CreateDeviceCMYK());
407 $gstate->SetFillColor(new ColorPt(1.0, 0.0, 0.0, 0.0));
408
409 $gstate->SetFillOpacity(0.5);
410 $writer->WriteElement($element);
411
412 // Write the same text on top the old; shifted by 3 points
413 $element->SetTextMatrix(1.0, 0.0, 0.0, 1.0, 33.0, 33.0);
414 $gstate->SetFillColor(new ColorPt(0.0, 1.0, 0.0, 0.0));
415 $gstate->SetFillOpacity(0.5);
416
417 $writer->WriteElement($element);
418 $writer->WriteElement($builder->CreateTextEnd());
419
420 // Draw three overlapping transparent circles.
421 $builder->PathBegin(); // start constructing the path
422 $builder->MoveTo(459.223, 505.646);
423 $builder->CurveTo(459.223, 415.841, 389.85, 343.04, 304.273, 343.04);
424 $builder->CurveTo(218.697, 343.04, 149.324, 415.841, 149.324, 505.646);
425 $builder->CurveTo(149.324, 595.45, 218.697, 668.25, 304.273, 668.25);
426 $builder->CurveTo(389.85, 668.25, 459.223, 595.45, 459.223, 505.646);
427 $element = $builder->PathEnd();
428 $element->SetPathFill(true);
429
430 $gstate = $element->GetGState();
431 $gstate->SetFillColorSpace(ColorSpace::CreateDeviceRGB());
432 $gstate->SetFillColor(new ColorPt(0.0, 0.0, 1.0));
433
434 $gstate->SetBlendMode(GState::e_bl_normal);
435 $gstate->SetFillOpacity(0.5);
436 $writer->WriteElement($element);
437
438 // Translate relative to the Blue Circle
439 $gstate->SetTransform(1.0, 0.0, 0.0, 1.0, 113.0, -185.0);
440 $gstate->SetFillColor(new ColorPt(0.0, 1.0, 0.0)); // Green Circle
441 $gstate->SetFillOpacity(0.5);
442 $writer->WriteElement($element);
443
444 // Translate relative to the Green Circle
445 $gstate->SetTransform(1.0, 0.0, 0.0, 1.0, -220.0, 0.0);
446 $gstate->SetFillColor(new ColorPt(1.0, 0.0, 0.0)); // Red Circle
447 $gstate->SetFillOpacity(0.5);
448 $writer->WriteElement($element);
449
450 $writer->End(); // save changes to the current page
451 $doc->PagePushBack($page);
452
453 // End page ------------------------------------
454
455 $doc->Save($output_path."element_builder.pdf", SDFDoc::e_remove_unused);
456 PDFNet::Terminate();
457 echo "Done. Result saved in element_builder.pdf...\n";
458?>

Did you find this helpful?

Trial setup questions?

Ask experts on Discord

Need other help?

Contact Support

Pricing or product questions?

Contact Sales