UNPKG

74.3 kBtext/x-cView Raw
1/*
2 Source File : PDFWriterDriver.cpp
3
4
5 Copyright 2013 Gal Kahana HummusJS
6
7 Licensed under the Apache License, Version 2.0 (the "License");
8 you may not use this file except in compliance with the License.
9 You may obtain a copy of the License at
10
11 http://www.apache.org/licenses/LICENSE-2.0
12
13 Unless required by applicable law or agreed to in writing, software
14 distributed under the License is distributed on an "AS IS" BASIS,
15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 See the License for the specific language governing permissions and
17 limitations under the License.
18
19 */
20#include "PDFWriterDriver.h"
21#include "PDFPageDriver.h"
22#include "ByteReaderWithPositionDriver.h"
23#include "PageContentContextDriver.h"
24#include "FormXObjectDriver.h"
25#include "UsedFontDriver.h"
26#include "ImageXObjectDriver.h"
27#include "ObjectsContextDriver.h"
28#include "DocumentContextExtenderAdapter.h"
29#include "DocumentCopyingContextDriver.h"
30#include "InputFile.h"
31#include "PDFParser.h"
32#include "PDFDateDriver.h"
33#include "PDFTextStringDriver.h"
34#include "PDFParser.h"
35#include "PDFPageInput.h"
36#include "PDFRectangle.h"
37#include "TIFFImageHandler.h"
38#include "IOBasicTypes.h"
39#include "PDFDocumentCopyingContext.h"
40#include "PDFFormXObject.h"
41#include "PDFReaderDriver.h"
42#include "InputFileDriver.h"
43#include "OutputFileDriver.h"
44#include "DocumentContextDriver.h"
45#include "ObjectByteReaderWithPosition.h"
46#include "DictionaryContextDriver.h"
47#include "ResourcesDictionaryDriver.h"
48#include "ConstructorsHolder.h"
49
50using namespace v8;
51
52PDFWriterDriver::PDFWriterDriver()
53{
54 mWriteStreamProxy = NULL;
55 mReadStreamProxy = NULL;
56 mStartedWithStream = false;
57 mIsCatalogUpdateRequired = false;
58}
59
60PDFWriterDriver::~PDFWriterDriver()
61{
62 delete mWriteStreamProxy;
63 delete mReadStreamProxy;
64}
65
66DEF_SUBORDINATE_INIT(PDFWriterDriver::Init)
67{
68 CREATE_ISOLATE_CONTEXT;
69
70 Local<FunctionTemplate> t = NEW_FUNCTION_TEMPLATE_EXTERNAL(New);
71
72 t->SetClassName(NEW_STRING("PDFWriter"));
73 t->InstanceTemplate()->SetInternalFieldCount(1);
74
75 SET_PROTOTYPE_METHOD(t, "end", End);
76 SET_PROTOTYPE_METHOD(t, "createPage", CreatePage);
77 SET_PROTOTYPE_METHOD(t, "writePage", WritePage);
78 SET_PROTOTYPE_METHOD(t, "writePageAndReturnID", WritePageAndReturnID);
79 SET_PROTOTYPE_METHOD(t, "startPageContentContext", StartPageContentContext);
80 SET_PROTOTYPE_METHOD(t, "pausePageContentContext", PausePageContentContext);
81 SET_PROTOTYPE_METHOD(t, "createFormXObject", CreateFormXObject);
82 SET_PROTOTYPE_METHOD(t, "endFormXObject", EndFormXObject);
83 SET_PROTOTYPE_METHOD(t, "createFormXObjectFromJPG", CreateformXObjectFromJPG);
84 SET_PROTOTYPE_METHOD(t, "getFontForFile", GetFontForFile);
85 SET_PROTOTYPE_METHOD(t, "attachURLLinktoCurrentPage", AttachURLLinktoCurrentPage);
86 SET_PROTOTYPE_METHOD(t, "shutdown", Shutdown);
87 SET_PROTOTYPE_METHOD(t, "createFormXObjectFromTIFF", CreateFormXObjectFromTIFF);
88 SET_PROTOTYPE_METHOD(t, "createImageXObjectFromJPG", CreateImageXObjectFromJPG);
89 SET_PROTOTYPE_METHOD(t, "createFormXObjectFromPNG", CreateFormXObjectFromPNG);
90 SET_PROTOTYPE_METHOD(t, "retrieveJPGImageInformation", RetrieveJPGImageInformation);
91 SET_PROTOTYPE_METHOD(t, "getObjectsContext", GetObjectsContext);
92 SET_PROTOTYPE_METHOD(t, "getDocumentContext", GetDocumentContext);
93 SET_PROTOTYPE_METHOD(t, "appendPDFPagesFromPDF", AppendPDFPagesFromPDF);
94 SET_PROTOTYPE_METHOD(t, "mergePDFPagesToPage", MergePDFPagesToPage);
95 SET_PROTOTYPE_METHOD(t, "createPDFCopyingContext", CreatePDFCopyingContext);
96 SET_PROTOTYPE_METHOD(t, "createFormXObjectsFromPDF", CreateFormXObjectsFromPDF);
97 SET_PROTOTYPE_METHOD(t, "createPDFCopyingContextForModifiedFile", CreatePDFCopyingContextForModifiedFile);
98 SET_PROTOTYPE_METHOD(t, "createPDFTextString", CreatePDFTextString);
99 SET_PROTOTYPE_METHOD(t, "createPDFDate", CreatePDFDate);
100 SET_PROTOTYPE_METHOD(t, "getImageDimensions", GetImageDimensions);
101 SET_PROTOTYPE_METHOD(t, "getImagePagesCount", GetImagePagesCount);
102 SET_PROTOTYPE_METHOD(t, "getImageType", GetImageType);
103 SET_PROTOTYPE_METHOD(t, "getModifiedFileParser", GetModifiedFileParser);
104 SET_PROTOTYPE_METHOD(t, "getModifiedInputFile", GetModifiedInputFile);
105 SET_PROTOTYPE_METHOD(t, "getOutputFile", GetOutputFile);
106 SET_PROTOTYPE_METHOD(t, "registerAnnotationReferenceForNextPageWrite", RegisterAnnotationReferenceForNextPageWrite);
107 SET_PROTOTYPE_METHOD(t, "requireCatalogUpdate", RequireCatalogUpdate);
108 SET_CONSTRUCTOR_EXPORT("PDFWriter", t);
109
110 // save in factory
111 EXPOSE_EXTERNAL_FOR_INIT(ConstructorsHolder, holder)
112 SET_CONSTRUCTOR(holder->PDFWriter_constructor, t);
113}
114
115METHOD_RETURN_TYPE PDFWriterDriver::New(const ARGS_TYPE& args)
116{
117 CREATE_ISOLATE_CONTEXT;
118 CREATE_ESCAPABLE_SCOPE;
119 EXPOSE_EXTERNAL_ARGS(ConstructorsHolder, externalHolder)
120
121 PDFWriterDriver* pdfWriter = new PDFWriterDriver();
122
123 pdfWriter->holder = externalHolder;
124 pdfWriter->Wrap(args.This());
125
126 SET_FUNCTION_RETURN_VALUE(args.This())
127}
128
129METHOD_RETURN_TYPE PDFWriterDriver::End(const ARGS_TYPE& args)
130{
131 CREATE_ISOLATE_CONTEXT;
132 CREATE_ESCAPABLE_SCOPE;
133
134 PDFWriterDriver* pdfWriter = ObjectWrap::Unwrap<PDFWriterDriver>(args.This());
135
136 EStatusCode status;
137
138 if(pdfWriter->mStartedWithStream)
139 status = pdfWriter->mPDFWriter.EndPDFForStream();
140 else
141 status = pdfWriter->mPDFWriter.EndPDF();
142
143 // now remove event listener
144 pdfWriter->mPDFWriter.GetDocumentContext().AddDocumentContextExtender(pdfWriter);
145
146
147 if(status != PDFHummus::eSuccess)
148 {
149 THROW_EXCEPTION("Unable to end PDF");
150 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
151 }
152
153 if(pdfWriter->mWriteStreamProxy)
154 {
155 delete pdfWriter->mWriteStreamProxy;
156 pdfWriter->mWriteStreamProxy = NULL;
157 }
158
159 if(pdfWriter->mReadStreamProxy)
160 {
161 delete pdfWriter->mReadStreamProxy;
162 pdfWriter->mReadStreamProxy = NULL;
163 }
164
165 SET_FUNCTION_RETURN_VALUE(args.This())
166}
167
168METHOD_RETURN_TYPE PDFWriterDriver::CreatePage(const ARGS_TYPE& args)
169{
170 CREATE_ISOLATE_CONTEXT;
171 CREATE_ESCAPABLE_SCOPE;
172 PDFWriterDriver* pdfWriter = ObjectWrap::Unwrap<PDFWriterDriver>(args.This());
173
174 SET_FUNCTION_RETURN_VALUE(pdfWriter->holder->GetNewPDFPage(args))
175
176}
177
178METHOD_RETURN_TYPE PDFWriterDriver::WritePage(const ARGS_TYPE& args)
179{
180 CREATE_ISOLATE_CONTEXT;
181 CREATE_ESCAPABLE_SCOPE;
182
183 WritePageAndReturnID(args);
184
185 SET_FUNCTION_RETURN_VALUE(args.This())
186
187}
188
189METHOD_RETURN_TYPE PDFWriterDriver::WritePageAndReturnID(const ARGS_TYPE& args)
190{
191 CREATE_ISOLATE_CONTEXT;
192 CREATE_ESCAPABLE_SCOPE;
193
194 PDFWriterDriver* pdfWriter = ObjectWrap::Unwrap<PDFWriterDriver>(args.This());
195
196 if (args.Length() != 1 || !pdfWriter->holder->IsPDFPageInstance(args[0])) {
197 THROW_EXCEPTION("Wrong arguments, provide a page as the single parameter");
198 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
199 }
200
201 PDFPageDriver* pageDriver = ObjectWrap::Unwrap<PDFPageDriver>(args[0]->TO_OBJECT());
202 if(!pageDriver)
203 {
204 THROW_EXCEPTION("Wrong arguments, provide a page as the single parameter");
205 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
206 }
207
208 if(pageDriver->ContentContext &&
209 (pdfWriter->mPDFWriter.EndPageContentContext(pageDriver->ContentContext) != PDFHummus::eSuccess))
210 {
211 THROW_EXCEPTION("Unable to finalize page context");
212 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
213 }
214 pageDriver->ContentContext = NULL;
215
216 EStatusCodeAndObjectIDType result = pdfWriter->mPDFWriter.WritePageAndReturnPageID(pageDriver->GetPage());
217
218 if(result.first != PDFHummus::eSuccess)
219 {
220 THROW_EXCEPTION("Unable to write page");
221 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
222 }
223
224 SET_FUNCTION_RETURN_VALUE(NEW_NUMBER(result.second))
225
226}
227
228METHOD_RETURN_TYPE PDFWriterDriver::StartPageContentContext(const ARGS_TYPE& args)
229{
230 CREATE_ISOLATE_CONTEXT;
231 CREATE_ESCAPABLE_SCOPE;
232
233 PDFWriterDriver* pdfWriter = ObjectWrap::Unwrap<PDFWriterDriver>(args.This());
234
235 if (args.Length() != 1 || !pdfWriter->holder->IsPDFPageInstance(args[0])) {
236 THROW_EXCEPTION("Wrong arguments, provide a page as the single parameter");
237 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
238 }
239
240 PDFPageDriver* pageDriver = ObjectWrap::Unwrap<PDFPageDriver>(args[0]->TO_OBJECT());
241 if(!pageDriver)
242 {
243 THROW_EXCEPTION("Wrong arguments, provide a page as the single parameter");
244 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
245 }
246
247
248 Local<Value> newInstance = pdfWriter->holder->GetNewPageContentContext(args);
249 PageContentContextDriver* contentContextDriver = ObjectWrap::Unwrap<PageContentContextDriver>(newInstance->TO_OBJECT());
250 contentContextDriver->ContentContext = pdfWriter->mPDFWriter.StartPageContentContext(pageDriver->GetPage());
251 contentContextDriver->SetResourcesDictionary(&(pageDriver->GetPage()->GetResourcesDictionary()));
252
253 // save it also at page driver, so we can end the context when the page is written
254 pageDriver->ContentContext = contentContextDriver->ContentContext;
255
256 SET_FUNCTION_RETURN_VALUE(newInstance)
257}
258
259METHOD_RETURN_TYPE PDFWriterDriver::PausePageContentContext(const ARGS_TYPE& args)
260{
261 CREATE_ISOLATE_CONTEXT;
262 CREATE_ESCAPABLE_SCOPE;
263
264 PDFWriterDriver* pdfWriter = ObjectWrap::Unwrap<PDFWriterDriver>(args.This());
265
266 if (args.Length() != 1 || !pdfWriter->holder->IsPageContentContextInstance(args[0])) {
267 THROW_EXCEPTION("Wrong arguments, provide a page context as the single parameter");
268 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
269 }
270
271 PageContentContextDriver* pageContextDriver = ObjectWrap::Unwrap<PageContentContextDriver>(args[0]->TO_OBJECT());
272 if(!pageContextDriver)
273 {
274 THROW_EXCEPTION("Wrong arguments, provide a page context as the single parameter");
275 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
276 }
277
278 if(!pageContextDriver->ContentContext)
279 {
280 THROW_EXCEPTION("paused context not initialized, please create one using pdfWriter.startPageContentContext");
281 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
282 }
283
284 pdfWriter->mPDFWriter.PausePageContentContext(pageContextDriver->ContentContext);
285
286 SET_FUNCTION_RETURN_VALUE(args.This())
287}
288
289METHOD_RETURN_TYPE PDFWriterDriver::CreateFormXObject(const ARGS_TYPE& args)
290{
291 CREATE_ISOLATE_CONTEXT;
292 CREATE_ESCAPABLE_SCOPE;
293
294 if((args.Length() != 4 && args.Length() != 5) || !args[0]->IsNumber() || !args[1]->IsNumber() || !args[2]->IsNumber() || !args[3]->IsNumber()
295 || (args.Length() == 5 && !args[4]->IsNumber()))
296 {
297 THROW_EXCEPTION("wrong arguments, pass 4 coordinates of the form rectangle and an optional 5th agument which is the forward reference ID");
298 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
299 }
300
301 PDFWriterDriver* pdfWriter = ObjectWrap::Unwrap<PDFWriterDriver>(args.This());
302 Local<Value> newInstance = pdfWriter->holder->GetNewFormXObject(args);
303 FormXObjectDriver* formXObjectDriver = ObjectWrap::Unwrap<FormXObjectDriver>(newInstance->TO_OBJECT());
304 formXObjectDriver->FormXObject =
305 args.Length() == 5 ?
306 pdfWriter->mPDFWriter.StartFormXObject(
307 PDFRectangle(TO_NUMBER(args[0])->Value(),
308 TO_NUMBER(args[1])->Value(),
309 TO_NUMBER(args[2])->Value(),
310 TO_NUMBER(args[3])->Value()),
311 (ObjectIDType)TO_NUMBER(args[4])->Value()):
312 pdfWriter->mPDFWriter.StartFormXObject(
313 PDFRectangle(TO_NUMBER(args[0])->Value(),
314 TO_NUMBER(args[1])->Value(),
315 TO_NUMBER(args[2])->Value(),
316 TO_NUMBER(args[3])->Value()));
317 SET_FUNCTION_RETURN_VALUE(newInstance)
318}
319
320METHOD_RETURN_TYPE PDFWriterDriver::EndFormXObject(const ARGS_TYPE& args)
321{
322 CREATE_ISOLATE_CONTEXT;
323 CREATE_ESCAPABLE_SCOPE;
324
325 PDFWriterDriver* pdfWriter = ObjectWrap::Unwrap<PDFWriterDriver>(args.This());
326
327 if (args.Length() != 1 || !pdfWriter->holder->IsFormXObjectInstance(args[0])) {
328 THROW_EXCEPTION("Wrong arguments, provide a form as the single parameter");
329 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
330 }
331
332 FormXObjectDriver* formContextDriver = ObjectWrap::Unwrap<FormXObjectDriver>(args[0]->TO_OBJECT());
333 if(!formContextDriver)
334 {
335 THROW_EXCEPTION("Wrong arguments, provide a form as the single parameter");
336 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
337 }
338
339 pdfWriter->mPDFWriter.EndFormXObject(formContextDriver->FormXObject);
340
341 SET_FUNCTION_RETURN_VALUE(args.This())
342
343}
344
345
346
347METHOD_RETURN_TYPE PDFWriterDriver::CreateformXObjectFromJPG(const ARGS_TYPE& args)
348{
349 CREATE_ISOLATE_CONTEXT;
350 CREATE_ESCAPABLE_SCOPE;
351
352 if((args.Length() != 1 && args.Length() != 2 ) || (!args[0]->IsString() && !args[0]->IsObject()) || (args.Length() == 2 && !args[1]->IsNumber()))
353 {
354 THROW_EXCEPTION("wrong arguments, pass 1 argument that is the path to the image or an image stream. Optionally pass an object ID for a forward reference image");
355 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
356 }
357
358 PDFWriterDriver* pdfWriter = ObjectWrap::Unwrap<PDFWriterDriver>(args.This());
359
360 PDFFormXObject* formXObject;
361
362 if(args[0]->IsObject())
363 {
364 ObjectByteReaderWithPosition proxy(args[0]->TO_OBJECT());
365
366 formXObject =
367 args.Length() == 2 ?
368 pdfWriter->mPDFWriter.CreateFormXObjectFromJPGStream(&proxy,(ObjectIDType)TO_INT32(args[1])->Value()):
369 pdfWriter->mPDFWriter.CreateFormXObjectFromJPGStream(&proxy);
370
371 }
372 else
373 {
374 formXObject =
375 args.Length() == 2 ?
376 pdfWriter->mPDFWriter.CreateFormXObjectFromJPGFile(*UTF_8_VALUE(args[0]->TO_STRING()),(ObjectIDType)TO_INT32(args[1])->Value()):
377 pdfWriter->mPDFWriter.CreateFormXObjectFromJPGFile(*UTF_8_VALUE(args[0]->TO_STRING()));
378 }
379 if(!formXObject)
380 {
381 THROW_EXCEPTION("unable to create form xobject. verify that the target is an existing jpg file/stream");
382 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
383 }
384
385 Local<Value> newInstance = pdfWriter->holder->GetNewFormXObject(args);
386 ObjectWrap::Unwrap<FormXObjectDriver>(newInstance->TO_OBJECT())->FormXObject = formXObject;
387 SET_FUNCTION_RETURN_VALUE(newInstance)
388}
389
390METHOD_RETURN_TYPE PDFWriterDriver::RetrieveJPGImageInformation(const ARGS_TYPE& args)
391{
392 CREATE_ISOLATE_CONTEXT;
393 CREATE_ESCAPABLE_SCOPE;
394
395 if(args.Length() != 1 ||
396 !args[0]->IsString())
397 {
398 THROW_EXCEPTION("wrong arguments, pass 1 argument that is the path to the image");
399 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
400 }
401
402 PDFWriterDriver* pdfWriter = ObjectWrap::Unwrap<PDFWriterDriver>(args.This());
403 BoolAndJPEGImageInformation info = pdfWriter->mPDFWriter.GetDocumentContext().GetJPEGImageHandler().RetrieveImageInformation(*UTF_8_VALUE(args[0]->TO_STRING()));
404
405 if(!info.first)
406 {
407 THROW_EXCEPTION("unable to retrieve image information");
408 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
409 }
410
411 Local<Object> result = NEW_OBJECT;
412
413 result->Set(GET_CURRENT_CONTEXT, NEW_SYMBOL("samplesWidth"), NEW_INTEGER((int)info.second.SamplesWidth));
414 result->Set(GET_CURRENT_CONTEXT, NEW_SYMBOL("samplesHeight"), NEW_INTEGER((int)info.second.SamplesHeight));
415 result->Set(GET_CURRENT_CONTEXT, NEW_SYMBOL("colorComponentsCount"), NEW_INTEGER(info.second.ColorComponentsCount));
416 result->Set(GET_CURRENT_CONTEXT, NEW_SYMBOL("JFIFInformationExists"), NEW_BOOLEAN(info.second.JFIFInformationExists));
417 if(info.second.JFIFInformationExists)
418 {
419 result->Set(GET_CURRENT_CONTEXT, NEW_SYMBOL("JFIFUnit"), NEW_INTEGER(info.second.JFIFUnit));
420 result->Set(GET_CURRENT_CONTEXT, NEW_SYMBOL("JFIFXDensity"), NEW_NUMBER(info.second.JFIFXDensity));
421 result->Set(GET_CURRENT_CONTEXT, NEW_SYMBOL("JFIFYDensity"), NEW_NUMBER(info.second.JFIFYDensity));
422 }
423 result->Set(GET_CURRENT_CONTEXT, NEW_SYMBOL("ExifInformationExists"), NEW_BOOLEAN(info.second.ExifInformationExists));
424 if(info.second.ExifInformationExists)
425 {
426 result->Set(GET_CURRENT_CONTEXT, NEW_SYMBOL("ExifUnit"), NEW_INTEGER(info.second.ExifUnit));
427 result->Set(GET_CURRENT_CONTEXT, NEW_SYMBOL("ExifXDensity"), NEW_NUMBER(info.second.ExifXDensity));
428 result->Set(GET_CURRENT_CONTEXT, NEW_SYMBOL("ExifYDensity"), NEW_NUMBER(info.second.ExifYDensity));
429 }
430 result->Set(GET_CURRENT_CONTEXT, NEW_SYMBOL("PhotoshopInformationExists"), NEW_BOOLEAN(info.second.PhotoshopInformationExists));
431 if(info.second.PhotoshopInformationExists)
432 {
433 result->Set(GET_CURRENT_CONTEXT, NEW_SYMBOL("PhotoshopXDensity"), NEW_NUMBER(info.second.PhotoshopXDensity));
434 result->Set(GET_CURRENT_CONTEXT, NEW_SYMBOL("PhotoshopYDensity"), NEW_NUMBER(info.second.PhotoshopYDensity));
435 }
436
437 SET_FUNCTION_RETURN_VALUE(result)
438}
439
440METHOD_RETURN_TYPE PDFWriterDriver::CreateFormXObjectFromPNG(const ARGS_TYPE& args)
441{
442 CREATE_ISOLATE_CONTEXT;
443 CREATE_ESCAPABLE_SCOPE;
444
445 if((args.Length() != 1 && args.Length() != 2 ) || (!args[0]->IsString() && !args[0]->IsObject()) || (args.Length() == 2 && !args[1]->IsNumber()))
446 {
447 THROW_EXCEPTION("wrong arguments, pass 1 argument that is the path to the image or an image stream. Optionally pass an object ID for a forward reference image");
448 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
449 }
450
451 PDFWriterDriver* pdfWriter = ObjectWrap::Unwrap<PDFWriterDriver>(args.This());
452
453 PDFFormXObject* formXObject;
454
455 if(args[0]->IsObject())
456 {
457 ObjectByteReaderWithPosition proxy(args[0]->TO_OBJECT());
458
459 formXObject =
460 args.Length() == 2 ?
461 pdfWriter->mPDFWriter.CreateFormXObjectFromPNGStream(&proxy,(ObjectIDType)TO_INT32(args[1])->Value()):
462 pdfWriter->mPDFWriter.CreateFormXObjectFromPNGStream(&proxy);
463
464 }
465 else
466 {
467 formXObject =
468 args.Length() == 2 ?
469 pdfWriter->mPDFWriter.CreateFormXObjectFromPNGFile(*UTF_8_VALUE(args[0]->TO_STRING()),(ObjectIDType)TO_INT32(args[1])->Value()):
470 pdfWriter->mPDFWriter.CreateFormXObjectFromPNGFile(*UTF_8_VALUE(args[0]->TO_STRING()));
471 }
472 if(!formXObject)
473 {
474 THROW_EXCEPTION("unable to create form xobject. verify that the target is an existing png file/stream");
475 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
476 }
477
478 Local<Value> newInstance = pdfWriter->holder->GetNewFormXObject(args);
479 ObjectWrap::Unwrap<FormXObjectDriver>(newInstance->TO_OBJECT())->FormXObject = formXObject;
480 SET_FUNCTION_RETURN_VALUE(newInstance)
481}
482
483METHOD_RETURN_TYPE PDFWriterDriver::GetFontForFile(const ARGS_TYPE& args)
484{
485 CREATE_ISOLATE_CONTEXT;
486 CREATE_ESCAPABLE_SCOPE;
487
488 if(args.Length() < 1 ||
489 !args[0]->IsString() ||
490 (args.Length() == 2 && !args[1]->IsString() && !args[1]->IsNumber()) ||
491 (args.Length() == 3 && !args[1]->IsString() && !args[2]->IsNumber()))
492 {
493 THROW_EXCEPTION("wrong arguments, pass 1 argument that is the path to the font file, with option to a 2nd parameter for another path in case of type 1 font. another optional argument may follow with font index in case of font packages (TTC, DFont)");
494 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
495 }
496
497 PDFWriterDriver* pdfWriter = ObjectWrap::Unwrap<PDFWriterDriver>(args.This());
498
499 PDFUsedFont* usedFont;
500
501 if(args.Length() == 3)
502 {
503 usedFont = pdfWriter->mPDFWriter.GetFontForFile(*UTF_8_VALUE(args[0]->TO_STRING()),
504 *UTF_8_VALUE(args[1]->TO_STRING()),
505 TO_UINT32(args[0])->Value());
506 }
507 else if(args.Length() == 2)
508 {
509 if(args[1]->IsString())
510 usedFont = pdfWriter->mPDFWriter.GetFontForFile(*UTF_8_VALUE(args[0]->TO_STRING()),
511 *UTF_8_VALUE(args[1]->TO_STRING()));
512 else
513 usedFont = pdfWriter->mPDFWriter.GetFontForFile(*UTF_8_VALUE(args[0]->TO_STRING()),
514 TO_UINT32(args[1])->Value());
515 }
516 else // length is 1
517 {
518 usedFont = pdfWriter->mPDFWriter.GetFontForFile(*UTF_8_VALUE(args[0]->TO_STRING()));
519 }
520
521 if(!usedFont)
522 {
523 THROW_EXCEPTION("unable to create font object. verify that the target is an existing and supported font type (ttf,otf,type1,dfont,ttc)");
524 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
525 }
526
527 Local<Value> newInstance = pdfWriter->holder->GetNewUsedFont(args);
528 ObjectWrap::Unwrap<UsedFontDriver>(newInstance->TO_OBJECT())->UsedFont = usedFont;
529 SET_FUNCTION_RETURN_VALUE(newInstance)
530}
531
532METHOD_RETURN_TYPE PDFWriterDriver::AttachURLLinktoCurrentPage(const ARGS_TYPE& args)
533{
534 CREATE_ISOLATE_CONTEXT;
535 CREATE_ESCAPABLE_SCOPE;
536
537 if(args.Length() != 5 ||
538 !args[0]->IsString() ||
539 !args[1]->IsNumber() ||
540 !args[2]->IsNumber() ||
541 !args[3]->IsNumber() ||
542 !args[4]->IsNumber())
543 {
544 THROW_EXCEPTION("wrong arguments, pass a url, and 4 numbers (left,bottom,right,top) for the rectangle valid for clicking");
545 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
546 }
547
548 PDFWriterDriver* pdfWriter = ObjectWrap::Unwrap<PDFWriterDriver>(args.This());
549
550 EStatusCode status = pdfWriter->mPDFWriter.AttachURLLinktoCurrentPage(*UTF_8_VALUE(args[0]->TO_STRING()),
551 PDFRectangle(TO_NUMBER(args[1])->Value(),
552 TO_NUMBER(args[2])->Value(),
553 TO_NUMBER(args[3])->Value(),
554 TO_NUMBER(args[4])->Value()));
555 if(status != eSuccess)
556 {
557 THROW_EXCEPTION("unable to attach link to current page. will happen if the input URL may not be encoded to ascii7");
558 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
559 }
560
561 SET_FUNCTION_RETURN_VALUE(args.This())
562}
563
564
565METHOD_RETURN_TYPE PDFWriterDriver::Shutdown(const ARGS_TYPE& args)
566{
567 CREATE_ISOLATE_CONTEXT;
568 CREATE_ESCAPABLE_SCOPE;
569
570 if(args.Length() != 1 ||
571 !args[0]->IsString())
572 {
573 THROW_EXCEPTION("wrong arguments, pass a path to save the state file to");
574 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
575 }
576
577 PDFWriterDriver* pdfWriter = ObjectWrap::Unwrap<PDFWriterDriver>(args.This());
578
579 EStatusCode status = pdfWriter->mPDFWriter.Shutdown(*UTF_8_VALUE(args[0]->TO_STRING()));
580 if(status != eSuccess)
581 {
582 THROW_EXCEPTION("unable to save state file. verify that path is not occupied");
583 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
584 }
585
586 SET_FUNCTION_RETURN_VALUE(args.This())
587}
588
589PDFHummus::EStatusCode PDFWriterDriver::StartPDF(const std::string& inOutputFilePath,
590 EPDFVersion inPDFVersion,
591 const LogConfiguration& inLogConfiguration,
592 const PDFCreationSettings& inCreationSettings)
593{
594 mStartedWithStream = false;
595
596 return setupListenerIfOK(mPDFWriter.StartPDF(inOutputFilePath,inPDFVersion,inLogConfiguration,inCreationSettings));
597}
598
599PDFHummus::EStatusCode PDFWriterDriver::StartPDF(Local<Object> inWriteStream,
600 EPDFVersion inPDFVersion,
601 const LogConfiguration& inLogConfiguration,
602 const PDFCreationSettings& inCreationSettings)
603{
604
605 mWriteStreamProxy = new ObjectByteWriterWithPosition(inWriteStream);
606 mStartedWithStream = true;
607 return setupListenerIfOK(mPDFWriter.StartPDFForStream(mWriteStreamProxy,inPDFVersion,inLogConfiguration,inCreationSettings));
608}
609
610
611
612PDFHummus::EStatusCode PDFWriterDriver::ContinuePDF(const std::string& inOutputFilePath,
613 const std::string& inStateFilePath,
614 const std::string& inOptionalOtherOutputFile,
615 const LogConfiguration& inLogConfiguration)
616{
617 mStartedWithStream = false;
618 return setupListenerIfOK(mPDFWriter.ContinuePDF(inOutputFilePath,inStateFilePath,inOptionalOtherOutputFile,inLogConfiguration));
619}
620
621PDFHummus::EStatusCode PDFWriterDriver::ContinuePDF(Local<Object> inOutputStream,
622 const std::string& inStateFilePath,
623 Local<Object> inModifiedSourceStream,
624 const LogConfiguration& inLogConfiguration)
625{
626 mStartedWithStream = true;
627 mWriteStreamProxy = new ObjectByteWriterWithPosition(inOutputStream);
628 if(!inModifiedSourceStream.IsEmpty())
629 mReadStreamProxy = new ObjectByteReaderWithPosition(inModifiedSourceStream);
630
631
632 return setupListenerIfOK(mPDFWriter.ContinuePDFForStream(mWriteStreamProxy,inStateFilePath,inModifiedSourceStream.IsEmpty() ? NULL : mReadStreamProxy,inLogConfiguration));
633}
634
635
636PDFHummus::EStatusCode PDFWriterDriver::ModifyPDF(const std::string& inSourceFile,
637 EPDFVersion inPDFVersion,
638 const std::string& inOptionalOtherOutputFile,
639 const LogConfiguration& inLogConfiguration,
640 const PDFCreationSettings& inCreationSettings)
641{
642 // two phase, cause i don't want to bother the users with the level BS.
643 // first, parse the source file, get the level. then modify with this level
644
645 mStartedWithStream = false;
646 return setupListenerIfOK(mPDFWriter.ModifyPDF(inSourceFile,inPDFVersion,inOptionalOtherOutputFile,inLogConfiguration,inCreationSettings));
647}
648
649PDFHummus::EStatusCode PDFWriterDriver::ModifyPDF(Local<Object> inSourceStream,
650 Local<Object> inDestinationStream,
651 EPDFVersion inPDFVersion,
652 const LogConfiguration& inLogConfiguration,
653 const PDFCreationSettings& inCreationSettings)
654{
655 mStartedWithStream = true;
656
657 mWriteStreamProxy = new ObjectByteWriterWithPosition(inDestinationStream);
658 mReadStreamProxy = new ObjectByteReaderWithPosition(inSourceStream);
659
660 // use minimal leve ePDFVersion10 to use the modified file level (cause i don't care
661 return setupListenerIfOK(mPDFWriter.ModifyPDFForStream(mReadStreamProxy,mWriteStreamProxy,false,inPDFVersion,inLogConfiguration,inCreationSettings));
662}
663
664METHOD_RETURN_TYPE PDFWriterDriver::CreateFormXObjectFromTIFF(const ARGS_TYPE& args)
665{
666 CREATE_ISOLATE_CONTEXT;
667 CREATE_ESCAPABLE_SCOPE;
668
669 if((args.Length() != 1 && args.Length() != 2) || (!args[0]->IsString() && !args[0]->IsObject()) || (args.Length() == 2 && !args[1]->IsObject() && !args[1]->IsNumber()))
670 {
671 THROW_EXCEPTION("wrong arguments, pass 1 argument that is the path to the image, and optionally an options object or object ID");
672 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
673 }
674
675 PDFWriterDriver* pdfWriter = ObjectWrap::Unwrap<PDFWriterDriver>(args.This());
676
677 TIFFUsageParameters tiffUsageParameters = TIFFUsageParameters::DefaultTIFFUsageParameters();
678 ObjectIDType objectID = 0;
679
680 if(args.Length() == 2)
681 {
682 if(args[1]->IsObject())
683 {
684 Local<Object> anObject = args[1]->TO_OBJECT();
685
686 // page index parameters
687 if(anObject->Has(GET_CURRENT_CONTEXT, NEW_STRING("pageIndex")).FromJust() && anObject->Get(GET_CURRENT_CONTEXT, NEW_STRING("pageIndex")).ToLocalChecked()->IsNumber())
688 tiffUsageParameters.PageIndex = (unsigned int)TO_NUMBER(anObject->Get(GET_CURRENT_CONTEXT, NEW_STRING("pageIndex")).ToLocalChecked())->Value();
689
690 if(anObject->Has(GET_CURRENT_CONTEXT, NEW_STRING("bwTreatment")).FromJust() && anObject->Get(GET_CURRENT_CONTEXT, NEW_STRING("bwTreatment")).ToLocalChecked()->IsObject())
691 {
692 // special black and white treatment
693 Local<Object> bwObject = anObject->Get(GET_CURRENT_CONTEXT, NEW_STRING("bwTreatment")).ToLocalChecked()->TO_OBJECT();
694 if(bwObject->Has(GET_CURRENT_CONTEXT, NEW_STRING("asImageMask")).FromJust() && bwObject->Get(GET_CURRENT_CONTEXT, NEW_STRING("asImageMask")).ToLocalChecked()->IsBoolean())
695 tiffUsageParameters.BWTreatment.AsImageMask = bwObject->Get(GET_CURRENT_CONTEXT, NEW_STRING("asImageMask")).ToLocalChecked()->TO_BOOLEAN()->Value();
696 if(bwObject->Has(GET_CURRENT_CONTEXT, NEW_STRING("oneColor")).FromJust() && bwObject->Get(GET_CURRENT_CONTEXT, NEW_STRING("oneColor")).ToLocalChecked()->IsArray())
697 tiffUsageParameters.BWTreatment.OneColor = colorFromArray(bwObject->Get(GET_CURRENT_CONTEXT, NEW_STRING("oneColor")).ToLocalChecked());
698 }
699
700 if(anObject->Has(GET_CURRENT_CONTEXT, NEW_STRING("grayscaleTreatment")).FromJust() && anObject->Get(GET_CURRENT_CONTEXT, NEW_STRING("grayscaleTreatment")).ToLocalChecked()->IsObject())
701 {
702 // special black and white treatment
703 Local<Object> colormapObject = anObject->Get(GET_CURRENT_CONTEXT, NEW_STRING("grayscaleTreatment")).ToLocalChecked()->TO_OBJECT();
704 if(colormapObject->Has(GET_CURRENT_CONTEXT, NEW_STRING("asColorMap")).FromJust() && colormapObject->Get(GET_CURRENT_CONTEXT, NEW_STRING("asColorMap")).ToLocalChecked()->IsBoolean())
705 tiffUsageParameters.GrayscaleTreatment.AsColorMap = colormapObject->Get(GET_CURRENT_CONTEXT, NEW_STRING("asColorMap")).ToLocalChecked()->TO_BOOLEAN()->Value();
706 if(colormapObject->Has(GET_CURRENT_CONTEXT, NEW_STRING("oneColor")).FromJust() && colormapObject->Get(GET_CURRENT_CONTEXT, NEW_STRING("oneColor")).ToLocalChecked()->IsArray())
707 tiffUsageParameters.GrayscaleTreatment.OneColor = colorFromArray(colormapObject->Get(GET_CURRENT_CONTEXT, NEW_STRING("oneColor")).ToLocalChecked());
708 if(colormapObject->Has(GET_CURRENT_CONTEXT, NEW_STRING("zeroColor")).FromJust() && colormapObject->Get(GET_CURRENT_CONTEXT, NEW_STRING("zeroColor")).ToLocalChecked()->IsArray())
709 tiffUsageParameters.GrayscaleTreatment.ZeroColor = colorFromArray(colormapObject->Get(GET_CURRENT_CONTEXT, NEW_STRING("zeroColor")).ToLocalChecked());
710 }
711 }
712 else // number
713 {
714 objectID = TO_INT32(args[1])->Value();
715 }
716
717 }
718
719 PDFFormXObject* formXObject;
720
721 if(args[0]->IsObject())
722 {
723 ObjectByteReaderWithPosition proxy(args[0]->TO_OBJECT());
724
725 formXObject =
726 objectID == 0 ?
727 pdfWriter->mPDFWriter.CreateFormXObjectFromTIFFStream(&proxy,tiffUsageParameters):
728 pdfWriter->mPDFWriter.CreateFormXObjectFromTIFFStream(&proxy,objectID,tiffUsageParameters);
729
730 }
731 else
732 {
733 formXObject =
734 objectID == 0 ?
735 pdfWriter->mPDFWriter.CreateFormXObjectFromTIFFFile(*UTF_8_VALUE(args[0]->TO_STRING()),tiffUsageParameters):
736 pdfWriter->mPDFWriter.CreateFormXObjectFromTIFFFile(*UTF_8_VALUE(args[0]->TO_STRING()),objectID,tiffUsageParameters);
737 }
738 if(!formXObject)
739 {
740 THROW_EXCEPTION("unable to create form xobject. verify that the target is an existing tiff file");
741 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
742 }
743
744 Local<Value> newInstance = pdfWriter->holder->GetNewFormXObject(args);
745 ObjectWrap::Unwrap<FormXObjectDriver>(newInstance->TO_OBJECT())->FormXObject = formXObject;
746 SET_FUNCTION_RETURN_VALUE(newInstance)
747}
748
749CMYKRGBColor PDFWriterDriver::colorFromArray(v8::Local<v8::Value> inArray)
750{
751 CREATE_ISOLATE_CONTEXT;
752
753 if(inArray->TO_OBJECT()->Get(GET_CURRENT_CONTEXT, NEW_STRING("length")).ToLocalChecked()->TO_UINT32Value() == 4)
754 {
755 // cmyk color
756 return CMYKRGBColor((unsigned char)TO_NUMBER(inArray->TO_OBJECT()->Get(GET_CURRENT_CONTEXT, 0).ToLocalChecked())->Value(),
757 (unsigned char)TO_NUMBER(inArray->TO_OBJECT()->Get(GET_CURRENT_CONTEXT, 1).ToLocalChecked())->Value(),
758 (unsigned char)TO_NUMBER(inArray->TO_OBJECT()->Get(GET_CURRENT_CONTEXT, 2).ToLocalChecked())->Value(),
759 (unsigned char)TO_NUMBER(inArray->TO_OBJECT()->Get(GET_CURRENT_CONTEXT, 3).ToLocalChecked())->Value());
760
761 }
762 else if(inArray->TO_OBJECT()->Get(GET_CURRENT_CONTEXT, v8::NEW_STRING("length")).ToLocalChecked()->TO_UINT32Value() == 3)
763 {
764 // rgb color
765 return CMYKRGBColor((unsigned char)TO_NUMBER(inArray->TO_OBJECT()->Get(GET_CURRENT_CONTEXT, 0).ToLocalChecked())->Value(),
766 (unsigned char)TO_NUMBER(inArray->TO_OBJECT()->Get(GET_CURRENT_CONTEXT, 1).ToLocalChecked())->Value(),
767 (unsigned char)TO_NUMBER(inArray->TO_OBJECT()->Get(GET_CURRENT_CONTEXT, 2).ToLocalChecked())->Value());
768 }
769 else
770 {
771 THROW_EXCEPTION("wrong input for color values. should be array of either 3 or 4 colors");
772 return CMYKRGBColor::CMYKBlack();
773 }
774}
775
776METHOD_RETURN_TYPE PDFWriterDriver::CreateImageXObjectFromJPG(const ARGS_TYPE& args)
777{
778 CREATE_ISOLATE_CONTEXT;
779 CREATE_ESCAPABLE_SCOPE;
780
781 if((args.Length() != 1 && args.Length() != 2) || (!args[0]->IsString() && !args[0]->IsObject()) || (args.Length() == 2 && !args[1]->IsNumber()))
782 {
783 THROW_EXCEPTION("wrong arguments, pass 1 argument that is the path to the image. pass another optional argument of a forward reference object ID");
784 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
785 }
786
787 PDFWriterDriver* pdfWriter = ObjectWrap::Unwrap<PDFWriterDriver>(args.This());
788
789
790 PDFImageXObject* imageXObject;
791
792 if(args[0]->IsObject())
793 {
794 ObjectByteReaderWithPosition proxy(args[0]->TO_OBJECT());
795
796 imageXObject =
797 args.Length() == 2 ?
798 pdfWriter->mPDFWriter.CreateImageXObjectFromJPGStream(&proxy,(ObjectIDType)TO_INT32(args[1])->Value()) :
799 pdfWriter->mPDFWriter.CreateImageXObjectFromJPGStream(&proxy);
800 }
801 else
802 {
803 imageXObject =
804 args.Length() == 2 ?
805 pdfWriter->mPDFWriter.CreateImageXObjectFromJPGFile(*UTF_8_VALUE(args[0]->TO_STRING()),(ObjectIDType)TO_INT32(args[1])->Value()) :
806 pdfWriter->mPDFWriter.CreateImageXObjectFromJPGFile(*UTF_8_VALUE(args[0]->TO_STRING()));
807 }
808 if(!imageXObject)
809 {
810 THROW_EXCEPTION("unable to create image xobject. verify that the target is an existing jpg file");
811 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
812 }
813
814 Local<Value> newInstance = pdfWriter->holder->GetNewImageXObject(args);
815 ObjectWrap::Unwrap<ImageXObjectDriver>(newInstance->TO_OBJECT())->ImageXObject = imageXObject;
816 SET_FUNCTION_RETURN_VALUE(newInstance)
817}
818
819METHOD_RETURN_TYPE PDFWriterDriver::GetObjectsContext(const ARGS_TYPE& args)
820{
821 CREATE_ISOLATE_CONTEXT;
822 CREATE_ESCAPABLE_SCOPE;
823
824 PDFWriterDriver* pdfWriter = ObjectWrap::Unwrap<PDFWriterDriver>(args.This());
825
826 Local<Value> newInstance = pdfWriter->holder->GetNewObjectsContext(args);
827 ObjectsContextDriver* objectsContextDriver = ObjectWrap::Unwrap<ObjectsContextDriver>(newInstance->TO_OBJECT());
828 objectsContextDriver->ObjectsContextInstance = &(pdfWriter->mPDFWriter.GetObjectsContext());
829
830 SET_FUNCTION_RETURN_VALUE(newInstance)
831}
832
833METHOD_RETURN_TYPE PDFWriterDriver::GetDocumentContext(const ARGS_TYPE& args)
834{
835 CREATE_ISOLATE_CONTEXT;
836 CREATE_ESCAPABLE_SCOPE;
837
838 PDFWriterDriver* pdfWriter = ObjectWrap::Unwrap<PDFWriterDriver>(args.This());
839
840 Local<Value> newInstance = pdfWriter->holder->GetNewDocumentContext(args);
841 DocumentContextDriver* documentContextDriver = ObjectWrap::Unwrap<DocumentContextDriver>(newInstance->TO_OBJECT());
842 documentContextDriver->DocumentContextInstance = &(pdfWriter->mPDFWriter.GetDocumentContext());
843
844 SET_FUNCTION_RETURN_VALUE(newInstance)
845}
846
847
848METHOD_RETURN_TYPE PDFWriterDriver::AppendPDFPagesFromPDF(const ARGS_TYPE& args)
849{
850 CREATE_ISOLATE_CONTEXT;
851 CREATE_ESCAPABLE_SCOPE;
852
853 if( (args.Length() < 1 && args.Length() > 2) ||
854 (!args[0]->IsString() && !args[0]->IsObject()) ||
855 (args.Length() >= 2 && !args[1]->IsObject())
856 )
857 {
858 THROW_EXCEPTION("wrong arguments, pass a path for file to append pages from or a stream object, optionally an options object");
859 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
860 }
861
862 PDFWriterDriver* pdfWriter = ObjectWrap::Unwrap<PDFWriterDriver>(args.This());
863
864 PDFPageRange pageRange;
865 PDFParsingOptions parsingOptions;
866
867 if(args.Length() >= 2) {
868 Local<Object> options = args[1]->TO_OBJECT();
869 if(options->Has(GET_CURRENT_CONTEXT, NEW_STRING("password")).FromJust() && options->Get(GET_CURRENT_CONTEXT, NEW_STRING("password")).ToLocalChecked()->IsString())
870 {
871 parsingOptions.Password = *UTF_8_VALUE(options->Get(GET_CURRENT_CONTEXT, NEW_STRING("password")).ToLocalChecked()->TO_STRING());
872 }
873 pageRange = ObjectToPageRange(options);
874 }
875
876 EStatusCodeAndObjectIDTypeList result;
877
878 if(args[0]->IsObject())
879 {
880 ObjectByteReaderWithPosition proxy(args[0]->TO_OBJECT());
881 result = pdfWriter->mPDFWriter.AppendPDFPagesFromPDF(
882 &proxy,
883 pageRange,
884 ObjectIDTypeList(),
885 parsingOptions);
886 }
887 else
888 {
889 result = pdfWriter->mPDFWriter.AppendPDFPagesFromPDF(
890 *UTF_8_VALUE(args[0]->TO_STRING()),
891 pageRange,
892 ObjectIDTypeList(),
893 parsingOptions);
894 }
895
896 if(result.first != eSuccess)
897 {
898 THROW_EXCEPTION("unable to append page, make sure it's fine");
899 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
900 }
901
902 Local<Array> resultPageIDs = NEW_ARRAY((unsigned int)result.second.size());
903 unsigned int index = 0;
904
905 ObjectIDTypeList::iterator it = result.second.begin();
906 for(; it != result.second.end();++it)
907 resultPageIDs->Set(GET_CURRENT_CONTEXT, NEW_NUMBER(index++),NEW_NUMBER(*it));
908
909 SET_FUNCTION_RETURN_VALUE(resultPageIDs)
910}
911
912PDFPageRange PDFWriterDriver::ObjectToPageRange(Local<Object> inObject)
913{
914 CREATE_ISOLATE_CONTEXT;
915 PDFPageRange pageRange;
916
917 if(inObject->Has(GET_CURRENT_CONTEXT, NEW_STRING("type")).FromJust() && inObject->Get(GET_CURRENT_CONTEXT, NEW_STRING("type")).ToLocalChecked()->IsNumber())
918 {
919 pageRange.mType = (PDFPageRange::ERangeType)(TO_UINT32(inObject->Get(GET_CURRENT_CONTEXT, NEW_STRING("type")).ToLocalChecked())->Value());
920 }
921
922 if(inObject->Has(GET_CURRENT_CONTEXT, NEW_STRING("specificRanges")).FromJust() && inObject->Get(GET_CURRENT_CONTEXT, NEW_STRING("specificRanges")).ToLocalChecked()->IsArray())
923 {
924 Local<Object> anArray = inObject->Get(GET_CURRENT_CONTEXT, NEW_STRING("specificRanges")).ToLocalChecked()->TO_OBJECT();
925 unsigned int length = TO_UINT32(anArray->Get(GET_CURRENT_CONTEXT, NEW_STRING("length")).ToLocalChecked())->Value();
926 for(unsigned int i=0; i < length; ++i)
927 {
928 if(!anArray->Get(GET_CURRENT_CONTEXT, i).ToLocalChecked()->IsArray() ||
929 TO_UINT32(anArray->Get(GET_CURRENT_CONTEXT, i).ToLocalChecked()->TO_OBJECT()->Get(GET_CURRENT_CONTEXT, NEW_STRING("length")).ToLocalChecked())->Value() != 2)
930 {
931 THROW_EXCEPTION("wrong argument for specificRanges. it should be an array of arrays. each subarray should be of the length of 2, signifying begining page and ending page numbers");
932 break;
933 }
934 Local<Object> item = anArray->Get(GET_CURRENT_CONTEXT, i).ToLocalChecked()->TO_OBJECT();
935 if(!item->Get(GET_CURRENT_CONTEXT, 0).ToLocalChecked()->IsNumber() || !item->Get(GET_CURRENT_CONTEXT, 1).ToLocalChecked()->IsNumber())
936 {
937 THROW_EXCEPTION("wrong argument for specificRanges. it should be an array of arrays. each subarray should be of the length of 2, signifying begining page and ending page numbers");
938 break;
939 }
940 pageRange.mSpecificRanges.push_back(ULongAndULong(
941 TO_UINT32(item->Get(GET_CURRENT_CONTEXT, 0).ToLocalChecked())->Value(),
942 TO_UINT32(item->Get(GET_CURRENT_CONTEXT, 1).ToLocalChecked())->Value()));
943
944 }
945 }
946
947 return pageRange;
948}
949
950class MergeInterpageCallbackCaller : public DocumentContextExtenderAdapter
951{
952public:
953 EStatusCode OnAfterMergePageFromPage(
954 PDFPage* inTargetPage,
955 PDFDictionary* inPageObjectDictionary,
956 ObjectsContext* inPDFWriterObjectContext,
957 DocumentContext* inPDFWriterDocumentContext,
958 PDFDocumentHandler* inPDFDocumentHandler)
959 {
960 if(!callback.IsEmpty())
961 {
962 const unsigned argc = 0;
963 callback->Call(GET_CURRENT_CONTEXT, GET_CURRENT_CONTEXT->Global(), argc, NULL).ToLocalChecked();
964 }
965 return PDFHummus::eSuccess;
966 }
967
968 bool IsValid(){return !callback.IsEmpty();}
969
970 Local<Function> callback;
971};
972
973METHOD_RETURN_TYPE PDFWriterDriver::MergePDFPagesToPage(const ARGS_TYPE& args)
974{
975 CREATE_ISOLATE_CONTEXT;
976 CREATE_ESCAPABLE_SCOPE;
977
978 /*
979 parameters are:
980 target page
981 file path to pdf to merge pages from OR stream of pdf to merge pages from
982 optional 1: options object
983 optional 2: callback function to call after each page merge
984 */
985
986 PDFWriterDriver* pdfWriter = ObjectWrap::Unwrap<PDFWriterDriver>(args.This());
987
988 if(args.Length() < 2)
989 {
990 THROW_EXCEPTION("Too few arguments. Pass a page object, a path to pages source file or an IByteReaderWithPosition, and two optional: configuration object and callback function that will be called between pages merging");
991 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
992 }
993
994 if(!pdfWriter->holder->IsPDFPageInstance(args[0]))
995 {
996 THROW_EXCEPTION("Invalid arguments. First argument must be a page object");
997 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
998 }
999
1000 if(!args[1]->IsString() &&
1001 !args[1]->IsObject())
1002 {
1003 THROW_EXCEPTION("Invalid arguments. Second argument must be either an input stream or a path to a pages source file.");
1004 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
1005 }
1006
1007 PDFPageDriver* page = ObjectWrap::Unwrap<PDFPageDriver>(args[0]->TO_OBJECT());
1008
1009 PDFPageRange pageRange;
1010 PDFParsingOptions parsingOptions;
1011
1012 // get page range
1013 if(args.Length() > 2 && args[2]->IsObject()) {
1014 Local<Object> options = args[2]->TO_OBJECT();
1015 if(options->Has(GET_CURRENT_CONTEXT, NEW_STRING("password")).FromJust() && options->Get(GET_CURRENT_CONTEXT, NEW_STRING("password")).ToLocalChecked()->IsString())
1016 {
1017 parsingOptions.Password = *UTF_8_VALUE(options->Get(GET_CURRENT_CONTEXT, NEW_STRING("password")).ToLocalChecked()->TO_STRING());
1018 }
1019 pageRange = ObjectToPageRange(options);
1020 }
1021 else if(args.Length() > 3 && args[3]->IsObject()) {
1022 Local<Object> options = args[3]->TO_OBJECT();
1023 if(options->Has(GET_CURRENT_CONTEXT, NEW_STRING("password")).FromJust() && options->Get(GET_CURRENT_CONTEXT, NEW_STRING("password")).ToLocalChecked()->IsString())
1024 {
1025 parsingOptions.Password = *UTF_8_VALUE(options->Get(GET_CURRENT_CONTEXT, NEW_STRING("password")).ToLocalChecked()->TO_STRING());
1026 }
1027 pageRange = ObjectToPageRange(options);
1028 }
1029
1030 // now see if there's a need for activating the callback. will do that using the document extensibility option of the lib
1031 MergeInterpageCallbackCaller caller;
1032 if((args.Length() > 2 && args[2]->IsFunction()) ||
1033 (args.Length() > 3 && args[3]->IsFunction()))
1034 caller.callback = Local<Function>::Cast(args[2]->IsFunction() ? args[2] : args[3]);
1035 if(caller.IsValid())
1036 pdfWriter->mPDFWriter.GetDocumentContext().AddDocumentContextExtender(&caller);
1037
1038 EStatusCode status;
1039 if(args[1]->IsString())
1040 {
1041 status = pdfWriter->mPDFWriter.MergePDFPagesToPage(page->GetPage(),
1042 *UTF_8_VALUE(args[1]->TO_STRING()),
1043 pageRange,
1044 ObjectIDTypeList(),
1045 parsingOptions);
1046 }
1047 else
1048 {
1049 ObjectByteReaderWithPosition proxy(args[1]->TO_OBJECT());
1050 status = pdfWriter->mPDFWriter.MergePDFPagesToPage(page->GetPage(),
1051 &proxy,
1052 pageRange,
1053 ObjectIDTypeList(),
1054 parsingOptions);
1055 }
1056
1057 if(caller.IsValid())
1058 pdfWriter->mPDFWriter.GetDocumentContext().RemoveDocumentContextExtender(&caller);
1059
1060 if(status != eSuccess)
1061 {
1062 THROW_EXCEPTION("unable to append to page, make sure source file exists");
1063 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
1064 }
1065 SET_FUNCTION_RETURN_VALUE(args.This())
1066}
1067
1068METHOD_RETURN_TYPE PDFWriterDriver::CreatePDFCopyingContext(const ARGS_TYPE& args)
1069{
1070 CREATE_ISOLATE_CONTEXT;
1071 CREATE_ESCAPABLE_SCOPE;
1072
1073 if( (args.Length() < 1 && args.Length() > 2) ||
1074 (!args[0]->IsString() && !args[0]->IsObject()) ||
1075 (args.Length() >= 2 && !args[1]->IsObject())
1076 )
1077 {
1078 THROW_EXCEPTION("wrong arguments, pass a path to a PDF file to create copying context for or a stream object, and then an optional options object");
1079 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
1080 }
1081
1082 PDFWriterDriver* pdfWriter = ObjectWrap::Unwrap<PDFWriterDriver>(args.This());
1083
1084 PDFDocumentCopyingContext* copyingContext;
1085
1086 ObjectByteReaderWithPosition* proxy = NULL;
1087 PDFParsingOptions parsingOptions;
1088
1089 if(args.Length() >= 2) {
1090 Local<Object> options = args[1]->TO_OBJECT();
1091 if(options->Has(GET_CURRENT_CONTEXT, NEW_STRING("password")).FromJust() && options->Get(GET_CURRENT_CONTEXT, NEW_STRING("password")).ToLocalChecked()->IsString())
1092 {
1093 parsingOptions.Password = *UTF_8_VALUE(options->Get(GET_CURRENT_CONTEXT, NEW_STRING("password")).ToLocalChecked()->TO_STRING());
1094 }
1095 }
1096
1097
1098 if(args[0]->IsObject())
1099 {
1100 if(pdfWriter->holder->IsPDFReaderInstance(args[0]))
1101 {
1102 // parser based copying context [note that here parsingOptions doesn't matter as the parser creation already took it into account]
1103
1104 PDFParser* theParser = ObjectWrap::Unwrap<PDFReaderDriver>(args[0]->TO_OBJECT())->GetParser();
1105 copyingContext = pdfWriter->mPDFWriter.GetDocumentContext().CreatePDFCopyingContext(theParser);
1106 }
1107 else
1108 {
1109 // stream based copying context
1110
1111 proxy = new ObjectByteReaderWithPosition(args[0]->TO_OBJECT());
1112 copyingContext = pdfWriter->mPDFWriter.CreatePDFCopyingContext(proxy,parsingOptions);
1113 }
1114 }
1115 else
1116 {
1117 // file path based copying context
1118 copyingContext = pdfWriter->mPDFWriter.CreatePDFCopyingContext(*UTF_8_VALUE(args[0]->TO_STRING()),parsingOptions);
1119 }
1120
1121 if(!copyingContext)
1122 {
1123 THROW_EXCEPTION("unable to create copying context. verify that the target is an existing PDF file");
1124 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
1125 }
1126
1127 Local<Value> newInstance = pdfWriter->holder->GetNewDocumentCopyingContext(args);
1128 ObjectWrap::Unwrap<DocumentCopyingContextDriver>(newInstance->TO_OBJECT())->CopyingContext = copyingContext;
1129 ObjectWrap::Unwrap<DocumentCopyingContextDriver>(newInstance->TO_OBJECT())->ReadStreamProxy = proxy;
1130 SET_FUNCTION_RETURN_VALUE(newInstance)
1131}
1132
1133METHOD_RETURN_TYPE PDFWriterDriver::CreateFormXObjectsFromPDF(const ARGS_TYPE& args)
1134{
1135 CREATE_ISOLATE_CONTEXT;
1136 CREATE_ESCAPABLE_SCOPE;
1137
1138 if(args.Length() < 1 ||
1139 args.Length() > 5 ||
1140 !args[0]->IsString() ||
1141 (args.Length() >= 2 && (!args[1]->IsNumber() && !args[1]->IsArray())) ||
1142 (args.Length() >= 3 && !args[2]->IsObject()) ||
1143 (args.Length() >= 4 && !args[3]->IsArray()) ||
1144 (args.Length() == 5 && !args[4]->IsArray())
1145 )
1146 {
1147 THROW_EXCEPTION("wrong arguments, pass a path to the file, and optionals - a box enumerator or actual 4 numbers box, a range object, a matrix for the form, array of object ids to copy in addition");
1148 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
1149 }
1150
1151 PDFWriterDriver* pdfWriter = ObjectWrap::Unwrap<PDFWriterDriver>(args.This());
1152
1153 PDFPageRange pageRange;
1154 PDFParsingOptions parsingOptions;
1155
1156 if(args.Length() >= 3) {
1157 Local<Object> options = args[2]->TO_OBJECT();
1158 if(options->Has(GET_CURRENT_CONTEXT, NEW_STRING("password")).FromJust() && options->Get(GET_CURRENT_CONTEXT, NEW_STRING("password")).ToLocalChecked()->IsString())
1159 {
1160 parsingOptions.Password = *UTF_8_VALUE(options->Get(GET_CURRENT_CONTEXT, NEW_STRING("password")).ToLocalChecked()->TO_STRING());
1161 }
1162 pageRange = ObjectToPageRange(options);
1163 }
1164
1165 EStatusCodeAndObjectIDTypeList result;
1166 double matrixBuffer[6];
1167 double* transformationMatrix = NULL;
1168
1169 if(args.Length() >= 4)
1170 {
1171 Local<Object> matrixArray = args[3]->TO_OBJECT();
1172 if(matrixArray->Get(GET_CURRENT_CONTEXT, v8::NEW_STRING("length")).ToLocalChecked()->TO_UINT32Value() != 6)
1173 {
1174 THROW_EXCEPTION("matrix array should be 6 numbers long");
1175 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
1176 }
1177
1178 for(int i=0;i<6;++i)
1179 matrixBuffer[i] = TO_NUMBER(matrixArray->Get(GET_CURRENT_CONTEXT, i).ToLocalChecked())->Value();
1180 transformationMatrix = matrixBuffer;
1181 }
1182
1183 ObjectIDTypeList extraObjectsList;
1184 if(args.Length() >= 5)
1185 {
1186 Local<Object> objectsIDsArray = args[4]->TO_OBJECT();
1187 unsigned int arrayLength = objectsIDsArray->Get(GET_CURRENT_CONTEXT, v8::NEW_STRING("length")).ToLocalChecked()->TO_UINT32Value();
1188 for(unsigned int i=0;i<arrayLength;++i)
1189 extraObjectsList.push_back((ObjectIDType)(TO_UINT32(objectsIDsArray->Get(GET_CURRENT_CONTEXT, i).ToLocalChecked())->Value()));
1190
1191 }
1192
1193 if(args[1]->IsArray())
1194 {
1195 Local<Object> boxArray = args[1]->TO_OBJECT();
1196 if(boxArray->Get(GET_CURRENT_CONTEXT, v8::NEW_STRING("length")).ToLocalChecked()->TO_UINT32Value() != 4)
1197 {
1198 THROW_EXCEPTION("box dimensions array should be 4 numbers long");
1199 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
1200 }
1201
1202 PDFRectangle box(TO_NUMBER(boxArray->Get(GET_CURRENT_CONTEXT, 0).ToLocalChecked())->Value(),
1203 TO_NUMBER(boxArray->Get(GET_CURRENT_CONTEXT, 1).ToLocalChecked())->Value(),
1204 TO_NUMBER(boxArray->Get(GET_CURRENT_CONTEXT, 2).ToLocalChecked())->Value(),
1205 TO_NUMBER(boxArray->Get(GET_CURRENT_CONTEXT, 3).ToLocalChecked())->Value());
1206
1207 result = pdfWriter->mPDFWriter.CreateFormXObjectsFromPDF(
1208 *UTF_8_VALUE(args[0]->TO_STRING()),
1209 pageRange,
1210 box,
1211 transformationMatrix,
1212 extraObjectsList,
1213 parsingOptions);
1214 }
1215 else
1216 {
1217 result = pdfWriter->mPDFWriter.CreateFormXObjectsFromPDF(
1218 *UTF_8_VALUE(args[0]->TO_STRING()),
1219 pageRange,
1220 (EPDFPageBox)TO_UINT32(args[1])->Value(),
1221 transformationMatrix,
1222 extraObjectsList,
1223 parsingOptions);
1224 }
1225
1226 if(result.first != eSuccess)
1227 {
1228 THROW_EXCEPTION("unable to create forms from file. make sure the file exists, and that the input page range is valid (well, if you provided one..m'k?");
1229 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
1230 }
1231
1232 Local<Array> resultFormIDs = NEW_ARRAY((unsigned int)result.second.size());
1233 unsigned int index = 0;
1234
1235 ObjectIDTypeList::iterator it = result.second.begin();
1236 for(; it != result.second.end();++it)
1237 resultFormIDs->Set(GET_CURRENT_CONTEXT, NEW_NUMBER(index++),NEW_NUMBER(*it));
1238
1239 SET_FUNCTION_RETURN_VALUE(resultFormIDs)
1240}
1241
1242METHOD_RETURN_TYPE PDFWriterDriver::CreatePDFCopyingContextForModifiedFile(const ARGS_TYPE& args)
1243{
1244 CREATE_ISOLATE_CONTEXT;
1245 CREATE_ESCAPABLE_SCOPE;
1246
1247 PDFWriterDriver* pdfWriter = ObjectWrap::Unwrap<PDFWriterDriver>(args.This());
1248
1249 PDFDocumentCopyingContext* copyingContext = pdfWriter->mPDFWriter.CreatePDFCopyingContextForModifiedFile();
1250 if(!copyingContext)
1251 {
1252 THROW_EXCEPTION("unable to create copying context for modified file...possibly a file is not being modified by this writer...");
1253 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
1254 }
1255
1256 Local<Value> newInstance = pdfWriter->holder->GetNewDocumentCopyingContext(args);
1257 ObjectWrap::Unwrap<DocumentCopyingContextDriver>(newInstance->TO_OBJECT())->CopyingContext = copyingContext;
1258 SET_FUNCTION_RETURN_VALUE(newInstance)
1259}
1260
1261METHOD_RETURN_TYPE PDFWriterDriver::CreatePDFTextString(const ARGS_TYPE& args)
1262{
1263 CREATE_ISOLATE_CONTEXT;
1264 CREATE_ESCAPABLE_SCOPE;
1265 PDFWriterDriver* pdfWriter = ObjectWrap::Unwrap<PDFWriterDriver>(args.This());
1266
1267 SET_FUNCTION_RETURN_VALUE(pdfWriter->holder->GetNewPDFTextString(args))
1268
1269}
1270
1271METHOD_RETURN_TYPE PDFWriterDriver::CreatePDFDate(const ARGS_TYPE& args)
1272{
1273 CREATE_ISOLATE_CONTEXT;
1274 CREATE_ESCAPABLE_SCOPE;
1275 PDFWriterDriver* pdfWriter = ObjectWrap::Unwrap<PDFWriterDriver>(args.This());
1276
1277 SET_FUNCTION_RETURN_VALUE(pdfWriter->holder->GetNewPDFDate(args))
1278
1279}
1280
1281PDFWriter* PDFWriterDriver::GetWriter()
1282{
1283 return &mPDFWriter;
1284}
1285
1286METHOD_RETURN_TYPE PDFWriterDriver::GetImageDimensions(const ARGS_TYPE& args)
1287{
1288 CREATE_ISOLATE_CONTEXT;
1289 CREATE_ESCAPABLE_SCOPE;
1290
1291 if(args.Length() < 1 || args.Length() > 3 ||
1292 !args[0]->IsString() ||
1293 (args.Length()>=2 && !args[1]->IsNumber()) ||
1294 (args.Length() >= 3 && !args[2]->IsObject())
1295 )
1296 {
1297 THROW_EXCEPTION("wrong arguments, pass 1 to 3 arguments. a path to an image, an optional image index (for multi-image files), and an options object");
1298 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
1299 }
1300
1301 PDFWriterDriver* pdfWriter = ObjectWrap::Unwrap<PDFWriterDriver>(args.This());
1302
1303 PDFParsingOptions parsingOptions;
1304
1305 if(args.Length() >= 3) {
1306 Local<Object> options = args[2]->TO_OBJECT();
1307 if(options->Has(GET_CURRENT_CONTEXT, NEW_STRING("password")).FromJust() && options->Get(GET_CURRENT_CONTEXT, NEW_STRING("password")).ToLocalChecked()->IsString())
1308 {
1309 parsingOptions.Password = *UTF_8_VALUE(options->Get(GET_CURRENT_CONTEXT, NEW_STRING("password")).ToLocalChecked()->TO_STRING());
1310 }
1311 }
1312
1313 DoubleAndDoublePair dimensions = pdfWriter->mPDFWriter.GetImageDimensions(
1314 *UTF_8_VALUE(args[0]->TO_STRING()),
1315 args.Length() >= 2 ? TO_UINT32(args[1])->Value() : 0,
1316 parsingOptions);
1317
1318 Local<Object> newObject = NEW_OBJECT;
1319
1320 newObject->Set(GET_CURRENT_CONTEXT, NEW_SYMBOL("width"),NEW_NUMBER(dimensions.first));
1321 newObject->Set(GET_CURRENT_CONTEXT, NEW_SYMBOL("height"),NEW_NUMBER(dimensions.second));
1322 SET_FUNCTION_RETURN_VALUE(newObject)
1323};
1324
1325
1326METHOD_RETURN_TYPE PDFWriterDriver::GetImagePagesCount(const ARGS_TYPE& args)
1327{
1328 CREATE_ISOLATE_CONTEXT;
1329 CREATE_ESCAPABLE_SCOPE;
1330
1331 if(args.Length() < 1 || args.Length() > 2 ||
1332 !args[0]->IsString() ||
1333 (args.Length() >= 2 && !args[1]->IsObject())
1334 )
1335 {
1336 THROW_EXCEPTION("wrong arguments, pass 1 argument and an optional one. a path to an image, and an options object");
1337 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
1338 }
1339
1340 PDFWriterDriver* pdfWriter = ObjectWrap::Unwrap<PDFWriterDriver>(args.This());
1341 PDFParsingOptions parsingOptions;
1342
1343 if(args.Length() >= 2) {
1344 Local<Object> options = args[1]->TO_OBJECT();
1345 if(options->Has(GET_CURRENT_CONTEXT, NEW_STRING("password")).FromJust() && options->Get(GET_CURRENT_CONTEXT, NEW_STRING("password")).ToLocalChecked()->IsString())
1346 {
1347 parsingOptions.Password = *UTF_8_VALUE(options->Get(GET_CURRENT_CONTEXT, NEW_STRING("password")).ToLocalChecked()->TO_STRING());
1348 }
1349 }
1350
1351 unsigned long result = pdfWriter->mPDFWriter.GetImagePagesCount(*UTF_8_VALUE(args[0]->TO_STRING()),parsingOptions);
1352
1353 SET_FUNCTION_RETURN_VALUE(NEW_NUMBER(result))
1354}
1355
1356METHOD_RETURN_TYPE PDFWriterDriver::GetImageType(const ARGS_TYPE& args) {
1357 CREATE_ISOLATE_CONTEXT;
1358 CREATE_ESCAPABLE_SCOPE;
1359
1360 if (args.Length() != 1 ||
1361 !args[0]->IsString())
1362 {
1363 THROW_EXCEPTION("wrong arguments, pass 1 argument. a path to an imag");
1364 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
1365 }
1366
1367 PDFWriterDriver* pdfWriter = ObjectWrap::Unwrap<PDFWriterDriver>(args.This());
1368
1369 PDFHummus::EHummusImageType imageType = pdfWriter->mPDFWriter.GetImageType(*UTF_8_VALUE(args[0]->TO_STRING()),0);
1370
1371 switch(imageType)
1372 {
1373 case PDFHummus::ePDF:
1374 {
1375 SET_FUNCTION_RETURN_VALUE(NEW_STRING("PDF"))
1376 break;
1377 }
1378 case PDFHummus::eJPG:
1379 {
1380 SET_FUNCTION_RETURN_VALUE(NEW_STRING("JPEG"))
1381 break;
1382 }
1383 case PDFHummus::eTIFF:
1384 {
1385 SET_FUNCTION_RETURN_VALUE(NEW_STRING("TIFF"))
1386 break;
1387 }
1388 case PDFHummus::ePNG:
1389 {
1390 SET_FUNCTION_RETURN_VALUE(NEW_STRING("PNG"))
1391 break;
1392 }
1393 default:
1394 {
1395 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
1396 }
1397 }
1398}
1399
1400METHOD_RETURN_TYPE PDFWriterDriver::GetModifiedFileParser(const ARGS_TYPE& args)
1401{
1402 CREATE_ISOLATE_CONTEXT;
1403 CREATE_ESCAPABLE_SCOPE;
1404
1405 PDFWriterDriver* pdfWriter = ObjectWrap::Unwrap<PDFWriterDriver>(args.This());
1406
1407 PDFParser* parser = &(pdfWriter->mPDFWriter.GetModifiedFileParser());
1408 if(!parser->GetTrailer()) // checking for the trailer should be a good indication to whether this parser is relevant
1409 {
1410 THROW_EXCEPTION("unable to create modified parser...possibly a file is not being modified by this writer...");
1411 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
1412 }
1413
1414 Local<Value> newInstance = pdfWriter->holder->GetNewPDFReader(args);
1415 ObjectWrap::Unwrap<PDFReaderDriver>(newInstance->TO_OBJECT())->SetFromOwnedParser(parser);
1416 SET_FUNCTION_RETURN_VALUE(newInstance)
1417}
1418
1419METHOD_RETURN_TYPE PDFWriterDriver::GetModifiedInputFile(const ARGS_TYPE& args)
1420{
1421 CREATE_ISOLATE_CONTEXT;
1422 CREATE_ESCAPABLE_SCOPE;
1423
1424 PDFWriterDriver* pdfWriter = ObjectWrap::Unwrap<PDFWriterDriver>(args.This());
1425
1426 InputFile* inputFile = &(pdfWriter->mPDFWriter.GetModifiedInputFile());
1427 if(!inputFile->GetInputStream())
1428 {
1429 THROW_EXCEPTION("unable to create modified input file...possibly a file is not being modified by this writer...");
1430 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
1431 }
1432
1433 Local<Value> newInstance = pdfWriter->holder->GetNewInputFile(args);
1434 ObjectWrap::Unwrap<InputFileDriver>(newInstance->TO_OBJECT())->SetFromOwnedFile(inputFile);
1435 SET_FUNCTION_RETURN_VALUE(newInstance)
1436}
1437
1438METHOD_RETURN_TYPE PDFWriterDriver::GetOutputFile(const ARGS_TYPE& args)
1439{
1440 CREATE_ISOLATE_CONTEXT;
1441 CREATE_ESCAPABLE_SCOPE;
1442
1443 PDFWriterDriver* pdfWriter = ObjectWrap::Unwrap<PDFWriterDriver>(args.This());
1444
1445 OutputFile* outputFile = &(pdfWriter->mPDFWriter.GetOutputFile());
1446 if(!outputFile->GetOutputStream())
1447 {
1448 THROW_EXCEPTION("unable to get output file. probably pdf writing hasn't started, or the output is not to a file");
1449 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
1450 }
1451
1452 Local<Value> newInstance = pdfWriter->holder->GetNewOutputFile(args);
1453 ObjectWrap::Unwrap<OutputFileDriver>(newInstance->TO_OBJECT())->SetFromOwnedFile(outputFile);
1454 SET_FUNCTION_RETURN_VALUE(newInstance)
1455}
1456
1457METHOD_RETURN_TYPE PDFWriterDriver::RegisterAnnotationReferenceForNextPageWrite(const ARGS_TYPE& args)
1458{
1459 CREATE_ISOLATE_CONTEXT;
1460 CREATE_ESCAPABLE_SCOPE;
1461
1462 if(args.Length() != 1 ||
1463 !args[0]->IsNumber())
1464 {
1465 THROW_EXCEPTION("wrong arguments, pass an object ID for an annotation to register");
1466 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
1467 }
1468
1469 PDFWriterDriver* pdfWriter = ObjectWrap::Unwrap<PDFWriterDriver>(args.This());
1470
1471 pdfWriter->mPDFWriter.GetDocumentContext().RegisterAnnotationReferenceForNextPageWrite(TO_UINT32(args[0])->Value());
1472
1473 SET_FUNCTION_RETURN_VALUE(args.This())
1474}
1475
1476METHOD_RETURN_TYPE PDFWriterDriver::RequireCatalogUpdate(const ARGS_TYPE& args)
1477{
1478 CREATE_ISOLATE_CONTEXT;
1479 CREATE_ESCAPABLE_SCOPE;
1480
1481 PDFWriterDriver* pdfWriter = ObjectWrap::Unwrap<PDFWriterDriver>(args.This());
1482
1483 pdfWriter->mIsCatalogUpdateRequired = true;
1484
1485 SET_FUNCTION_RETURN_VALUE(UNDEFINED)
1486}
1487
1488/*
1489 From now on, extensions event triggers.
1490 got the following events for now:
1491
1492 OnPageWrite: {
1493 page:PDFPage,
1494 pageDictionaryContext:DictionaryContext
1495 }
1496 OnResourcesWrite {
1497 resources: ResourcesDictionary
1498 pageResourcesDictionaryContext: DictionaryContext
1499 }
1500 OnResourceDictionaryWrite {
1501 resourceDictionaryName: string
1502 resourceDictionary: DictionaryContext
1503 }
1504 OnCatalogWrite {
1505 catalogDictionaryContext: DictionaryContext
1506 }
1507*/
1508
1509PDFHummus::EStatusCode PDFWriterDriver::OnPageWrite(
1510 PDFPage* inPage,
1511 DictionaryContext* inPageDictionaryContext,
1512 ObjectsContext* inPDFWriterObjectContext,
1513 PDFHummus::DocumentContext* inDocumentContext) {
1514 CREATE_ISOLATE_CONTEXT;
1515 CREATE_ESCAPABLE_SCOPE;
1516
1517 Local<Object> params = NEW_OBJECT;
1518
1519 params->Set(GET_CURRENT_CONTEXT, NEW_SYMBOL("page"),this->holder->GetInstanceFor(inPage));
1520 params->Set(GET_CURRENT_CONTEXT, NEW_SYMBOL("pageDictionaryContext"), this->holder->GetInstanceFor(inPageDictionaryContext));
1521 return triggerEvent("OnPageWrite",params);
1522}
1523PDFHummus::EStatusCode PDFWriterDriver::OnResourcesWrite(
1524 ResourcesDictionary* inResources,
1525 DictionaryContext* inPageResourcesDictionaryContext,
1526 ObjectsContext* inPDFWriterObjectContext,
1527 PDFHummus::DocumentContext* inDocumentContext) {
1528 CREATE_ISOLATE_CONTEXT;
1529 CREATE_ESCAPABLE_SCOPE;
1530
1531 Local<Object> params = NEW_OBJECT;
1532
1533 params->Set(GET_CURRENT_CONTEXT, NEW_SYMBOL("resources"),this->holder->GetInstanceFor(inResources));
1534 params->Set(GET_CURRENT_CONTEXT, NEW_SYMBOL("pageResourcesDictionaryContext"),this->holder->GetInstanceFor(inPageResourcesDictionaryContext));
1535 return triggerEvent("OnResourcesWrite",params);
1536}
1537
1538PDFHummus::EStatusCode PDFWriterDriver::OnResourceDictionaryWrite(
1539 DictionaryContext* inResourceDictionary,
1540 const std::string& inResourceDictionaryName,
1541 ObjectsContext* inPDFWriterObjectContext,
1542 PDFHummus::DocumentContext* inDocumentContext) {
1543 CREATE_ISOLATE_CONTEXT;
1544 CREATE_ESCAPABLE_SCOPE;
1545
1546 Local<Object> params = NEW_OBJECT;
1547
1548 params->Set(GET_CURRENT_CONTEXT, NEW_SYMBOL("resourceDictionaryName"),NEW_STRING(inResourceDictionaryName.c_str()));
1549 params->Set(GET_CURRENT_CONTEXT, NEW_SYMBOL("resourceDictionary"),this->holder->GetInstanceFor(inResourceDictionary));
1550 return triggerEvent("OnResourceDictionaryWrite",params);
1551}
1552
1553PDFHummus::EStatusCode PDFWriterDriver::OnFormXObjectWrite(
1554 ObjectIDType inFormXObjectID,
1555 ObjectIDType inFormXObjectResourcesDictionaryID,
1556 DictionaryContext* inFormDictionaryContext,
1557 ObjectsContext* inPDFWriterObjectContext,
1558 PDFHummus::DocumentContext* inDocumentContext) {
1559
1560 return PDFHummus::eSuccess;
1561}
1562PDFHummus::EStatusCode PDFWriterDriver::OnJPEGImageXObjectWrite(
1563 ObjectIDType inImageXObjectID,
1564 DictionaryContext* inImageDictionaryContext,
1565 ObjectsContext* inPDFWriterObjectContext,
1566 PDFHummus::DocumentContext* inDocumentContext,
1567 JPEGImageHandler* inJPGImageHandler) {
1568
1569 return PDFHummus::eSuccess;
1570}
1571PDFHummus::EStatusCode PDFWriterDriver::OnTIFFImageXObjectWrite(
1572 ObjectIDType inImageXObjectID,
1573 DictionaryContext* inImageDictionaryContext,
1574 ObjectsContext* inPDFWriterObjectContext,
1575 PDFHummus::DocumentContext* inDocumentContext,
1576 TIFFImageHandler* inTIFFImageHandler) {
1577
1578 return PDFHummus::eSuccess;
1579}
1580
1581PDFHummus::EStatusCode PDFWriterDriver::triggerEvent(const std::string& inEventName, v8::Local<v8::Object> inParams) {
1582 CREATE_ISOLATE_CONTEXT;
1583 CREATE_ESCAPABLE_SCOPE;
1584
1585 Local<Value> value = THIS_HANDLE->Get(GET_CURRENT_CONTEXT, NEW_STRING("triggerDocumentExtensionEvent")).ToLocalChecked();
1586 if(value->IsUndefined())
1587 return PDFHummus::eFailure;
1588 Local<Function> func = Local<Function>::Cast(value);
1589 Local<Value> args[2];
1590 args[0] = NEW_STRING(inEventName.c_str());
1591 args[1] = inParams;
1592 func->Call(GET_CURRENT_CONTEXT, THIS_HANDLE, 2, args).ToLocalChecked();
1593 return PDFHummus::eSuccess;
1594}
1595
1596
1597PDFHummus::EStatusCode PDFWriterDriver::OnCatalogWrite(
1598 CatalogInformation* inCatalogInformation,
1599 DictionaryContext* inCatalogDictionaryContext,
1600 ObjectsContext* inPDFWriterObjectContext,
1601 PDFHummus::DocumentContext* inDocumentContext) {
1602 CREATE_ISOLATE_CONTEXT;
1603 CREATE_ESCAPABLE_SCOPE;
1604
1605 Local<Object> params = NEW_OBJECT;
1606
1607 // this is the only important one
1608 params->Set(GET_CURRENT_CONTEXT, NEW_SYMBOL("catalogDictionaryContext"),this->holder->GetInstanceFor(inCatalogDictionaryContext));
1609 return triggerEvent("OnCatalogWrite",params);
1610}
1611
1612
1613PDFHummus::EStatusCode PDFWriterDriver::OnPDFParsingComplete(
1614 ObjectsContext* inPDFWriterObjectContext,
1615 PDFHummus::DocumentContext* inDocumentContext,
1616 PDFDocumentHandler* inPDFDocumentHandler) {
1617
1618 return PDFHummus::eSuccess;
1619}
1620PDFHummus::EStatusCode PDFWriterDriver::OnBeforeCreateXObjectFromPage(
1621 PDFDictionary* inPageObjectDictionary,
1622 ObjectsContext* inPDFWriterObjectContext,
1623 PDFHummus::DocumentContext* inDocumentContext,
1624 PDFDocumentHandler* inPDFDocumentHandler) {
1625
1626 return PDFHummus::eSuccess;
1627}
1628PDFHummus::EStatusCode PDFWriterDriver::OnAfterCreateXObjectFromPage(
1629 PDFFormXObject* iPageObjectResultXObject,
1630 PDFDictionary* inPageObjectDictionary,
1631 ObjectsContext* inPDFWriterObjectContext,
1632 PDFHummus::DocumentContext* inDocumentContext,
1633 PDFDocumentHandler* inPDFDocumentHandler) {
1634
1635 return PDFHummus::eSuccess;
1636}
1637PDFHummus::EStatusCode PDFWriterDriver::OnBeforeCreatePageFromPage(
1638 PDFDictionary* inPageObjectDictionary,
1639 ObjectsContext* inPDFWriterObjectContext,
1640 PDFHummus::DocumentContext* inDocumentContext,
1641 PDFDocumentHandler* inPDFDocumentHandler) {
1642
1643 return PDFHummus::eSuccess;
1644}
1645PDFHummus::EStatusCode PDFWriterDriver::OnAfterCreatePageFromPage(
1646 PDFPage* iPageObjectResultPage,
1647 PDFDictionary* inPageObjectDictionary,
1648 ObjectsContext* inPDFWriterObjectContext,
1649 PDFHummus::DocumentContext* inDocumentContext,
1650 PDFDocumentHandler* inPDFDocumentHandler) {
1651
1652 return PDFHummus::eSuccess;
1653}
1654PDFHummus::EStatusCode PDFWriterDriver::OnBeforeMergePageFromPage(
1655 PDFPage* inTargetPage,
1656 PDFDictionary* inPageObjectDictionary,
1657 ObjectsContext* inPDFWriterObjectContext,
1658 PDFHummus::DocumentContext* inDocumentContext,
1659 PDFDocumentHandler* inPDFDocumentHandler) {
1660
1661 return PDFHummus::eSuccess;
1662}
1663PDFHummus::EStatusCode PDFWriterDriver::OnAfterMergePageFromPage(
1664 PDFPage* inTargetPage,
1665 PDFDictionary* inPageObjectDictionary,
1666 ObjectsContext* inPDFWriterObjectContext,
1667 PDFHummus::DocumentContext* inDocumentContext,
1668 PDFDocumentHandler* inPDFDocumentHandler) {
1669
1670 return PDFHummus::eSuccess;
1671}
1672PDFHummus::EStatusCode PDFWriterDriver::OnPDFCopyingComplete(
1673 ObjectsContext* inPDFWriterObjectContext,
1674 PDFHummus::DocumentContext* inDocumentContext,
1675 PDFDocumentHandler* inPDFDocumentHandler) {
1676
1677 return PDFHummus::eSuccess;
1678}
1679bool PDFWriterDriver::IsCatalogUpdateRequiredForModifiedFile(PDFParser* inModifiderFileParser) {
1680
1681 return mIsCatalogUpdateRequired;
1682}
1683
1684PDFHummus::EStatusCode PDFWriterDriver::setupListenerIfOK(PDFHummus::EStatusCode inCode) {
1685 if(inCode == PDFHummus::eSuccess)
1686 mPDFWriter.GetDocumentContext().AddDocumentContextExtender(this);
1687 return inCode;
1688}
\No newline at end of file