1 /**
2  * Describes main document.
3  */
4 module harud.doc;
5 
6 import harud.c.capi;
7 import harud.c.consts;
8 import harud;
9 import std.conv;
10 import std.string;
11 
12 /**
13  * PDF Document Class
14  */
15 class Doc : IHaruObject {
16    protected HPDF_Doc _doc;
17    protected void delegate(HPDF_STATUS, HPDF_STATUS) dlg;
18    public HPDF_Font fuente;
19 
20    /**
21     * Creates a new Doc instance
22     * Returns: the new Doc instance
23     */
24    this() {
25       void delegate(uint, uint) stdErrorHandler = delegate void(uint e, uint d) { throw new HarudException(e); };
26       this(stdErrorHandler);
27    }
28 
29    /**
30     * Creates a new Doc instance with a delegate which is invoked when an
31     * error occurred.
32     *
33     * The delegate must be in the form of
34     * ---
35     * void error_callback(uint error_no, uint detail_no)
36     * ---
37     , where error_no it's the number's error and detail_no it's the detail's number
38     *
39     * Params:
40     * _dlg = The delegate wich is invoked
41     *
42     * Returns:
43     * the new Doc instance
44     *
45     * Examples:
46     * ------------------------------------
47     * void error_handler(uint error_no, uint detail_no) {
48     *    writefln("error_no: %s, detail_no: %s", error_no, detail_no);
49     * }
50     * Doc document = new Doc( &errorHandler );
51     * ------------------------------------
52     */
53    this(void delegate(HPDF_STATUS error_no, HPDF_STATUS detail_no) _dlg) {
54       dlg = _dlg;
55       this._doc = HPDF_New(&errorHandler, cast(void*)this);
56    }
57 
58    extern (C) static void errorHandler(HPDF_STATUS error_no, HPDF_STATUS detail_no, Doc doc) {
59       doc.dlg(error_no, detail_no);
60    }
61 
62    /**
63     * Creates a new page and adds it after the last page of a document.
64     *
65     * Returns:
66     * a Page instance of the created page on success. Otherwise, it returns error-code and error-handler is called.
67     */
68    Page addPage() {
69       return new Page(HPDF_AddPage(this._doc));
70    }
71 
72    /**
73     * Adds a page labeling range for the document.
74     *
75     * Params:
76     *  pageNum = The first page that applies this labeling range
77     *  style = One of the following numbering styles:
78     *  $(UL
79     *     $(LI PageNumStyle.DECIMAL - Arabic numerals (1 2 3 4))
80     *     $(LI PageNumStyle.UPPER_ROMAN - Uppercase roman numerals (I II III IV))
81     *     $(LI PageNumStyle.LOWER_ROMAN - Lowercase roman numerals (i ii iii iv))
82     *     $(LI PageNumStyle.UPPER_LETTERS - Uppercase letters (A B C D))
83     *     $(LI PageNumStyle,LOWER_LETTERS - Lowercase letters (a b c d))
84     *  )
85     *
86     *  firstPage = The first page number to use
87     *  prefix = The prefix for the page label. (null is allowed.)
88     */
89    HPDF_STATUS addPageLabel(uint pageNum, PageNumStyle style, uint firstPage, string prefix = null) {
90       return HPDF_AddPageLabel(this._doc, pageNum, style, firstPage, prefix.toStringz());
91    }
92 
93    /**
94     * Creates an instance of Outline object.
95     *
96     * Params:
97     *  parent = the instance of a Outline object which comes to the parent of the created outline object. If null, the outline is created as a root outline.
98     *  title = the caption of the outline object.
99     *  encoder = the instance of a Encoding object applied to the title. If null, PDFDocEncoding is used.
100     *
101     * Returns:
102     * when createOutline() succeeds, it returns a instance of Outline object. Otherwise, it returns null and error-handler is invoked.
103     */
104    Outline createOutline(string title, Outline parent = null, Encoder encoder = null) {
105       HPDF_Outline outline = HPDF_CreateOutline(this._doc, parent is null ? null : parent.getHandle(), title.toStringz(),
106             encoder is null ? null : encoder.getHandle());
107       return new Outline(outline);
108    }
109 
110    /**
111     * Gets the handle of the current encoder of the document object.
112     *
113     * The current encoder is set by invoking currentEncoder setter and it is used to processing a text when an application invokes setInfoAttr().
114     * The default value of it is null.
115     *
116     * Returns:
117     * It returns an instance of a Encoder object or null
118     */
119    Encoder getCurrentEncoder() {
120       HPDF_Encoder encoder = HPDF_GetCurrentEncoder(this._doc);
121       return new Encoder(encoder);
122    }
123 
124    /**
125     * Sets the current encoder for the document
126     *
127     * Params:
128     * encodingName = the name of an encoding
129     */
130    HPDF_STATUS setCurrentEncoderByName(string encodingName) {
131       return HPDF_SetCurrentEncoder(this._doc, encodingName.toStringz());
132    }
133 
134    /**
135     * Returns current page object.
136     *
137     * Returns:
138     * it returns the instance of a current Page object. Otherwise it returns NULL.
139     */
140    Page getCurrentPage() {
141       return new Page(HPDF_GetCurrentPage(this._doc));
142    }
143 
144    /**
145     * Gets an instance of a Encoder object by specified encoding name
146     *
147     * Params:
148     *  encodingName = a valid encoding name
149     *
150     * Returns:
151     * when getEncoder() succeeds, it returns an instance of a Encoder object. Otherwise, it returns null and error-handler is called
152     */
153    Encoder getEncoder(string encodingName) {
154       HPDF_Encoder encoder = HPDF_GetEncoder(this._doc, encodingName.toStringz());
155       return new Encoder(encoder);
156    }
157 
158    /**
159     * Returns the last error code.
160     */
161    HPDF_STATUS getError() {
162       return HPDF_GetError(this._doc);
163    }
164 
165    /**
166     * Once an error code is set, IO processing functions cannot be invoked.
167     *
168     * In the case of executing a function after the cause of the error is fixed, an application have to invoke resetError() to clear error-code before executing functions
169     */
170    void resetError() {
171       HPDF_ResetError(this._doc);
172    }
173 
174    /**
175     * Sets a user-defined error delegate.
176     *
177     * If a function call fails, the error delegate is called.
178     *
179     * Params:
180     * _dlg = The delegate to invoke
181     *
182     * See_Also:
183     * this( void delegate( HPDF_STATUS error_no, HPDF_STATUS detail_no ) _dlg )
184     */
185    HPDF_STATUS setErrorHandler(void delegate(HPDF_STATUS, HPDF_STATUS) _dlg) {
186       this.dlg = _dlg;
187       return HPDF_SetErrorHandler(this._doc, &errorHandler);
188    }
189 
190    /**
191     * Gets a Font instance of the requested font
192     *
193     * Params:
194     *  fontName = a valid font name
195     *
196     * Returns:
197     *  when getFont() succeeds, it returns the instance of a Font object.
198     *  Otherwise, it returns null and error-handler is called.
199     */
200    Font getFont(string fontName)
201    in {
202       assert(fontName.length > 0);
203    }
204    do {
205       return new Font(HPDF_GetFont(this._doc, fontName.toStringz(), null));
206    }
207 
208    /**
209     * Gets a Font instance of the requested font
210     *
211     * Params:
212     *  fontName = A valid font name
213     *  encodingName = A valid encoding name
214     *
215     * Returns:
216     * when getFont() succeeds, it returns the instance of a Font object.
217     * Otherwise, it returns null and error-handler is called
218     */
219    Font getFont(string fontName, string encodingName)
220    in {
221       assert(fontName.length > 0);
222       assert(encodingName.length > 0);
223    }
224    do {
225       return new Font(HPDF_GetFont(this._doc, fontName.toStringz(), encodingName.toStringz()));
226    }
227 
228    /**
229     * Gets an attribute value from info dictionary.
230     *
231     * Params:
232     *  type = one of the following:
233     *  $(UL
234     *     $(LI HaruInfo.author)
235     *     $(LI HaruInfo.creator)
236     *     $(LI HaruInfo.title)
237     *     $(LI HaruInfo.subject)
238     *     $(LI HaruInfo.keywords)
239     *  )
240     *
241     * Returns:
242     * when succeeds, it returns the string value of the info dictionary.
243     * If the infomation has not been set or an error has occurred, it returns
244     * null.
245     */
246    string getInfoAttr(HaruInfoType type) {
247       return to!string(HPDF_GetInfoAttr(this._doc, type));
248    }
249 
250    /**
251     * Sets the text of an info dictionary attribute, using current encoding of the document
252     *
253     * Params:
254     *  type = one of the following:
255     *  $(UL
256     *     $(LI HaruInfo.author)
257     *     $(LI HaruInfo.creator)
258     *     $(LI HaruInfo.title)
259     *     $(LI HaruInfo.subject)
260     *     $(LI HaruInfo.keywords)
261     *  )
262     *  value = text
263     */
264    HPDF_STATUS setInfoAttr(HaruInfoType type, string value) {
265       return HPDF_SetInfoAttr(this._doc, type, value.toStringz());
266    }
267 
268    /**
269     * Gets the size of the temporary stream of the document.
270     *
271     * Returns: the size of the temporary stream
272     */
273    uint getStreamSize() {
274       return HPDF_GetStreamSize(this._doc);
275    }
276 
277    /**
278     * Creates a new page and inserts it just before the specified page.
279     *
280     * Params:
281     * target = the instance of a Page. Insert new page just before.
282     *
283     * Returns:
284     * a Page instance of the created page on success. Otherwise, it returns NULL and error-handler is called.
285     */
286    Page insertPage(Page target) {
287       return new Page(HPDF_InsertPage(this._doc, target.getHandle()));
288    }
289 
290    /**
291     * Returns the current setting for page layout
292     *
293     * Returns:
294     * the current setting for $(LINK2 harud/c/types/PageLayout.html, PageLayout)
295     */
296    PageLayout getPageLayout() {
297       return HPDF_GetPageLayout(this._doc);
298    }
299 
300    /**
301     * Sets how the page should be displayed.
302     *
303     * If this attribute is not set, the setting of the viewer application is used
304     *
305     * Params:
306     * layout = $(LINK2 harud/c/types/PageLayout.html, PageLayout) value
307     */
308    void setPageLayout(PageLayout layout) {
309       HPDF_SetPageLayout(this._doc, layout);
310    }
311 
312    /**
313     * Returns the current setting for page mode
314     *
315     * Returns:
316     * the current setting for $(LINK2 harud/c/types/PageMode.html, PageMode)
317     */
318    PageMode getPageMode() {
319       return HPDF_GetPageMode(this._doc);
320    }
321 
322    /**
323     * Sets how the document should be displayed
324     *
325     * Params:
326     * mode = Page mode $(LINK2 harud/c/types/PageMode.html, PageMode)
327     */
328    void setPageMode(PageMode mode) {
329       HPDF_SetPageMode(this._doc, mode);
330    }
331 
332    /**
333     * Copies the data from the temporary stream of the document into a buffer.
334     *
335     * Params:
336     * buf = Pointer to the buffer
337     * size = Size of the buffer
338     */
339    HPDF_STATUS readFromStream(ubyte* buf, uint* size) {
340       return HPDF_ReadFromStream(this._doc, buf, size);
341    }
342 
343    /**
344     * Rewinds the temporary stream of the document
345     */
346    HPDF_STATUS resetStream() {
347       return HPDF_ResetStream(this._doc);
348    }
349 
350    /**
351     * Saves the document to a file.
352     *
353     * Params:
354     *  filename = The name of the file to save
355     */
356    HPDF_STATUS saveToFile(string filename) {
357       return HPDF_SaveToFile(this._doc, filename.toStringz());
358    }
359 
360    /**
361     * Saves the document to a temporary stream.
362     */
363    HPDF_STATUS saveToStream() {
364       return HPDF_SaveToStream(this._doc);
365    }
366 
367    /**
368     * In the default setting, a Doc object has one "Pages" object as root of pages.
369     *
370     * All "Page" objects are created as a kid of the "Pages" object.
371     * Since a "Pages" object can own only 8191 kids objects, the maximum number of pages are 8191 page.
372     * Additionally, the state that there are a lot of "Page" object under
373     * one"Pages" object is not good, because it causes performance degradation of a viewer application.
374     *
375     * An application can change the setting of a pages tree by invoking setPagesConfiguration().
376     * If pagePerPages parameter is set to more than zero, a two-tier pages tree is created.
377     * A root "Pages" object can own 8191 "Pages" object, and each lower "Pages" object can own pagePerPages "Page" objects.
378     * As a result, the maximum number of pages becomes 8191 * pagePerPages page.
379     * An application cannot invoke setPageConfiguration() after a page is added to document
380     *
381     * Params:
382     *  pagePerPages = Specify the numbers of pages that a "Pages" object can own
383     */
384    HPDF_STATUS setPagesConfiguration(uint pagePerPages) {
385       return HPDF_SetPagesConfiguration(this._doc, pagePerPages);
386    }
387 
388    /**
389     * Set the first page to appear when a document is opened.
390     *
391     * Params:
392     *  openAction = a valid destination object.
393     */
394    HPDF_STATUS setOpenAction(HPDF_Destination openAction) {
395       return HPDF_SetOpenAction(this._doc, openAction);
396    }
397 
398    /**
399     * Loads a Type1 font from an external file and registers it in the document object
400     *
401     * Params:
402     *  afmfilename = a path of an AFM file
403     *  pfmfilename = a path of a PFA/PFB file. If null, the glyph data of font file is not embedded to a PDF file
404     *
405     * Returns:
406     *  it returns the name of a font. Otherwise, it returns null and error-handler is called
407     */
408    string loadType1FontFromFile(string afmfilename, string pfmfilename = null) {
409       return to!string(HPDF_LoadType1FontFromFile(this._doc, afmfilename.toStringz(), pfmfilename.toStringz()));
410    }
411 
412    /**
413     * Loads a TrueType font from an external file and register it to a document object
414     *
415     * Params:
416     *  filename = A path of a TrueType font file (.ttf)
417     *  embedding = if this parameter is true, the glyph data of the font is embedded, otherwise only the matrix data is included in PDF file
418     *
419     * Returns:
420     *  when loadTTFontFromFile() succeeds, it returns the name of a font.
421     *  Otherwise, it returns null and error-handler is called
422     */
423    string loadTTFontFromFile(string filename, bool embedding = false) {
424       return to!string(HPDF_LoadTTFontFromFile(this._doc, filename.toStringz(), embedding ? HPDF_TRUE : HPDF_FALSE));
425    }
426 
427    /**
428     * Loads a TrueType font from an external file (at the selected index) and register it to a document object
429     *
430     * Params:
431     *  filename = A path of a TrueType font file (.ttf)
432     *  embedding = if this parameter is true, the glyph data of the font is embedded, otherwise only the matrix data is included in PDF file
433     *  index = the index of font to be loaded.
434     *
435     * Returns:
436     *  when loadTTFontFromFile() succeeds, it returns the name of a font. Otherwise, it returns null and error-handler is called
437     */
438    string loadTTFontFromFile(string filename, uint index, bool embedding) {
439       return to!string(HPDF_LoadTTFontFromFile2(this._doc, filename.toStringz(), index, embedding ? HPDF_TRUE : HPDF_FALSE));
440    }
441 
442    /**
443     * Enables Japanese fonts. After useJPFonts() is involed, an application can use the following Japanese fonts
444     *
445     * $(UL
446     *    $(LI MS-Mincyo)
447     *    $(LI MS-Mincyo,Bold)
448     *    $(LI MS-Mincyo,Italic)
449     *    $(LI MS-Mincyo,BoldItalic)
450     *    $(LI MS-Gothic)
451     *    $(LI MS-Gothic,Bold)
452     *    $(LI MS-Gothic,Italic)
453     *    $(LI MS-Gothic,BoldItalic)
454     *    $(LI MS-PMincyo)
455     *    $(LI MS-PMincyo,Bold)
456     *    $(LI MS-PMincyo,Italic)
457     *    $(LI MS-PMincyo,BoldItalic)
458     *    $(LI MS-PGothic)
459     *    $(LI MS-PGothic,Bold)
460     *    $(LI MS-PGothic,Italic)
461     *    $(LI MS-PGothic,BoldItalic)
462     * )
463     */
464    HPDF_STATUS useJPFonts() {
465       return HPDF_UseJPFonts(this._doc);
466    }
467 
468    /**
469     * Enables Korean fonts. After useKRFonts() is involed, an application can use the following Korean fonts
470     *
471     * $(UL
472     *    $(LI DotumChe)
473     *    $(LI DotumChe,Bold)
474     *    $(LI DotumChe,Italic)
475     *    $(LI DotumChe,BoldItalic)
476     *    $(LI Dotum)
477     *    $(LI Dotum,Bold)
478     *    $(LI Dotum,Italic)
479     *    $(LI Dotum,BoldItalic)
480     *    $(LI BatangChe)
481     *    $(LI BatangChe,Bold)
482     *    $(LI BatangChe,Italic)
483     *    $(LI BatangChe,BoldItalic)
484     *    $(LI Batang)
485     *    $(LI Batang,Bold)
486     *    $(LI Batang,Italic)
487     *    $(LI Batang,BoldItalic)
488     * )
489     */
490    HPDF_STATUS useKRFonts() {
491       return HPDF_UseKRFonts(this._doc);
492    }
493 
494    /**
495     * Enables simplified Chinese fonts.
496     *
497     * After useCNSFonts() is involed, an application can use the following simplified Chinese fonts
498     *
499     * $(UL
500     *    $(LI SimSun)
501     *    $(LI SimSun,Bold)
502     *    $(LI SimSun,Italic)
503     *    $(LI SimSun,BoldItalic)
504     *    $(LI SimHei)
505     *    $(LI SimHei,Bold)
506     *    $(LI SimHei,Italic)
507     *    $(LI SimHei,BoldItalic)
508     * )
509     *
510     */
511    HPDF_STATUS useCNSFonts() {
512       return HPDF_UseCNSFonts(this._doc);
513    }
514 
515    /**
516     * Enables traditional Chinese fonts.
517     *
518     * After useCNTFonts() is involed, an application can use the following traditional Chinese fonts
519     *
520     * $(UL
521     *    $(LI MingLiU)
522     *    $(LI MingLiU,Bold)
523     *    $(LI MingLiU,Italic)
524     *    $(LI MingLiU,BoldItalic)
525     * )
526     */
527    HPDF_STATUS useCNTFonts() {
528       return HPDF_UseCNTFonts(this._doc);
529    }
530 
531    /**
532     * Enables Japanese encodings.
533     *
534     * After useJPEncodings() is invoked, an application can use the following Japanese encodings:
535     * $(UL
536     *    $(LI 90ms-RKSJ-H)
537     *    $(LI 90ms-RKSJ-V)
538     *    $(LI 90msp-RKSJ-H)
539     *    $(LI EUC-H)
540     *    $(LI EUC-V)
541     * )
542     */
543    HPDF_STATUS useJPEncodings() {
544       return HPDF_UseJPEncodings(this._doc);
545    }
546 
547    /**
548     * Enables Korean encodings.
549     *
550     * After useKREncodings() is involed, an application can use the following Korean encodings:
551     *
552     * $(UL
553     *    $(LI KSC-EUC-H)
554     *    $(LI KSC-EUC-V)
555     *    $(LI KSCms-UHC-H)
556     *    $(LI KSCms-UHC-HW-H)
557     *    $(LI KSCms-UHC-HW-V)
558     * )
559     */
560    HPDF_STATUS useKREncodings() {
561       return HPDF_UseKREncodings(this._doc);
562    }
563 
564    /**
565     * Enables simplified Chinese encodings.
566     *
567     * After useCNSEncodings() is involed, an application can use the following simplified Chinese encodings
568     * $(UL
569     *    $(LI GB-EUC-H)
570     *    $(LI GB-EUC-V)
571     *    $(LI GBK-EUC-H)
572     *    $(LI GBK-EUC-V)
573     * )
574     */
575    HPDF_STATUS useCNSEncodings() {
576       return HPDF_UseCNSEncodings(this._doc);
577    }
578 
579    /**
580     * Enables traditional Chinese encodings.
581     *
582     * After useCNTEncodings() is involed, an application can use the following traditional Chinese encodings.
583     *
584     * $(UL
585     *    $(LI GB-EUC-H)
586     *    $(LI GB-EUC-V)
587     *    $(LI GBK-EUC-H)
588     *    $(LI GBK-EUC-V)
589     * )
590     */
591    HPDF_STATUS useCNTEncodings() {
592       return HPDF_UseCNTEncodings(this._doc);
593    }
594 
595    /**
596     * Loads an external PNG image file.
597     *
598     * If deferred is true. then does not load all the data immediately (only size and color properties are loaded).
599     * The main data are loaded just before the image object is written to PDF, and the loaded data are deleted immediately.
600     *
601     * Params:
602     *  filename = a path to a PNG image file
603     *  deferred = if the load of the image must be referred
604     *
605     * Returns:
606     * when loadPngImageFromFile() succeeds, it returns an instance of a Image object.
607     * Otherwise, it returns null and error-handler is called.
608     */
609    Image loadPngImageFromFile(string filename, bool deferred = false) {
610       HPDF_Image image = null;
611       if (deferred) {
612          image = HPDF_LoadPngImageFromFile2(this._doc, filename.toStringz());
613       } else {
614          image = HPDF_LoadPngImageFromFile(this._doc, filename.toStringz());
615       }
616       return new Image(image);
617    }
618 
619    /**
620     * Loads an image which has "raw" image format.
621     *
622     * This function loads the data without any conversion. So it is usually faster than the other functions.
623     *
624     * Params:
625     * filename = A path to a image file.
626     * width = The width of an image file.
627     * height = The height of an image file.
628     * colorSpace = the $(LINK2 harud/c/types/ColorSpace.html, ColorSpace).
629     * `deviceGrey`, `deviceRGB` or `deviceCMYK` are allowed.
630     *
631     * Returns:
632     * When loadRawImageFromFile() succeeds, it returns an instance of a $(LINK2 harud/image/Image.html,Image) object.
633     * Otherwise, it returns `null` and error-handler is called.
634     */
635    Image loadRawImageFromFile(string filename, uint width, uint height, ColorSpace colorSpace) {
636       HPDF_Image image = HPDF_LoadRawImageFromFile(this._doc, filename.toStringz(), width, height, colorSpace);
637       return new Image(image);
638    }
639 
640    /**
641     * Loads an image which has $(I raw) image format from buffer.
642     *
643     * This function loads the data without any conversion. So it is usually faster than the other functions.
644     * The formats that loadRawImageFromMem() can load is the same as loadRawImageFromFile()
645     *
646     * Params:
647     *  buf = The pointer to the image data.
648     *  width = The width of an image file.
649     *  height = The height of an image file.
650     *  colorSpace = the $(LINK2 harud/c/types/ColorSpace.html, ColorSpace).  `deviceGrey`, `deviceRGB` or `deviceCMYK` are allowed.
651     *  bitsPerComponent = The bit size of each color component. The valid value is either 1, 2, 4, 8.
652     *
653     * Returns:
654     * When loadRawImageFromMem() succeeds,
655     * it returns an instance of a $(LINK2 harud/image/Image.html,Image) object.
656     * Otherwise, it returns `null` and error-handler is called.
657     */
658    Image loadRawImageFromMem(ubyte* buf, uint width, uint height, ColorSpace colorSpace, uint bitsPerComponent) {
659       HPDF_Image image = HPDF_LoadRawImageFromMem(this._doc, buf, width, height, colorSpace, bitsPerComponent);
660       return new Image(image);
661    }
662 
663    /**
664     * Loads an external JPEG image file
665     *
666     * Params:
667     * filename = path to a JPEG image file
668     *
669     * Returns:
670     * when loadJpegImageFromFile() succeeds,
671     * it returns an instance of a $(LINK2 harud/image/Image.html,Image) object.
672     * Otherwise, it returns `null` and error-handler is called.
673     */
674    Image loadJpegImageFromFile(string filename) {
675       HPDF_Image image = HPDF_LoadJpegImageFromFile(this._doc, filename.toStringz());
676       return new Image(image);
677    }
678 
679    /**
680     * Sets a datetime attribute in the info dictionary.
681     *
682     * Params:
683     *  type = one of the following attributes:
684     *  $(UL
685     *    $(LI HaruInfo.CREATION_DATE)
686     *    $(LI HaruInfo.MOD_DATE)
687     *  )
688     *
689     *  value = The new value for the attribute.
690     *
691     * See_Also: HaruDate
692     */
693    HPDF_STATUS setInfoDateAttr(HaruInfoType type, HaruDate value) {
694       return HPDF_SetInfoDateAttr(this._doc, type, value);
695    }
696 
697    /**
698     * Sets a password for the document. If the password is set, document contents are encrypted
699     *
700     * Params:
701     *  ownerPasswd = The password for the owner of the document. The owner can change the permission of the document. null, zero length string, and the same value as user password are not allowed.
702     *  userPasswd = The password for the user of the document. The userPassword may be set to null or zero length string.
703     *
704     */
705    HPDF_STATUS setPassword(string ownerPasswd, string userPasswd = null) {
706       return HPDF_SetPassword(this._doc, ownerPasswd.toStringz(), userPasswd.toStringz());
707    }
708 
709    /**
710     * Set the permission flags for the document
711     *
712     * Params:
713     *  permission = One or more of the $(LINK2 harud/c/types/HaruPermission.html, HaruPermission) "ored" together
714     */
715    HPDF_STATUS setPermission(HaruPermission permission) {
716       return HPDF_SetPermission(this._doc, permission);
717    }
718 
719    /**
720     * Set the encryption mode. As the side effect, ups the version of PDF to 1.4 when the mode is set to HaruEncryptMode.R3
721     *
722     * Params:
723     *  mode = One  of the $(LINK2
724     *  harud/c/types/HaruEncryptMode.html, HaruEncryptMode)
725     *  keyLen = Specify the byte length of encryption key. Only valid for HaruEncryptMode.R3. Between 5 (40 bits) and 16 (128 bits) can be specified
726     *
727     */
728    HPDF_STATUS setEncryptionMode(HaruEncryptMode mode, uint keyLen) {
729       return HPDF_SetEncryptionMode(this._doc, mode, keyLen);
730    }
731 
732    /**
733     * Set the mode of compression.
734     *
735     * Params:
736     *  mode = Compression mode $(LINK2 harud/c/types/CompressionMode.html, CompressionMode)
737     */
738    HPDF_STATUS setCompressionMode(CompressionMode mode) {
739       return HPDF_SetCompressionMode(this._doc, mode);
740    }
741 
742    HPDF_HANDLE getHandle() {
743       return this._doc;
744    }
745 }
746 
747 /**
748  * Get version
749  */
750 string getVersion() {
751    return to!string(HPDF_GetVersion());
752 }
753 
754 /**
755  * Checks if the document is valid.
756  *
757  * Params:
758  *  document = The instance of Doc to check
759  *
760  * Returns:
761  *  If the specified document handle is valid, it returns true.
762  *  Otherwise, it returns false and error-handler is called.
763  */
764 static bool hasDoc(Doc document) {
765    return (HPDF_HasDoc(document._doc) != 0);
766 }