1 /*
2  * << Haru Free PDF Library >> -- hpdf_page_operator.c
3  *
4  * URL: http://libharu.org
5  *
6  * Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
7  * Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
8  *
9  * Permission to use, copy, modify, distribute and sell this software
10  * and its documentation for any purpose is hereby granted without fee,
11  * provided that the above copyright notice appear in all copies and
12  * that both that copyright notice and this permission notice appear
13  * in supporting documentation.
14  * It is provided "as is" without express or implied warranty.
15  *
16  */
17 
18 #include "hpdf_conf.h"
19 #include "hpdf_utils.h"
20 #include "hpdf_pages.h"
21 #include "hpdf.h"
22 
23 static const HPDF_Point INIT_POS = {0, 0};
24 static const HPDF_DashMode INIT_MODE = {{0, 0, 0, 0, 0, 0, 0, 0}, 0, 0};
25 
26 
27 static HPDF_STATUS
28 InternalWriteText  (HPDF_PageAttr    attr,
29                     const char      *text);
30 
31 
32 static HPDF_STATUS
33 InternalArc  (HPDF_Page    page,
34               HPDF_REAL    x,
35               HPDF_REAL    y,
36               HPDF_REAL    ray,
37               HPDF_REAL    ang1,
38               HPDF_REAL    ang2,
39               HPDF_BOOL    cont_flg);
40 
41 
42 static HPDF_STATUS
43 InternalShowTextNextLine  (HPDF_Page    page,
44                            const char  *text,
45                            HPDF_UINT    len);
46 
47 
48 
49 /*--- General graphics state ---------------------------------------------*/
50 
51 /* w */
52 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_SetLineWidth(HPDF_Page page,HPDF_REAL line_width)53 HPDF_Page_SetLineWidth  (HPDF_Page  page,
54                          HPDF_REAL  line_width)
55 {
56     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PAGE_DESCRIPTION |
57                     HPDF_GMODE_TEXT_OBJECT);
58     HPDF_PageAttr attr;
59 
60     HPDF_PTRACE ((" HPDF_Page_SetLineWidth\n"));
61 
62     if (ret != HPDF_OK)
63         return ret;
64 
65     attr = (HPDF_PageAttr)page->attr;
66 
67     if (line_width < 0)
68         return HPDF_RaiseError (page->error, HPDF_PAGE_OUT_OF_RANGE, 0);
69 
70     if (HPDF_Stream_WriteReal (attr->stream, line_width) != HPDF_OK)
71         return HPDF_CheckError (page->error);
72 
73     if (HPDF_Stream_WriteStr (attr->stream, " w\012") != HPDF_OK)
74         return HPDF_CheckError (page->error);
75 
76     attr->gstate->line_width = line_width;
77 
78     return ret;
79 }
80 
81 /* J */
82 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_SetLineCap(HPDF_Page page,HPDF_LineCap line_cap)83 HPDF_Page_SetLineCap  (HPDF_Page     page,
84                        HPDF_LineCap  line_cap)
85 {
86     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PAGE_DESCRIPTION |
87                     HPDF_GMODE_TEXT_OBJECT);
88     HPDF_PageAttr attr;
89 
90     HPDF_PTRACE ((" HPDF_Page_SetLineCap\n"));
91 
92     if (ret != HPDF_OK)
93         return ret;
94 
95     if (line_cap >= HPDF_LINECAP_EOF)
96         return HPDF_RaiseError (page->error, HPDF_PAGE_OUT_OF_RANGE,
97                 (HPDF_STATUS)line_cap);
98 
99     attr = (HPDF_PageAttr)page->attr;
100 
101     if ((ret = HPDF_Stream_WriteInt (attr->stream,
102                 (HPDF_UINT)line_cap)) != HPDF_OK)
103         return ret;
104 
105     if ((ret = HPDF_Stream_WriteStr (attr->stream,
106                 " J\012")) != HPDF_OK)
107         return HPDF_CheckError (page->error);
108 
109     attr->gstate->line_cap = line_cap;
110 
111     return ret;
112 }
113 
114 /* j */
115 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_SetLineJoin(HPDF_Page page,HPDF_LineJoin line_join)116 HPDF_Page_SetLineJoin  (HPDF_Page      page,
117                         HPDF_LineJoin  line_join)
118 {
119     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PAGE_DESCRIPTION |
120                     HPDF_GMODE_TEXT_OBJECT);
121     HPDF_PageAttr attr;
122 
123     HPDF_PTRACE ((" HPDF_Page_SetLineJoin\n"));
124 
125     if (ret != HPDF_OK)
126         return ret;
127 
128     if (line_join >= HPDF_LINEJOIN_EOF)
129         return HPDF_RaiseError (page->error, HPDF_PAGE_OUT_OF_RANGE,
130                 (HPDF_STATUS)line_join);
131 
132     attr = (HPDF_PageAttr)page->attr;
133 
134     if (HPDF_Stream_WriteInt (attr->stream, (HPDF_UINT)line_join) != HPDF_OK)
135         return HPDF_CheckError (page->error);
136 
137     if (HPDF_Stream_WriteStr (attr->stream, " j\012") != HPDF_OK)
138         return HPDF_CheckError (page->error);
139 
140     attr->gstate->line_join = line_join;
141 
142     return ret;
143 }
144 
145 /* M */
146 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_SetMiterLimit(HPDF_Page page,HPDF_REAL miter_limit)147 HPDF_Page_SetMiterLimit  (HPDF_Page  page,
148                           HPDF_REAL  miter_limit)
149 {
150     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PAGE_DESCRIPTION |
151                     HPDF_GMODE_TEXT_OBJECT);
152     HPDF_PageAttr attr;
153 
154     HPDF_PTRACE ((" HPDF_Page_SetMitterLimit\n"));
155 
156     if (ret != HPDF_OK)
157         return ret;
158 
159     attr = (HPDF_PageAttr)page->attr;
160 
161     if (miter_limit < 1)
162         return HPDF_RaiseError (page->error, HPDF_PAGE_OUT_OF_RANGE, 0);
163 
164     if (HPDF_Stream_WriteReal (attr->stream, miter_limit) != HPDF_OK)
165         return HPDF_CheckError (page->error);
166 
167     if (HPDF_Stream_WriteStr (attr->stream, " M\012") != HPDF_OK)
168         return HPDF_CheckError (page->error);
169 
170     attr->gstate->miter_limit = miter_limit;
171 
172     return ret;
173 }
174 
175 /* d */
176 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_SetDash(HPDF_Page page,const HPDF_UINT16 * dash_ptn,HPDF_UINT num_param,HPDF_UINT phase)177 HPDF_Page_SetDash  (HPDF_Page           page,
178                     const HPDF_UINT16  *dash_ptn,
179                     HPDF_UINT           num_param,
180                     HPDF_UINT           phase)
181 {
182     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PAGE_DESCRIPTION |
183                     HPDF_GMODE_TEXT_OBJECT);
184     char buf[HPDF_TMP_BUF_SIZ];
185     char *pbuf = buf;
186     char *eptr = buf + HPDF_TMP_BUF_SIZ - 1;
187     const HPDF_UINT16 *pdash_ptn = dash_ptn;
188     HPDF_PageAttr attr;
189     HPDF_UINT i;
190 
191     HPDF_PTRACE ((" HPDF_Page_SetDash\n"));
192 
193     if (ret != HPDF_OK)
194         return ret;
195 
196     if (num_param != 1 && (num_param / 2) * 2 != num_param)
197         return HPDF_RaiseError (page->error, HPDF_PAGE_INVALID_PARAM_COUNT,
198                 num_param);
199 
200     if (num_param == 0 && phase > 0)
201         return HPDF_RaiseError (page->error, HPDF_PAGE_OUT_OF_RANGE,
202                 phase);
203 
204     if (!dash_ptn && num_param > 0)
205         return HPDF_RaiseError (page->error, HPDF_INVALID_PARAMETER,
206                 phase);
207 
208     HPDF_MemSet (buf, 0, HPDF_TMP_BUF_SIZ);
209     *pbuf++ = '[';
210 
211     for (i = 0; i < num_param; i++) {
212         if (*pdash_ptn == 0 || *pdash_ptn > HPDF_MAX_DASH_PATTERN)
213             return HPDF_RaiseError (page->error, HPDF_PAGE_OUT_OF_RANGE, 0);
214 
215         pbuf = HPDF_IToA (pbuf, *pdash_ptn, eptr);
216         *pbuf++ = ' ';
217         pdash_ptn++;
218     }
219 
220     *pbuf++ = ']';
221     *pbuf++ = ' ';
222 
223     pbuf = HPDF_IToA (pbuf, phase, eptr);
224     HPDF_StrCpy (pbuf, " d\012", eptr);
225 
226     attr = (HPDF_PageAttr)page->attr;
227 
228     if ((ret = HPDF_Stream_WriteStr (attr->stream, buf)) != HPDF_OK)
229         return HPDF_CheckError (page->error);
230 
231     attr->gstate->dash_mode = INIT_MODE;
232     attr->gstate->dash_mode.num_ptn = num_param;
233     attr->gstate->dash_mode.phase = phase;
234 
235     pdash_ptn = dash_ptn;
236     for (i = 0; i < num_param; i++) {
237         attr->gstate->dash_mode.ptn[i] = *pdash_ptn;
238         pdash_ptn++;
239     }
240 
241     return ret;
242 }
243 
244 
245 /* ri --not implemented yet */
246 
247 /* i */
248 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_SetFlat(HPDF_Page page,HPDF_REAL flatness)249 HPDF_Page_SetFlat  (HPDF_Page  page,
250                     HPDF_REAL  flatness)
251 {
252     HPDF_PageAttr attr;
253     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PAGE_DESCRIPTION |
254                     HPDF_GMODE_TEXT_OBJECT);
255 
256     HPDF_PTRACE ((" HPDF_Page_SetFlat\n"));
257 
258     if (ret != HPDF_OK)
259         return ret;
260 
261     attr = (HPDF_PageAttr)page->attr;
262 
263     if (flatness > 100 || flatness < 0)
264         return HPDF_RaiseError (page->error, HPDF_PAGE_OUT_OF_RANGE, 0);
265 
266     if (HPDF_Stream_WriteReal (attr->stream, flatness) != HPDF_OK)
267         return HPDF_CheckError (page->error);
268 
269     if (HPDF_Stream_WriteStr (attr->stream, " i\012") != HPDF_OK)
270         return HPDF_CheckError (page->error);
271 
272     attr->gstate->flatness = flatness;
273 
274     return ret;
275 }
276 
277 /* gs */
278 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_SetExtGState(HPDF_Page page,HPDF_ExtGState ext_gstate)279 HPDF_Page_SetExtGState  (HPDF_Page        page,
280                          HPDF_ExtGState   ext_gstate)
281 {
282     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PAGE_DESCRIPTION);
283     HPDF_PageAttr attr;
284     const char *local_name;
285 
286     HPDF_PTRACE ((" HPDF_Page_SetExtGState\n"));
287 
288     if (ret != HPDF_OK)
289         return ret;
290 
291     if (!HPDF_ExtGState_Validate (ext_gstate))
292         return HPDF_RaiseError (page->error, HPDF_INVALID_OBJECT, 0);
293 
294     if (page->mmgr != ext_gstate->mmgr)
295         return HPDF_RaiseError (page->error, HPDF_INVALID_EXT_GSTATE, 0);
296 
297     attr = (HPDF_PageAttr)page->attr;
298     local_name = HPDF_Page_GetExtGStateName (page, ext_gstate);
299 
300     if (!local_name)
301         return HPDF_CheckError (page->error);
302 
303     if (HPDF_Stream_WriteEscapeName (attr->stream, local_name) != HPDF_OK)
304         return HPDF_CheckError (page->error);
305 
306     if (HPDF_Stream_WriteStr (attr->stream, " gs\012") != HPDF_OK)
307         return HPDF_CheckError (page->error);
308 
309     /* change objct class to read only. */
310     ext_gstate->header.obj_class = (HPDF_OSUBCLASS_EXT_GSTATE_R | HPDF_OCLASS_DICT);
311 
312     return ret;
313 }
314 
315 
316 /*--- Special graphic state operator --------------------------------------*/
317 
318 /* q */
319 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_GSave(HPDF_Page page)320 HPDF_Page_GSave  (HPDF_Page  page)
321 {
322     HPDF_GState new_gstate;
323     HPDF_PageAttr attr;
324     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PAGE_DESCRIPTION);
325 
326     HPDF_PTRACE ((" HPDF_Page_GSave\n"));
327 
328     if (ret != HPDF_OK)
329         return ret;
330 
331     attr = (HPDF_PageAttr)page->attr;
332 
333     new_gstate = HPDF_GState_New (page->mmgr, attr->gstate);
334     if (!new_gstate)
335         return HPDF_CheckError (page->error);
336 
337     if (HPDF_Stream_WriteStr (attr->stream, "q\012") != HPDF_OK)
338         return HPDF_CheckError (page->error);
339 
340     attr->gstate = new_gstate;
341 
342     return ret;
343 }
344 
345 /* Q */
346 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_GRestore(HPDF_Page page)347 HPDF_Page_GRestore  (HPDF_Page  page)
348 {
349     HPDF_GState new_gstate;
350     HPDF_PageAttr attr;
351     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PAGE_DESCRIPTION);
352 
353     HPDF_PTRACE ((" HPDF_Page_GRestore\n"));
354 
355     if (ret != HPDF_OK)
356         return ret;
357 
358     attr = (HPDF_PageAttr)page->attr;
359 
360     if (!attr->gstate->prev)
361         return HPDF_RaiseError (page->error, HPDF_PAGE_CANNOT_RESTORE_GSTATE,
362                 0);
363 
364     new_gstate = HPDF_GState_Free (page->mmgr, attr->gstate);
365 
366     attr->gstate = new_gstate;
367 
368     if (HPDF_Stream_WriteStr (attr->stream, "Q\012") != HPDF_OK)
369         return HPDF_CheckError (page->error);
370 
371     return ret;
372 }
373 
374 /* cm */
375 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_Concat(HPDF_Page page,HPDF_REAL a,HPDF_REAL b,HPDF_REAL c,HPDF_REAL d,HPDF_REAL x,HPDF_REAL y)376 HPDF_Page_Concat  (HPDF_Page         page,
377                    HPDF_REAL         a,
378                    HPDF_REAL         b,
379                    HPDF_REAL         c,
380                    HPDF_REAL         d,
381                    HPDF_REAL         x,
382                    HPDF_REAL         y)
383 {
384     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PAGE_DESCRIPTION);
385     char buf[HPDF_TMP_BUF_SIZ];
386     char *pbuf = buf;
387     char *eptr = buf + HPDF_TMP_BUF_SIZ - 1;
388     HPDF_PageAttr attr;
389     HPDF_TransMatrix tm;
390 
391     HPDF_PTRACE ((" HPDF_Page_Concat\n"));
392 
393     if (ret != HPDF_OK)
394         return ret;
395 
396     attr = (HPDF_PageAttr)page->attr;
397 
398     HPDF_MemSet (buf, 0, HPDF_TMP_BUF_SIZ);
399 
400     pbuf = HPDF_FToA (pbuf, a, eptr);
401     *pbuf++ = ' ';
402     pbuf = HPDF_FToA (pbuf, b, eptr);
403     *pbuf++ = ' ';
404     pbuf = HPDF_FToA (pbuf, c, eptr);
405     *pbuf++ = ' ';
406     pbuf = HPDF_FToA (pbuf, d, eptr);
407     *pbuf++ = ' ';
408     pbuf = HPDF_FToA (pbuf, x, eptr);
409     *pbuf++ = ' ';
410     pbuf = HPDF_FToA (pbuf, y, eptr);
411     HPDF_StrCpy (pbuf, " cm\012", eptr);
412 
413     if (HPDF_Stream_WriteStr (attr->stream, buf) != HPDF_OK)
414         return HPDF_CheckError (page->error);
415 
416     tm = attr->gstate->trans_matrix;
417 
418     attr->gstate->trans_matrix.a = tm.a * a + tm.b * c;
419     attr->gstate->trans_matrix.b = tm.a * b + tm.b * d;
420     attr->gstate->trans_matrix.c = tm.c * a + tm.d * c;
421     attr->gstate->trans_matrix.d = tm.c * b + tm.d * d;
422     attr->gstate->trans_matrix.x = tm.x + x * tm.a + y * tm.c;
423     attr->gstate->trans_matrix.y = tm.y + x * tm.b + y * tm.d;
424 
425     return ret;
426 }
427 
428 /*--- Path construction operator ------------------------------------------*/
429 
430 /* m */
431 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_MoveTo(HPDF_Page page,HPDF_REAL x,HPDF_REAL y)432 HPDF_Page_MoveTo  (HPDF_Page  page,
433                    HPDF_REAL  x,
434                    HPDF_REAL  y)
435 {
436     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PAGE_DESCRIPTION |
437                     HPDF_GMODE_PATH_OBJECT);
438     char buf[HPDF_TMP_BUF_SIZ];
439     char *pbuf = buf;
440     char *eptr = buf + HPDF_TMP_BUF_SIZ - 1;
441     HPDF_PageAttr attr;
442 
443     HPDF_PTRACE ((" HPDF_Page_MoveTo\n"));
444 
445     if (ret != HPDF_OK)
446         return ret;
447 
448     attr = (HPDF_PageAttr)page->attr;
449 
450     HPDF_MemSet (buf, 0, HPDF_TMP_BUF_SIZ);
451 
452     pbuf = HPDF_FToA (pbuf, x, eptr);
453     *pbuf++ = ' ';
454     pbuf = HPDF_FToA (pbuf, y, eptr);
455     HPDF_StrCpy (pbuf, " m\012", eptr);
456 
457     if (HPDF_Stream_WriteStr (attr->stream, buf) != HPDF_OK)
458         return HPDF_CheckError (page->error);
459 
460     attr->cur_pos.x = x;
461     attr->cur_pos.y = y;
462     attr->str_pos = attr->cur_pos;
463     attr->gmode = HPDF_GMODE_PATH_OBJECT;
464 
465     return ret;
466 }
467 
468 /* l */
469 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_LineTo(HPDF_Page page,HPDF_REAL x,HPDF_REAL y)470 HPDF_Page_LineTo  (HPDF_Page  page,
471                    HPDF_REAL  x,
472                    HPDF_REAL  y)
473 {
474     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PATH_OBJECT);
475     char buf[HPDF_TMP_BUF_SIZ];
476     char *pbuf = buf;
477     char *eptr = buf + HPDF_TMP_BUF_SIZ - 1;
478     HPDF_PageAttr attr;
479 
480     HPDF_PTRACE ((" HPDF_Page_LineTo\n"));
481 
482     if (ret != HPDF_OK)
483         return ret;
484 
485     attr = (HPDF_PageAttr)page->attr;
486 
487     HPDF_MemSet (buf, 0, HPDF_TMP_BUF_SIZ);
488 
489     pbuf = HPDF_FToA (pbuf, x, eptr);
490     *pbuf++ = ' ';
491     pbuf = HPDF_FToA (pbuf, y, eptr);
492     HPDF_StrCpy (pbuf, " l\012", eptr);
493 
494     if (HPDF_Stream_WriteStr (attr->stream, buf) != HPDF_OK)
495         return HPDF_CheckError (page->error);
496 
497     attr->cur_pos.x = x;
498     attr->cur_pos.y = y;
499 
500     return ret;
501 }
502 
503 /* c */
504 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_CurveTo(HPDF_Page page,HPDF_REAL x1,HPDF_REAL y1,HPDF_REAL x2,HPDF_REAL y2,HPDF_REAL x3,HPDF_REAL y3)505 HPDF_Page_CurveTo  (HPDF_Page  page,
506                     HPDF_REAL  x1,
507                     HPDF_REAL  y1,
508                     HPDF_REAL  x2,
509                     HPDF_REAL  y2,
510                     HPDF_REAL  x3,
511                     HPDF_REAL  y3)
512 {
513     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PATH_OBJECT);
514     char buf[HPDF_TMP_BUF_SIZ];
515     char *pbuf = buf;
516     char *eptr = buf + HPDF_TMP_BUF_SIZ - 1;
517     HPDF_PageAttr attr;
518 
519     HPDF_PTRACE ((" HPDF_Page_CurveTo\n"));
520 
521     if (ret != HPDF_OK)
522         return ret;
523 
524     attr = (HPDF_PageAttr)page->attr;
525 
526     HPDF_MemSet (buf, 0, HPDF_TMP_BUF_SIZ);
527 
528     pbuf = HPDF_FToA (pbuf, x1, eptr);
529     *pbuf++ = ' ';
530     pbuf = HPDF_FToA (pbuf, y1, eptr);
531     *pbuf++ = ' ';
532     pbuf = HPDF_FToA (pbuf, x2, eptr);
533     *pbuf++ = ' ';
534     pbuf = HPDF_FToA (pbuf, y2, eptr);
535     *pbuf++ = ' ';
536     pbuf = HPDF_FToA (pbuf, x3, eptr);
537     *pbuf++ = ' ';
538     pbuf = HPDF_FToA (pbuf, y3, eptr);
539     HPDF_StrCpy (pbuf, " c\012", eptr);
540 
541     if (HPDF_Stream_WriteStr (attr->stream, buf) != HPDF_OK)
542         return HPDF_CheckError (page->error);
543 
544     attr->cur_pos.x = x3;
545     attr->cur_pos.y = y3;
546 
547     return ret;
548 }
549 
550 /* v */
551 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_CurveTo2(HPDF_Page page,HPDF_REAL x2,HPDF_REAL y2,HPDF_REAL x3,HPDF_REAL y3)552 HPDF_Page_CurveTo2  (HPDF_Page  page,
553                      HPDF_REAL  x2,
554                      HPDF_REAL  y2,
555                      HPDF_REAL  x3,
556                      HPDF_REAL  y3)
557 {
558     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PATH_OBJECT);
559     char buf[HPDF_TMP_BUF_SIZ];
560     char *pbuf = buf;
561     char *eptr = buf + HPDF_TMP_BUF_SIZ - 1;
562     HPDF_PageAttr attr;
563 
564     HPDF_PTRACE ((" HPDF_Page_CurveTo2\n"));
565 
566     if (ret != HPDF_OK)
567         return ret;
568 
569     attr = (HPDF_PageAttr)page->attr;
570 
571     HPDF_MemSet (buf, 0, HPDF_TMP_BUF_SIZ);
572 
573     pbuf = HPDF_FToA (pbuf, x2, eptr);
574     *pbuf++ = ' ';
575     pbuf = HPDF_FToA (pbuf, y2, eptr);
576     *pbuf++ = ' ';
577     pbuf = HPDF_FToA (pbuf, x3, eptr);
578     *pbuf++ = ' ';
579     pbuf = HPDF_FToA (pbuf, y3, eptr);
580     HPDF_StrCpy (pbuf, " v\012", eptr);
581 
582     if (HPDF_Stream_WriteStr (attr->stream, buf) != HPDF_OK)
583         return HPDF_CheckError (page->error);
584 
585     attr->cur_pos.x = x3;
586     attr->cur_pos.y = y3;
587 
588     return ret;
589 }
590 
591 /* y */
592 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_CurveTo3(HPDF_Page page,HPDF_REAL x1,HPDF_REAL y1,HPDF_REAL x3,HPDF_REAL y3)593 HPDF_Page_CurveTo3  (HPDF_Page  page,
594                      HPDF_REAL  x1,
595                      HPDF_REAL  y1,
596                      HPDF_REAL  x3,
597                      HPDF_REAL  y3)
598 {
599     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PATH_OBJECT);
600     char buf[HPDF_TMP_BUF_SIZ];
601     char *pbuf = buf;
602     char *eptr = buf + HPDF_TMP_BUF_SIZ - 1;
603     HPDF_PageAttr attr;
604 
605     HPDF_PTRACE ((" HPDF_Page_CurveTo3\n"));
606 
607     if (ret != HPDF_OK)
608         return ret;
609 
610     attr = (HPDF_PageAttr)page->attr;
611 
612     HPDF_MemSet (buf, 0, HPDF_TMP_BUF_SIZ);
613 
614     pbuf = HPDF_FToA (pbuf, x1, eptr);
615     *pbuf++ = ' ';
616     pbuf = HPDF_FToA (pbuf, y1, eptr);
617     *pbuf++ = ' ';
618     pbuf = HPDF_FToA (pbuf, x3, eptr);
619     *pbuf++ = ' ';
620     pbuf = HPDF_FToA (pbuf, y3, eptr);
621     HPDF_StrCpy (pbuf, " y\012", eptr);
622 
623     if (HPDF_Stream_WriteStr (attr->stream, buf) != HPDF_OK)
624         return HPDF_CheckError (page->error);
625 
626     attr->cur_pos.x = x3;
627     attr->cur_pos.y = y3;
628 
629     return ret;
630 }
631 
632 /* h */
633 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_ClosePath(HPDF_Page page)634 HPDF_Page_ClosePath  (HPDF_Page  page)
635 {
636     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PATH_OBJECT);
637     HPDF_PageAttr attr;
638 
639     HPDF_PTRACE ((" HPDF_Page_ClosePath\n"));
640 
641     if (ret != HPDF_OK)
642         return ret;
643 
644     attr = (HPDF_PageAttr)page->attr;
645 
646     if (HPDF_Stream_WriteStr (attr->stream, "h\012") != HPDF_OK)
647         return HPDF_CheckError (page->error);
648 
649     attr->cur_pos = attr->str_pos;
650 
651     return ret;
652 }
653 
654 /* re */
655 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_Rectangle(HPDF_Page page,HPDF_REAL x,HPDF_REAL y,HPDF_REAL width,HPDF_REAL height)656 HPDF_Page_Rectangle  (HPDF_Page  page,
657                       HPDF_REAL  x,
658                       HPDF_REAL  y,
659                       HPDF_REAL  width,
660                       HPDF_REAL  height)
661 {
662     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PAGE_DESCRIPTION |
663                     HPDF_GMODE_PATH_OBJECT);
664     char buf[HPDF_TMP_BUF_SIZ];
665     char *pbuf = buf;
666     char *eptr = buf + HPDF_TMP_BUF_SIZ - 1;
667     HPDF_PageAttr attr;
668 
669     HPDF_PTRACE ((" HPDF_Page_Rectangle\n"));
670 
671     if (ret != HPDF_OK)
672         return ret;
673 
674     attr = (HPDF_PageAttr)page->attr;
675 
676     HPDF_MemSet (buf, 0, HPDF_TMP_BUF_SIZ);
677 
678     pbuf = HPDF_FToA (pbuf, x, eptr);
679     *pbuf++ = ' ';
680     pbuf = HPDF_FToA (pbuf, y, eptr);
681     *pbuf++ = ' ';
682     pbuf = HPDF_FToA (pbuf, width, eptr);
683     *pbuf++ = ' ';
684     pbuf = HPDF_FToA (pbuf, height, eptr);
685     HPDF_StrCpy (pbuf, " re\012", eptr);
686 
687     if (HPDF_Stream_WriteStr (attr->stream, buf) != HPDF_OK)
688         return HPDF_CheckError (page->error);
689 
690     attr->cur_pos.x = x;
691     attr->cur_pos.y = y;
692     attr->str_pos = attr->cur_pos;
693     attr->gmode = HPDF_GMODE_PATH_OBJECT;
694 
695     return ret;
696 }
697 
698 
699 /*--- Path painting operator ---------------------------------------------*/
700 
701 /* S */
702 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_Stroke(HPDF_Page page)703 HPDF_Page_Stroke  (HPDF_Page  page)
704 {
705     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PATH_OBJECT |
706         HPDF_GMODE_CLIPPING_PATH);
707     HPDF_PageAttr attr;
708 
709     HPDF_PTRACE ((" HPDF_Page_Stroke\n"));
710 
711     if (ret != HPDF_OK)
712         return ret;
713 
714     attr = (HPDF_PageAttr)page->attr;
715 
716     if (HPDF_Stream_WriteStr (attr->stream, "S\012") != HPDF_OK)
717         return HPDF_CheckError (page->error);
718 
719     attr->gmode = HPDF_GMODE_PAGE_DESCRIPTION;
720     attr->cur_pos = INIT_POS;
721 
722     return ret;
723 }
724 
725 /* s */
726 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_ClosePathStroke(HPDF_Page page)727 HPDF_Page_ClosePathStroke  (HPDF_Page  page)
728 {
729     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PATH_OBJECT |
730             HPDF_GMODE_CLIPPING_PATH);
731     HPDF_PageAttr attr;
732 
733     HPDF_PTRACE ((" HPDF_Page_ClosePathStroke\n"));
734 
735     if (ret != HPDF_OK)
736         return ret;
737 
738     attr = (HPDF_PageAttr)page->attr;
739 
740     if (HPDF_Stream_WriteStr (attr->stream, "s\012") != HPDF_OK)
741         return HPDF_CheckError (page->error);
742 
743     attr->gmode = HPDF_GMODE_PAGE_DESCRIPTION;
744     attr->cur_pos = INIT_POS;
745 
746     return ret;
747 }
748 
749 /* f */
750 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_Fill(HPDF_Page page)751 HPDF_Page_Fill  (HPDF_Page  page)
752 {
753     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PATH_OBJECT |
754             HPDF_GMODE_CLIPPING_PATH);
755     HPDF_PageAttr attr;
756 
757     HPDF_PTRACE ((" HPDF_Page_Fill\n"));
758 
759     if (ret != HPDF_OK)
760         return ret;
761 
762     attr = (HPDF_PageAttr)page->attr;
763 
764     if (HPDF_Stream_WriteStr (attr->stream, "f\012") != HPDF_OK)
765         return HPDF_CheckError (page->error);
766 
767     attr->gmode = HPDF_GMODE_PAGE_DESCRIPTION;
768     attr->cur_pos = INIT_POS;
769 
770     return ret;
771 }
772 
773 /* f* */
774 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_Eofill(HPDF_Page page)775 HPDF_Page_Eofill  (HPDF_Page  page)
776 {
777     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PATH_OBJECT |
778             HPDF_GMODE_CLIPPING_PATH);
779     HPDF_PageAttr attr;
780 
781     HPDF_PTRACE ((" HPDF_Page_Eofill\n"));
782 
783     if (ret != HPDF_OK)
784         return ret;
785 
786     attr = (HPDF_PageAttr)page->attr;
787 
788     if (HPDF_Stream_WriteStr (attr->stream, "f*\012") != HPDF_OK)
789         return HPDF_CheckError (page->error);
790 
791     attr->gmode = HPDF_GMODE_PAGE_DESCRIPTION;
792     attr->cur_pos = INIT_POS;
793 
794     return ret;
795 }
796 
797 /* B */
798 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_FillStroke(HPDF_Page page)799 HPDF_Page_FillStroke  (HPDF_Page  page)
800 {
801     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PATH_OBJECT |
802             HPDF_GMODE_CLIPPING_PATH);
803     HPDF_PageAttr attr;
804 
805     HPDF_PTRACE ((" HPDF_Page_FillStroke\n"));
806 
807     if (ret != HPDF_OK)
808         return ret;
809 
810     attr = (HPDF_PageAttr)page->attr;
811 
812     if (HPDF_Stream_WriteStr (attr->stream, "B\012") != HPDF_OK)
813         return HPDF_CheckError (page->error);
814 
815     attr->gmode = HPDF_GMODE_PAGE_DESCRIPTION;
816     attr->cur_pos = INIT_POS;
817 
818     return ret;
819 }
820 
821 /* B* */
822 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_EofillStroke(HPDF_Page page)823 HPDF_Page_EofillStroke  (HPDF_Page  page)
824 {
825     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PATH_OBJECT |
826             HPDF_GMODE_CLIPPING_PATH);
827     HPDF_PageAttr attr;
828 
829     HPDF_PTRACE ((" HPDF_Page_EofillStroke\n"));
830 
831     if (ret != HPDF_OK)
832         return ret;
833 
834     attr = (HPDF_PageAttr)page->attr;
835 
836     if (HPDF_Stream_WriteStr (attr->stream, "B*\012") != HPDF_OK)
837         return HPDF_CheckError (page->error);
838 
839     attr->gmode = HPDF_GMODE_PAGE_DESCRIPTION;
840 
841     return ret;
842 }
843 
844 /* b */
845 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_ClosePathFillStroke(HPDF_Page page)846 HPDF_Page_ClosePathFillStroke  (HPDF_Page  page)
847 {
848     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PATH_OBJECT |
849             HPDF_GMODE_CLIPPING_PATH);
850     HPDF_PageAttr attr;
851 
852     HPDF_PTRACE ((" HPDF_Page_ClosePathFillStroke\n"));
853 
854     if (ret != HPDF_OK)
855         return ret;
856 
857     attr = (HPDF_PageAttr)page->attr;
858 
859     if (HPDF_Stream_WriteStr (attr->stream, "b\012") != HPDF_OK)
860         return HPDF_CheckError (page->error);
861 
862     attr->gmode = HPDF_GMODE_PAGE_DESCRIPTION;
863     attr->cur_pos = INIT_POS;
864 
865     return ret;
866 }
867 
868 /* b* */
869 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_ClosePathEofillStroke(HPDF_Page page)870 HPDF_Page_ClosePathEofillStroke  (HPDF_Page  page)
871 {
872     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PATH_OBJECT |
873             HPDF_GMODE_CLIPPING_PATH);
874     HPDF_PageAttr attr;
875 
876     HPDF_PTRACE ((" HPDF_Page_ClosePathEofillStroke\n"));
877 
878     if (ret != HPDF_OK)
879         return ret;
880 
881     attr = (HPDF_PageAttr)page->attr;
882 
883     if (HPDF_Stream_WriteStr (attr->stream, "b*\012") != HPDF_OK)
884         return HPDF_CheckError (page->error);
885 
886     attr->gmode = HPDF_GMODE_PAGE_DESCRIPTION;
887     attr->cur_pos = INIT_POS;
888 
889     return ret;
890 }
891 
892 /* n */
893 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_EndPath(HPDF_Page page)894 HPDF_Page_EndPath  (HPDF_Page  page)
895 {
896     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PATH_OBJECT |
897             HPDF_GMODE_CLIPPING_PATH);
898     HPDF_PageAttr attr;
899 
900     HPDF_PTRACE ((" HPDF_PageEndPath\n"));
901 
902     if (ret != HPDF_OK)
903         return ret;
904 
905     attr = (HPDF_PageAttr)page->attr;
906 
907     if (HPDF_Stream_WriteStr (attr->stream, "n\012") != HPDF_OK)
908         return HPDF_CheckError (page->error);
909 
910     attr->gmode = HPDF_GMODE_PAGE_DESCRIPTION;
911     attr->cur_pos = INIT_POS;
912 
913     return ret;
914 }
915 
916 
917 /*--- Clipping paths operator --------------------------------------------*/
918 
919 /* W */
920 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_Clip(HPDF_Page page)921 HPDF_Page_Clip  (HPDF_Page  page)
922 {
923     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PATH_OBJECT);
924     HPDF_PageAttr attr;
925 
926     HPDF_PTRACE ((" HPDF_Page_Clip\n"));
927 
928     if (ret != HPDF_OK)
929         return ret;
930 
931     attr = (HPDF_PageAttr)page->attr;
932 
933     if (HPDF_Stream_WriteStr (attr->stream, "W\012") != HPDF_OK)
934         return HPDF_CheckError (page->error);
935 
936     attr->gmode = HPDF_GMODE_CLIPPING_PATH;
937 
938     return ret;
939 }
940 
941 /* W* */
942 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_Eoclip(HPDF_Page page)943 HPDF_Page_Eoclip  (HPDF_Page  page)
944 {
945     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PATH_OBJECT);
946     HPDF_PageAttr attr;
947 
948     HPDF_PTRACE ((" HPDF_Page_Eoclip\n"));
949 
950     if (ret != HPDF_OK)
951         return ret;
952 
953     attr = (HPDF_PageAttr)page->attr;
954 
955     if (HPDF_Stream_WriteStr (attr->stream, "W*\012") != HPDF_OK)
956         return HPDF_CheckError (page->error);
957 
958     attr->gmode = HPDF_GMODE_CLIPPING_PATH;
959 
960     return ret;
961 }
962 
963 
964 /*--- Text object operator -----------------------------------------------*/
965 
966 /* BT */
967 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_BeginText(HPDF_Page page)968 HPDF_Page_BeginText  (HPDF_Page  page)
969 {
970     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PAGE_DESCRIPTION);
971     HPDF_PageAttr attr;
972     const HPDF_TransMatrix INIT_MATRIX = {1, 0, 0, 1, 0, 0};
973 
974     HPDF_PTRACE ((" HPDF_Page_BeginText\n"));
975 
976     if (ret != HPDF_OK)
977         return ret;
978 
979     attr = (HPDF_PageAttr)page->attr;
980 
981     if (HPDF_Stream_WriteStr (attr->stream, "BT\012") != HPDF_OK)
982         return HPDF_CheckError (page->error);
983 
984     attr->gmode = HPDF_GMODE_TEXT_OBJECT;
985     attr->text_pos = INIT_POS;
986     attr->text_matrix = INIT_MATRIX;
987 
988     return ret;
989 }
990 
991 /* ET */
992 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_EndText(HPDF_Page page)993 HPDF_Page_EndText  (HPDF_Page  page)
994 {
995     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_TEXT_OBJECT);
996     HPDF_PageAttr attr;
997 
998     HPDF_PTRACE ((" HPDF_Page_EndText\n"));
999 
1000     if (ret != HPDF_OK)
1001         return ret;
1002 
1003     attr = (HPDF_PageAttr)page->attr;
1004 
1005     if (HPDF_Stream_WriteStr (attr->stream, "ET\012") != HPDF_OK)
1006         return HPDF_CheckError (page->error);
1007 
1008     attr->text_pos = INIT_POS;
1009     attr->gmode = HPDF_GMODE_PAGE_DESCRIPTION;
1010 
1011     return ret;
1012 }
1013 
1014 /*--- Text state ---------------------------------------------------------*/
1015 
1016 /* Tc */
1017 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_SetCharSpace(HPDF_Page page,HPDF_REAL value)1018 HPDF_Page_SetCharSpace  (HPDF_Page  page,
1019                          HPDF_REAL  value)
1020 {
1021     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PAGE_DESCRIPTION |
1022                     HPDF_GMODE_TEXT_OBJECT);
1023     HPDF_PageAttr attr;
1024 
1025     HPDF_PTRACE ((" HPDF_Page_SetCharSpace\n"));
1026 
1027     if (ret != HPDF_OK)
1028         return ret;
1029 
1030     attr = (HPDF_PageAttr)page->attr;
1031 
1032     if (value < HPDF_MIN_CHARSPACE || value > HPDF_MAX_CHARSPACE)
1033         return HPDF_RaiseError (page->error, HPDF_PAGE_OUT_OF_RANGE, 0);
1034 
1035     if (HPDF_Stream_WriteReal (attr->stream, value) != HPDF_OK)
1036         return HPDF_CheckError (page->error);
1037 
1038     if (HPDF_Stream_WriteStr (attr->stream, " Tc\012") != HPDF_OK)
1039         return HPDF_CheckError (page->error);
1040 
1041     attr->gstate->char_space = value;
1042 
1043     return ret;
1044 }
1045 
1046 /* Tw */
1047 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_SetWordSpace(HPDF_Page page,HPDF_REAL value)1048 HPDF_Page_SetWordSpace  (HPDF_Page  page,
1049                          HPDF_REAL  value)
1050 {
1051     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PAGE_DESCRIPTION |
1052                     HPDF_GMODE_TEXT_OBJECT);
1053     HPDF_PageAttr attr;
1054 
1055     HPDF_PTRACE ((" HPDF_Page_SetWordSpace\n"));
1056 
1057     if (ret != HPDF_OK)
1058         return ret;
1059 
1060     attr = (HPDF_PageAttr)page->attr;
1061 
1062     if (value < HPDF_MIN_WORDSPACE || value > HPDF_MAX_WORDSPACE)
1063         return HPDF_RaiseError (page->error, HPDF_PAGE_OUT_OF_RANGE, 0);
1064 
1065     if (HPDF_Stream_WriteReal (attr->stream, value) != HPDF_OK)
1066         return HPDF_CheckError (page->error);
1067 
1068     if (HPDF_Stream_WriteStr (attr->stream, " Tw\012") != HPDF_OK)
1069         return HPDF_CheckError (page->error);
1070 
1071     attr->gstate->word_space = value;
1072 
1073     return ret;
1074 }
1075 
1076 /* Tz */
1077 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_SetHorizontalScalling(HPDF_Page page,HPDF_REAL value)1078 HPDF_Page_SetHorizontalScalling  (HPDF_Page  page,
1079                                   HPDF_REAL  value)
1080 {
1081     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PAGE_DESCRIPTION |
1082                     HPDF_GMODE_TEXT_OBJECT);
1083     HPDF_PageAttr attr;
1084 
1085     HPDF_PTRACE ((" HPDF_Page_SetHorizontalScalling\n"));
1086 
1087     if (ret != HPDF_OK)
1088         return ret;
1089 
1090     attr = (HPDF_PageAttr)page->attr;
1091 
1092     if (value < HPDF_MIN_HORIZONTALSCALING ||
1093             value > HPDF_MAX_HORIZONTALSCALING)
1094         return HPDF_RaiseError (page->error, HPDF_PAGE_OUT_OF_RANGE, 0);
1095 
1096     if (HPDF_Stream_WriteReal (attr->stream, value) != HPDF_OK)
1097         return HPDF_CheckError (page->error);
1098 
1099     if (HPDF_Stream_WriteStr (attr->stream, " Tz\012") != HPDF_OK)
1100         return HPDF_CheckError (page->error);
1101 
1102     attr->gstate->h_scalling = value;
1103 
1104     return ret;
1105 }
1106 
1107 /* TL */
1108 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_SetTextLeading(HPDF_Page page,HPDF_REAL value)1109 HPDF_Page_SetTextLeading  (HPDF_Page  page,
1110                            HPDF_REAL  value)
1111 {
1112     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PAGE_DESCRIPTION |
1113                     HPDF_GMODE_TEXT_OBJECT);
1114     HPDF_PageAttr attr;
1115 
1116     HPDF_PTRACE ((" HPDF_Page_SetTextLeading\n"));
1117 
1118     if (ret != HPDF_OK)
1119         return ret;
1120 
1121     attr = (HPDF_PageAttr)page->attr;
1122 
1123     if (HPDF_Stream_WriteReal (attr->stream, value) != HPDF_OK)
1124         return HPDF_CheckError (page->error);
1125 
1126     if (HPDF_Stream_WriteStr (attr->stream, " TL\012") != HPDF_OK)
1127         return HPDF_CheckError (page->error);
1128 
1129     attr->gstate->text_leading = value;
1130 
1131     return ret;
1132 }
1133 
1134 /* Tf */
1135 
1136 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_SetFontAndSize(HPDF_Page page,HPDF_Font font,HPDF_REAL size)1137 HPDF_Page_SetFontAndSize  (HPDF_Page  page,
1138                            HPDF_Font  font,
1139                            HPDF_REAL  size)
1140 {
1141     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PAGE_DESCRIPTION |
1142                     HPDF_GMODE_TEXT_OBJECT);
1143     char buf[HPDF_TMP_BUF_SIZ];
1144     char *pbuf = buf;
1145     char *eptr = buf + HPDF_TMP_BUF_SIZ - 1;
1146     const char *local_name;
1147     HPDF_PageAttr attr;
1148 
1149     HPDF_PTRACE ((" HPDF_Page_SetFontAndSize\n"));
1150 
1151     if (ret != HPDF_OK)
1152         return ret;
1153 
1154     if (!HPDF_Font_Validate (font))
1155         return HPDF_RaiseError (page->error, HPDF_PAGE_INVALID_FONT, 0);
1156 
1157     if (size <= 0 || size > HPDF_MAX_FONTSIZE)
1158         return HPDF_RaiseError (page->error, HPDF_PAGE_INVALID_FONT_SIZE, size);
1159 
1160     if (page->mmgr != font->mmgr)
1161         return HPDF_RaiseError (page->error, HPDF_PAGE_INVALID_FONT, 0);
1162 
1163     attr = (HPDF_PageAttr)page->attr;
1164     local_name = HPDF_Page_GetLocalFontName (page, font);
1165 
1166     if (!local_name)
1167         return HPDF_RaiseError (page->error, HPDF_PAGE_INVALID_FONT, 0);
1168 
1169     if (HPDF_Stream_WriteEscapeName (attr->stream, local_name) != HPDF_OK)
1170         return HPDF_CheckError (page->error);
1171 
1172     HPDF_MemSet (buf, 0, HPDF_TMP_BUF_SIZ);
1173     *pbuf++ = ' ';
1174     pbuf = HPDF_FToA (pbuf, size, eptr);
1175     HPDF_StrCpy (pbuf, " Tf\012", eptr);
1176 
1177     if (HPDF_Stream_WriteStr (attr->stream, buf) != HPDF_OK)
1178         return HPDF_CheckError (page->error);
1179 
1180     attr->gstate->font = font;
1181     attr->gstate->font_size = size;
1182     attr->gstate->writing_mode = ((HPDF_FontAttr)font->attr)->writing_mode;
1183 
1184     return ret;
1185 }
1186 
1187 /* Tr */
1188 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_SetTextRenderingMode(HPDF_Page page,HPDF_TextRenderingMode mode)1189 HPDF_Page_SetTextRenderingMode  (HPDF_Page               page,
1190                                  HPDF_TextRenderingMode  mode)
1191 {
1192     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PAGE_DESCRIPTION |
1193                     HPDF_GMODE_TEXT_OBJECT);
1194     HPDF_PageAttr attr;
1195 
1196     HPDF_PTRACE ((" HPDF_Page_SetTextRenderingMode\n"));
1197 
1198     if (ret != HPDF_OK)
1199         return ret;
1200 
1201     if (mode >= HPDF_RENDERING_MODE_EOF)
1202         return HPDF_RaiseError (page->error, HPDF_PAGE_OUT_OF_RANGE,
1203                 (HPDF_STATUS)mode);
1204 
1205     attr = (HPDF_PageAttr)page->attr;
1206 
1207     if (HPDF_Stream_WriteInt (attr->stream, (HPDF_INT)mode) != HPDF_OK)
1208         return HPDF_CheckError (page->error);
1209 
1210     if (HPDF_Stream_WriteStr (attr->stream, " Tr\012") != HPDF_OK)
1211         return HPDF_CheckError (page->error);
1212 
1213     attr->gstate->rendering_mode = mode;
1214 
1215     return ret;
1216 }
1217 
1218 /* Ts */
1219 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_SetTextRaise(HPDF_Page page,HPDF_REAL value)1220 HPDF_Page_SetTextRaise  (HPDF_Page  page,
1221                          HPDF_REAL  value)
1222 {
1223     return HPDF_Page_SetTextRise (page, value);
1224 }
1225 
1226 
1227 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_SetTextRise(HPDF_Page page,HPDF_REAL value)1228 HPDF_Page_SetTextRise  (HPDF_Page  page,
1229                         HPDF_REAL  value)
1230 {
1231     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PAGE_DESCRIPTION |
1232                     HPDF_GMODE_TEXT_OBJECT);
1233     HPDF_PageAttr attr;
1234 
1235     HPDF_PTRACE ((" HPDF_Page_SetTextRaise\n"));
1236 
1237     if (ret != HPDF_OK)
1238         return ret;
1239 
1240     attr = (HPDF_PageAttr)page->attr;
1241 
1242     if (HPDF_Stream_WriteReal (attr->stream, value) != HPDF_OK)
1243         return HPDF_CheckError (page->error);
1244 
1245     if (HPDF_Stream_WriteStr (attr->stream, " Ts\012") != HPDF_OK)
1246         return HPDF_CheckError (page->error);
1247 
1248     attr->gstate->text_rise = value;
1249 
1250     return ret;
1251 }
1252 
1253 /*--- Text positioning ---------------------------------------------------*/
1254 
1255 /* Td */
1256 
1257 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_MoveTextPos(HPDF_Page page,HPDF_REAL x,HPDF_REAL y)1258 HPDF_Page_MoveTextPos  (HPDF_Page  page,
1259                         HPDF_REAL  x,
1260                         HPDF_REAL  y)
1261 {
1262     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_TEXT_OBJECT);
1263     char buf[HPDF_TMP_BUF_SIZ];
1264     char *pbuf = buf;
1265     char *eptr = buf + HPDF_TMP_BUF_SIZ - 1;
1266     HPDF_PageAttr attr;
1267 
1268     HPDF_PTRACE ((" HPDF_Page_MoveTextPos\n"));
1269 
1270     if (ret != HPDF_OK)
1271         return ret;
1272 
1273     attr = (HPDF_PageAttr)page->attr;
1274 
1275     HPDF_MemSet (buf, 0, HPDF_TMP_BUF_SIZ);
1276 
1277     pbuf = HPDF_FToA (pbuf, x, eptr);
1278     *pbuf++ = ' ';
1279     pbuf = HPDF_FToA (pbuf, y, eptr);
1280     HPDF_StrCpy (pbuf, " Td\012", eptr);
1281 
1282     if (HPDF_Stream_WriteStr (attr->stream, buf) != HPDF_OK)
1283         return HPDF_CheckError (page->error);
1284 
1285     attr->text_matrix.x += x * attr->text_matrix.a + y * attr->text_matrix.c;
1286     attr->text_matrix.y += y * attr->text_matrix.d + x * attr->text_matrix.b;
1287     attr->text_pos.x = attr->text_matrix.x;
1288     attr->text_pos.y = attr->text_matrix.y;
1289 
1290     return ret;
1291 }
1292 
1293 /* TD */
1294 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_MoveTextPos2(HPDF_Page page,HPDF_REAL x,HPDF_REAL y)1295 HPDF_Page_MoveTextPos2  (HPDF_Page  page,
1296                          HPDF_REAL  x,
1297                          HPDF_REAL  y)
1298 {
1299     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_TEXT_OBJECT);
1300     char buf[HPDF_TMP_BUF_SIZ];
1301     char *pbuf = buf;
1302     char *eptr = buf + HPDF_TMP_BUF_SIZ - 1;
1303     HPDF_PageAttr attr;
1304 
1305     HPDF_PTRACE ((" HPDF_Page_MoveTextPos2\n"));
1306 
1307     if (ret != HPDF_OK)
1308         return ret;
1309 
1310     attr = (HPDF_PageAttr)page->attr;
1311 
1312     HPDF_MemSet (buf, 0, HPDF_TMP_BUF_SIZ);
1313 
1314     pbuf = HPDF_FToA (pbuf, x, eptr);
1315     *pbuf++ = ' ';
1316     pbuf = HPDF_FToA (pbuf, y, eptr);
1317     HPDF_StrCpy (pbuf, " TD\012", eptr);
1318 
1319     if (HPDF_Stream_WriteStr (attr->stream, buf) != HPDF_OK)
1320         return HPDF_CheckError (page->error);
1321 
1322     attr->text_matrix.x += x * attr->text_matrix.a + y * attr->text_matrix.c;
1323     attr->text_matrix.y += y * attr->text_matrix.d + x * attr->text_matrix.b;
1324     attr->text_pos.x = attr->text_matrix.x;
1325     attr->text_pos.y = attr->text_matrix.y;
1326     attr->gstate->text_leading = -y;
1327 
1328     return ret;
1329 }
1330 
1331 /* Tm */
1332 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_SetTextMatrix(HPDF_Page page,HPDF_REAL a,HPDF_REAL b,HPDF_REAL c,HPDF_REAL d,HPDF_REAL x,HPDF_REAL y)1333 HPDF_Page_SetTextMatrix  (HPDF_Page         page,
1334                           HPDF_REAL    a,
1335                           HPDF_REAL    b,
1336                           HPDF_REAL    c,
1337                           HPDF_REAL    d,
1338                           HPDF_REAL    x,
1339                           HPDF_REAL    y)
1340 {
1341     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_TEXT_OBJECT);
1342     char buf[HPDF_TMP_BUF_SIZ];
1343     char *pbuf = buf;
1344     char *eptr = buf + HPDF_TMP_BUF_SIZ - 1;
1345     HPDF_PageAttr attr;
1346 
1347     HPDF_PTRACE ((" HPDF_Page_SetTextMatrix\n"));
1348 
1349     if (ret != HPDF_OK)
1350         return ret;
1351 
1352     attr = (HPDF_PageAttr)page->attr;
1353 
1354     if ((a == 0 || d == 0) && (b == 0 || c == 0))
1355         return HPDF_RaiseError (page->error, HPDF_INVALID_PARAMETER, 0);
1356 
1357     HPDF_MemSet (buf, 0, HPDF_TMP_BUF_SIZ);
1358 
1359     pbuf = HPDF_FToA (pbuf, a, eptr);
1360     *pbuf++ = ' ';
1361     pbuf = HPDF_FToA (pbuf, b, eptr);
1362     *pbuf++ = ' ';
1363     pbuf = HPDF_FToA (pbuf, c, eptr);
1364     *pbuf++ = ' ';
1365     pbuf = HPDF_FToA (pbuf, d, eptr);
1366     *pbuf++ = ' ';
1367     pbuf = HPDF_FToA (pbuf, x, eptr);
1368     *pbuf++ = ' ';
1369     pbuf = HPDF_FToA (pbuf, y, eptr);
1370     HPDF_StrCpy (pbuf, " Tm\012", eptr);
1371 
1372     if (HPDF_Stream_WriteStr (attr->stream, buf) != HPDF_OK)
1373         return HPDF_CheckError (page->error);
1374 
1375     attr->text_matrix.a = a;
1376     attr->text_matrix.b = b;
1377     attr->text_matrix.c = c;
1378     attr->text_matrix.d = d;
1379     attr->text_matrix.x = x;
1380     attr->text_matrix.y = y;
1381     attr->text_pos.x = attr->text_matrix.x;
1382     attr->text_pos.y = attr->text_matrix.y;
1383 
1384     return ret;
1385 }
1386 
1387 
1388 /* T* */
1389 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_MoveToNextLine(HPDF_Page page)1390 HPDF_Page_MoveToNextLine  (HPDF_Page  page)
1391 {
1392     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_TEXT_OBJECT);
1393     HPDF_PageAttr attr;
1394 
1395     HPDF_PTRACE ((" HPDF_Page_MoveToNextLine\n"));
1396 
1397     if (ret != HPDF_OK)
1398         return ret;
1399 
1400     attr = (HPDF_PageAttr)page->attr;
1401 
1402     if (HPDF_Stream_WriteStr (attr->stream, "T*\012") != HPDF_OK)
1403         return HPDF_CheckError (page->error);
1404 
1405     /* calculate the reference point of text */
1406     attr->text_matrix.x -= attr->gstate->text_leading * attr->text_matrix.c;
1407     attr->text_matrix.y -= attr->gstate->text_leading * attr->text_matrix.d;
1408 
1409     attr->text_pos.x = attr->text_matrix.x;
1410     attr->text_pos.y = attr->text_matrix.y;
1411 
1412     return ret;
1413 }
1414 
1415 /*--- Text showing -------------------------------------------------------*/
1416 
1417 /* Tj */
1418 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_ShowText(HPDF_Page page,const char * text)1419 HPDF_Page_ShowText  (HPDF_Page    page,
1420                      const char  *text)
1421 {
1422     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_TEXT_OBJECT);
1423     HPDF_PageAttr attr;
1424     HPDF_REAL tw;
1425 
1426     HPDF_PTRACE ((" HPDF_Page_ShowText\n"));
1427 
1428     if (ret != HPDF_OK || text == NULL || text[0] == 0)
1429         return ret;
1430 
1431     attr = (HPDF_PageAttr)page->attr;
1432 
1433     /* no font exists */
1434     if (!attr->gstate->font)
1435         return HPDF_RaiseError (page->error, HPDF_PAGE_FONT_NOT_FOUND, 0);
1436 
1437     tw = HPDF_Page_TextWidth (page, text);
1438     if (!tw)
1439         return ret;
1440 
1441     if (InternalWriteText (attr, text) != HPDF_OK)
1442         return HPDF_CheckError (page->error);
1443 
1444     if (HPDF_Stream_WriteStr (attr->stream, " Tj\012") != HPDF_OK)
1445         return HPDF_CheckError (page->error);
1446 
1447     /* calculate the reference point of text */
1448     if (attr->gstate->writing_mode == HPDF_WMODE_HORIZONTAL) {
1449         attr->text_pos.x += tw * attr->text_matrix.a;
1450         attr->text_pos.y += tw * attr->text_matrix.b;
1451     } else {
1452         attr->text_pos.x -= tw * attr->text_matrix.b;
1453         attr->text_pos.y -= tw * attr->text_matrix.a;
1454     }
1455 
1456     return ret;
1457 }
1458 
1459 /* TJ */
1460 /* ' */
1461 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_ShowTextNextLine(HPDF_Page page,const char * text)1462 HPDF_Page_ShowTextNextLine  (HPDF_Page    page,
1463                              const char  *text)
1464 {
1465     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_TEXT_OBJECT);
1466     HPDF_PageAttr attr;
1467     HPDF_REAL tw;
1468 
1469     HPDF_PTRACE ((" HPDF_Page_ShowTextNextLine\n"));
1470 
1471     if (ret != HPDF_OK)
1472         return ret;
1473 
1474     attr = (HPDF_PageAttr)page->attr;
1475 
1476     /* no font exists */
1477     if (!attr->gstate->font)
1478         return HPDF_RaiseError (page->error, HPDF_PAGE_FONT_NOT_FOUND, 0);
1479 
1480     if (text == NULL || text[0] == 0)
1481         return HPDF_Page_MoveToNextLine(page);
1482 
1483     if (InternalWriteText (attr, text) != HPDF_OK)
1484         return HPDF_CheckError (page->error);
1485 
1486     if (HPDF_Stream_WriteStr (attr->stream, " \'\012") != HPDF_OK)
1487         return HPDF_CheckError (page->error);
1488 
1489     tw = HPDF_Page_TextWidth (page, text);
1490 
1491     /* calculate the reference point of text */
1492     attr->text_matrix.x -= attr->gstate->text_leading * attr->text_matrix.c;
1493     attr->text_matrix.y -= attr->gstate->text_leading * attr->text_matrix.d;
1494 
1495     attr->text_pos.x = attr->text_matrix.x;
1496     attr->text_pos.y = attr->text_matrix.y;
1497 
1498     if (attr->gstate->writing_mode == HPDF_WMODE_HORIZONTAL) {
1499         attr->text_pos.x += tw * attr->text_matrix.a;
1500         attr->text_pos.y += tw * attr->text_matrix.b;
1501     } else {
1502         attr->text_pos.x -= tw * attr->text_matrix.b;
1503         attr->text_pos.y -= tw * attr->text_matrix.a;
1504     }
1505 
1506     return ret;
1507 }
1508 
1509 /* " */
1510 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_ShowTextNextLineEx(HPDF_Page page,HPDF_REAL word_space,HPDF_REAL char_space,const char * text)1511 HPDF_Page_ShowTextNextLineEx  (HPDF_Page    page,
1512                                HPDF_REAL    word_space,
1513                                HPDF_REAL    char_space,
1514                                const char  *text)
1515 {
1516     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_TEXT_OBJECT);
1517     HPDF_PageAttr attr;
1518     HPDF_REAL tw;
1519     char buf[HPDF_TMP_BUF_SIZ];
1520     char *pbuf = buf;
1521     char *eptr = buf + HPDF_TMP_BUF_SIZ - 1;
1522 
1523     HPDF_PTRACE ((" HPDF_Page_ShowTextNextLineEX\n"));
1524 
1525     if (ret != HPDF_OK)
1526         return ret;
1527 
1528     if (word_space < HPDF_MIN_WORDSPACE || word_space > HPDF_MAX_WORDSPACE)
1529         return HPDF_RaiseError (page->error, HPDF_PAGE_OUT_OF_RANGE, 0);
1530 
1531     if (char_space < HPDF_MIN_CHARSPACE || char_space > HPDF_MAX_CHARSPACE)
1532         return HPDF_RaiseError (page->error, HPDF_PAGE_OUT_OF_RANGE, 0);
1533 
1534     attr = (HPDF_PageAttr)page->attr;
1535 
1536     /* no font exists */
1537     if (!attr->gstate->font)
1538         return HPDF_RaiseError (page->error, HPDF_PAGE_FONT_NOT_FOUND, 0);
1539 
1540     if (text == NULL || text[0] == 0)
1541         return HPDF_Page_MoveToNextLine(page);
1542 
1543     HPDF_MemSet (buf, 0, HPDF_TMP_BUF_SIZ);
1544     pbuf = HPDF_FToA (pbuf, word_space, eptr);
1545     *pbuf++ = ' ';
1546     pbuf = HPDF_FToA (pbuf, char_space, eptr);
1547     *pbuf = ' ';
1548 
1549     if (InternalWriteText (attr, buf) != HPDF_OK)
1550         return HPDF_CheckError (page->error);
1551 
1552     if (InternalWriteText (attr, text) != HPDF_OK)
1553         return HPDF_CheckError (page->error);
1554 
1555     if (HPDF_Stream_WriteStr (attr->stream, " \"\012") != HPDF_OK)
1556         return HPDF_CheckError (page->error);
1557 
1558     attr->gstate->word_space = word_space;
1559     attr->gstate->char_space = char_space;
1560 
1561     tw = HPDF_Page_TextWidth (page, text);
1562 
1563     /* calculate the reference point of text */
1564     attr->text_matrix.x += attr->gstate->text_leading * attr->text_matrix.b;
1565     attr->text_matrix.y -= attr->gstate->text_leading * attr->text_matrix.a;
1566 
1567     attr->text_pos.x = attr->text_matrix.x;
1568     attr->text_pos.y = attr->text_matrix.y;
1569 
1570     if (attr->gstate->writing_mode == HPDF_WMODE_HORIZONTAL) {
1571         attr->text_pos.x += tw * attr->text_matrix.a;
1572         attr->text_pos.y += tw * attr->text_matrix.b;
1573     } else {
1574         attr->text_pos.x -= tw * attr->text_matrix.b;
1575         attr->text_pos.y -= tw * attr->text_matrix.a;
1576     }
1577 
1578     return ret;
1579 }
1580 
1581 
1582 /*--- Color showing ------------------------------------------------------*/
1583 
1584 /* cs --not implemented yet */
1585 /* CS --not implemented yet */
1586 /* sc --not implemented yet */
1587 /* scn --not implemented yet */
1588 /* SC --not implemented yet */
1589 /* SCN --not implemented yet */
1590 
1591 /* g */
1592 
1593 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_SetGrayFill(HPDF_Page page,HPDF_REAL gray)1594 HPDF_Page_SetGrayFill  (HPDF_Page  page,
1595                         HPDF_REAL  gray)
1596 {
1597     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PAGE_DESCRIPTION |
1598                     HPDF_GMODE_TEXT_OBJECT);
1599     HPDF_PageAttr attr;
1600 
1601     HPDF_PTRACE ((" HPDF_Page_SetGrayFill\n"));
1602 
1603     if (ret != HPDF_OK)
1604         return ret;
1605 
1606     attr = (HPDF_PageAttr)page->attr;
1607 
1608     if (gray < 0 || gray > 1)
1609         return HPDF_RaiseError (page->error, HPDF_PAGE_OUT_OF_RANGE, 0);
1610 
1611     if (HPDF_Stream_WriteReal (attr->stream, gray) != HPDF_OK)
1612         return HPDF_CheckError (page->error);
1613 
1614     if (HPDF_Stream_WriteStr (attr->stream, " g\012") != HPDF_OK)
1615         return HPDF_CheckError (page->error);
1616 
1617     attr->gstate->gray_fill = gray;
1618     attr->gstate->cs_fill = HPDF_CS_DEVICE_GRAY;
1619 
1620     return ret;
1621 }
1622 
1623 /* G */
1624 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_SetGrayStroke(HPDF_Page page,HPDF_REAL gray)1625 HPDF_Page_SetGrayStroke  (HPDF_Page  page,
1626                           HPDF_REAL  gray)
1627 {
1628     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PAGE_DESCRIPTION |
1629                     HPDF_GMODE_TEXT_OBJECT);
1630     HPDF_PageAttr attr;
1631 
1632     HPDF_PTRACE ((" HPDF_Page_SetGrayStroke\n"));
1633 
1634     if (ret != HPDF_OK)
1635         return ret;
1636 
1637     attr = (HPDF_PageAttr)page->attr;
1638 
1639     if (gray < 0 || gray > 1)
1640         return HPDF_RaiseError (page->error, HPDF_PAGE_OUT_OF_RANGE, 0);
1641 
1642     if (HPDF_Stream_WriteReal (attr->stream, gray) != HPDF_OK)
1643         return HPDF_CheckError (page->error);
1644 
1645     if (HPDF_Stream_WriteStr (attr->stream, " G\012") != HPDF_OK)
1646         return HPDF_CheckError (page->error);
1647 
1648     attr->gstate->gray_stroke = gray;
1649     attr->gstate->cs_stroke = HPDF_CS_DEVICE_GRAY;
1650 
1651     return ret;
1652 }
1653 
1654 /* rg */
1655 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_SetRGBFill(HPDF_Page page,HPDF_REAL r,HPDF_REAL g,HPDF_REAL b)1656 HPDF_Page_SetRGBFill  (HPDF_Page  page,
1657                        HPDF_REAL  r,
1658                        HPDF_REAL  g,
1659                        HPDF_REAL  b)
1660 {
1661     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_TEXT_OBJECT |
1662                     HPDF_GMODE_PAGE_DESCRIPTION);
1663     char buf[HPDF_TMP_BUF_SIZ];
1664     char *pbuf = buf;
1665     char *eptr = buf + HPDF_TMP_BUF_SIZ - 1;
1666     HPDF_PageAttr attr;
1667 
1668     HPDF_PTRACE ((" HPDF_Page_SetRGBFill\n"));
1669 
1670     if (ret != HPDF_OK)
1671         return ret;
1672 
1673     if (r < 0 || r > 1 || g < 0 || g > 1 || b < 0 || b > 1)
1674         return HPDF_RaiseError (page->error, HPDF_PAGE_OUT_OF_RANGE, 0);
1675 
1676     attr = (HPDF_PageAttr)page->attr;
1677 
1678     HPDF_MemSet (buf, 0, HPDF_TMP_BUF_SIZ);
1679 
1680     pbuf = HPDF_FToA (pbuf, r, eptr);
1681     *pbuf++ = ' ';
1682     pbuf = HPDF_FToA (pbuf, g, eptr);
1683     *pbuf++ = ' ';
1684     pbuf = HPDF_FToA (pbuf, b, eptr);
1685     HPDF_StrCpy (pbuf, " rg\012", eptr);
1686 
1687     if (HPDF_Stream_WriteStr (attr->stream, buf) != HPDF_OK)
1688         return HPDF_CheckError (page->error);
1689 
1690     attr->gstate->rgb_fill.r = r;
1691     attr->gstate->rgb_fill.g = g;
1692     attr->gstate->rgb_fill.b = b;
1693     attr->gstate->cs_fill = HPDF_CS_DEVICE_RGB;
1694 
1695     return ret;
1696 }
1697 
1698 /* RG */
1699 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_SetRGBStroke(HPDF_Page page,HPDF_REAL r,HPDF_REAL g,HPDF_REAL b)1700 HPDF_Page_SetRGBStroke  (HPDF_Page  page,
1701                          HPDF_REAL  r,
1702                          HPDF_REAL  g,
1703                          HPDF_REAL  b)
1704 {
1705     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_TEXT_OBJECT |
1706                     HPDF_GMODE_PAGE_DESCRIPTION);
1707     char buf[HPDF_TMP_BUF_SIZ];
1708     char *pbuf = buf;
1709     char *eptr = buf + HPDF_TMP_BUF_SIZ - 1;
1710     HPDF_PageAttr attr;
1711 
1712     HPDF_PTRACE ((" HPDF_Page_SetRGBStroke\n"));
1713 
1714     if (ret != HPDF_OK)
1715         return ret;
1716 
1717     if (r < 0 || r > 1 || g < 0 || g > 1 || b < 0 || b > 1)
1718         return HPDF_RaiseError (page->error, HPDF_PAGE_OUT_OF_RANGE, 0);
1719 
1720     attr = (HPDF_PageAttr)page->attr;
1721 
1722     HPDF_MemSet (buf, 0, HPDF_TMP_BUF_SIZ);
1723 
1724     pbuf = HPDF_FToA (pbuf, r, eptr);
1725     *pbuf++ = ' ';
1726     pbuf = HPDF_FToA (pbuf, g, eptr);
1727     *pbuf++ = ' ';
1728     pbuf = HPDF_FToA (pbuf, b, eptr);
1729     HPDF_StrCpy (pbuf, " RG\012", eptr);
1730 
1731     if (HPDF_Stream_WriteStr (attr->stream, buf) != HPDF_OK)
1732         return HPDF_CheckError (page->error);
1733 
1734     attr->gstate->rgb_stroke.r = r;
1735     attr->gstate->rgb_stroke.g = g;
1736     attr->gstate->rgb_stroke.b = b;
1737     attr->gstate->cs_stroke = HPDF_CS_DEVICE_RGB;
1738 
1739     return ret;
1740 }
1741 
1742 /* k */
1743 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_SetCMYKFill(HPDF_Page page,HPDF_REAL c,HPDF_REAL m,HPDF_REAL y,HPDF_REAL k)1744 HPDF_Page_SetCMYKFill  (HPDF_Page  page,
1745                         HPDF_REAL  c,
1746                         HPDF_REAL  m,
1747                         HPDF_REAL  y,
1748                         HPDF_REAL  k)
1749 {
1750     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_TEXT_OBJECT |
1751                     HPDF_GMODE_PAGE_DESCRIPTION);
1752     char buf[HPDF_TMP_BUF_SIZ];
1753     char *pbuf = buf;
1754     char *eptr = buf + HPDF_TMP_BUF_SIZ - 1;
1755     HPDF_PageAttr attr;
1756 
1757     HPDF_PTRACE ((" HPDF_Page_SetCMYKFill\n"));
1758 
1759     if (ret != HPDF_OK)
1760         return ret;
1761 
1762     if (c < 0 || c > 1 || m < 0 || m > 1 || y < 0 || y > 1 || k < 0 || k > 1)
1763         return HPDF_RaiseError (page->error, HPDF_PAGE_OUT_OF_RANGE, 0);
1764 
1765     attr = (HPDF_PageAttr)page->attr;
1766 
1767     HPDF_MemSet (buf, 0, HPDF_TMP_BUF_SIZ);
1768 
1769     pbuf = HPDF_FToA (pbuf, c, eptr);
1770     *pbuf++ = ' ';
1771     pbuf = HPDF_FToA (pbuf, m, eptr);
1772     *pbuf++ = ' ';
1773     pbuf = HPDF_FToA (pbuf, y, eptr);
1774     *pbuf++ = ' ';
1775     pbuf = HPDF_FToA (pbuf, k, eptr);
1776     HPDF_StrCpy (pbuf, " k\012", eptr);
1777 
1778     if (HPDF_Stream_WriteStr (attr->stream, buf) != HPDF_OK)
1779         return HPDF_CheckError (page->error);
1780 
1781     attr->gstate->cmyk_fill.c = c;
1782     attr->gstate->cmyk_fill.m = m;
1783     attr->gstate->cmyk_fill.y = y;
1784     attr->gstate->cmyk_fill.k = k;
1785     attr->gstate->cs_fill = HPDF_CS_DEVICE_CMYK;
1786 
1787     return ret;
1788 }
1789 
1790 /* K */
1791 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_SetCMYKStroke(HPDF_Page page,HPDF_REAL c,HPDF_REAL m,HPDF_REAL y,HPDF_REAL k)1792 HPDF_Page_SetCMYKStroke  (HPDF_Page  page,
1793                           HPDF_REAL  c,
1794                           HPDF_REAL  m,
1795                           HPDF_REAL  y,
1796                           HPDF_REAL  k)
1797 {
1798     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_TEXT_OBJECT |
1799                     HPDF_GMODE_PAGE_DESCRIPTION);
1800     char buf[HPDF_TMP_BUF_SIZ];
1801     char *pbuf = buf;
1802     char *eptr = buf + HPDF_TMP_BUF_SIZ - 1;
1803     HPDF_PageAttr attr;
1804 
1805     HPDF_PTRACE ((" HPDF_Page_SetCMYKStroke\n"));
1806 
1807     if (ret != HPDF_OK)
1808         return ret;
1809 
1810     if (c < 0 || c > 1 || m < 0 || m > 1 || y < 0 || y > 1 || k < 0 || k > 1)
1811         return HPDF_RaiseError (page->error, HPDF_PAGE_OUT_OF_RANGE, 0);
1812 
1813     attr = (HPDF_PageAttr)page->attr;
1814 
1815     HPDF_MemSet (buf, 0, HPDF_TMP_BUF_SIZ);
1816 
1817     pbuf = HPDF_FToA (pbuf, c, eptr);
1818     *pbuf++ = ' ';
1819     pbuf = HPDF_FToA (pbuf, m, eptr);
1820     *pbuf++ = ' ';
1821     pbuf = HPDF_FToA (pbuf, y, eptr);
1822     *pbuf++ = ' ';
1823     pbuf = HPDF_FToA (pbuf, k, eptr);
1824     HPDF_StrCpy (pbuf, " K\012", eptr);
1825 
1826     if (HPDF_Stream_WriteStr (attr->stream, buf) != HPDF_OK)
1827         return HPDF_CheckError (page->error);
1828 
1829     attr->gstate->cmyk_stroke.c = c;
1830     attr->gstate->cmyk_stroke.m = m;
1831     attr->gstate->cmyk_stroke.y = y;
1832     attr->gstate->cmyk_stroke.k = k;
1833     attr->gstate->cs_stroke = HPDF_CS_DEVICE_CMYK;
1834 
1835     return ret;
1836 }
1837 
1838 /*--- Shading patterns ---------------------------------------------------*/
1839 
1840 /* sh --not implemented yet */
1841 
1842 /*--- In-line images -----------------------------------------------------*/
1843 
1844 /* BI --not implemented yet */
1845 /* ID --not implemented yet */
1846 /* EI --not implemented yet */
1847 
1848 /*--- XObjects -----------------------------------------------------------*/
1849 
1850 /* Do */
1851 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_ExecuteXObject(HPDF_Page page,HPDF_XObject obj)1852 HPDF_Page_ExecuteXObject  (HPDF_Page     page,
1853                            HPDF_XObject  obj)
1854 {
1855     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PAGE_DESCRIPTION);
1856     HPDF_PageAttr attr;
1857     const char *local_name;
1858 
1859     HPDF_PTRACE ((" HPDF_Page_ExecuteXObject\n"));
1860 
1861     if (ret != HPDF_OK)
1862         return ret;
1863 
1864     if (!obj || obj->header.obj_class != (HPDF_OSUBCLASS_XOBJECT |
1865             HPDF_OCLASS_DICT))
1866         return HPDF_RaiseError (page->error, HPDF_INVALID_OBJECT, 0);
1867 
1868     if (page->mmgr != obj->mmgr)
1869         return HPDF_RaiseError (page->error, HPDF_PAGE_INVALID_XOBJECT, 0);
1870 
1871     attr = (HPDF_PageAttr)page->attr;
1872     local_name = HPDF_Page_GetXObjectName (page, obj);
1873 
1874     if (!local_name)
1875         return HPDF_RaiseError (page->error, HPDF_PAGE_INVALID_XOBJECT, 0);
1876 
1877     if (HPDF_Stream_WriteEscapeName (attr->stream, local_name) != HPDF_OK)
1878         return HPDF_CheckError (page->error);
1879 
1880     if (HPDF_Stream_WriteStr (attr->stream, " Do\012") != HPDF_OK)
1881         return HPDF_CheckError (page->error);
1882 
1883     return ret;
1884 }
1885 
1886 /*--- Marked content -----------------------------------------------------*/
1887 
1888 /* BMC --not implemented yet */
1889 /* BDC --not implemented yet */
1890 /* EMC --not implemented yet */
1891 /* MP --not implemented yet */
1892 /* DP --not implemented yet */
1893 
1894 /*--- Compatibility ------------------------------------------------------*/
1895 
1896 /* BX --not implemented yet */
1897 /* EX --not implemented yet */
1898 
1899 
1900 /*--- combined function --------------------------------------------------*/
1901 
1902 static const HPDF_REAL KAPPA = 0.552F;
1903 
1904 static char*
QuarterCircleA(char * pbuf,char * eptr,HPDF_REAL x,HPDF_REAL y,HPDF_REAL ray)1905 QuarterCircleA  (char   *pbuf,
1906                  char   *eptr,
1907                  HPDF_REAL    x,
1908                  HPDF_REAL    y,
1909                  HPDF_REAL    ray)
1910 {
1911     pbuf = HPDF_FToA (pbuf, x -ray, eptr);
1912     *pbuf++ = ' ';
1913     pbuf = HPDF_FToA (pbuf, y + ray * KAPPA, eptr);
1914     *pbuf++ = ' ';
1915     pbuf = HPDF_FToA (pbuf, x -ray * KAPPA, eptr);
1916     *pbuf++ = ' ';
1917     pbuf = HPDF_FToA (pbuf, y + ray, eptr);
1918     *pbuf++ = ' ';
1919     pbuf = HPDF_FToA (pbuf, x, eptr);
1920     *pbuf++ = ' ';
1921     pbuf = HPDF_FToA (pbuf, y + ray, eptr);
1922     return (char *)HPDF_StrCpy (pbuf, " c\012", eptr);
1923 }
1924 
1925 static char*
QuarterCircleB(char * pbuf,char * eptr,HPDF_REAL x,HPDF_REAL y,HPDF_REAL ray)1926 QuarterCircleB  (char   *pbuf,
1927                  char   *eptr,
1928                  HPDF_REAL    x,
1929                  HPDF_REAL    y,
1930                  HPDF_REAL    ray)
1931 {
1932     pbuf = HPDF_FToA (pbuf, x + ray * KAPPA, eptr);
1933     *pbuf++ = ' ';
1934     pbuf = HPDF_FToA (pbuf, y + ray, eptr);
1935     *pbuf++ = ' ';
1936     pbuf = HPDF_FToA (pbuf, x + ray, eptr);
1937     *pbuf++ = ' ';
1938     pbuf = HPDF_FToA (pbuf, y + ray * KAPPA, eptr);
1939     *pbuf++ = ' ';
1940     pbuf = HPDF_FToA (pbuf, x + ray, eptr);
1941     *pbuf++ = ' ';
1942     pbuf = HPDF_FToA (pbuf, y, eptr);
1943     return (char *)HPDF_StrCpy (pbuf, " c\012", eptr);
1944 }
1945 
1946 static char*
QuarterCircleC(char * pbuf,char * eptr,HPDF_REAL x,HPDF_REAL y,HPDF_REAL ray)1947 QuarterCircleC  (char   *pbuf,
1948                  char   *eptr,
1949                  HPDF_REAL    x,
1950                  HPDF_REAL    y,
1951                  HPDF_REAL    ray)
1952 {
1953     pbuf = HPDF_FToA (pbuf, x + ray, eptr);
1954     *pbuf++ = ' ';
1955     pbuf = HPDF_FToA (pbuf, y - ray * KAPPA, eptr);
1956     *pbuf++ = ' ';
1957     pbuf = HPDF_FToA (pbuf, x + ray * KAPPA, eptr);
1958     *pbuf++ = ' ';
1959     pbuf = HPDF_FToA (pbuf, y - ray, eptr);
1960     *pbuf++ = ' ';
1961     pbuf = HPDF_FToA (pbuf, x, eptr);
1962     *pbuf++ = ' ';
1963     pbuf = HPDF_FToA (pbuf, y - ray, eptr);
1964     return (char *)HPDF_StrCpy (pbuf, " c\012", eptr);
1965 }
1966 
1967 static char*
QuarterCircleD(char * pbuf,char * eptr,HPDF_REAL x,HPDF_REAL y,HPDF_REAL ray)1968 QuarterCircleD  (char   *pbuf,
1969                  char   *eptr,
1970                  HPDF_REAL    x,
1971                  HPDF_REAL    y,
1972                  HPDF_REAL    ray)
1973 {
1974     pbuf = HPDF_FToA (pbuf, x - ray * KAPPA, eptr);
1975     *pbuf++ = ' ';
1976     pbuf = HPDF_FToA (pbuf, y - ray, eptr);
1977     *pbuf++ = ' ';
1978     pbuf = HPDF_FToA (pbuf, x - ray, eptr);
1979     *pbuf++ = ' ';
1980     pbuf = HPDF_FToA (pbuf, y - ray * KAPPA, eptr);
1981     *pbuf++ = ' ';
1982     pbuf = HPDF_FToA (pbuf, x - ray, eptr);
1983     *pbuf++ = ' ';
1984     pbuf = HPDF_FToA (pbuf, y, eptr);
1985     return (char *)HPDF_StrCpy (pbuf, " c\012", eptr);
1986 }
1987 
1988 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_Circle(HPDF_Page page,HPDF_REAL x,HPDF_REAL y,HPDF_REAL ray)1989 HPDF_Page_Circle  (HPDF_Page     page,
1990                    HPDF_REAL     x,
1991                    HPDF_REAL     y,
1992                    HPDF_REAL     ray)
1993 {
1994     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PAGE_DESCRIPTION |
1995             HPDF_GMODE_PATH_OBJECT);
1996     char buf[HPDF_TMP_BUF_SIZ * 2];
1997     char *pbuf = buf;
1998     char *eptr = buf + HPDF_TMP_BUF_SIZ - 1;
1999     HPDF_PageAttr attr;
2000 
2001     HPDF_PTRACE ((" HPDF_Page_Circle\n"));
2002 
2003     if (ret != HPDF_OK)
2004         return ret;
2005 
2006     attr = (HPDF_PageAttr)page->attr;
2007 
2008     HPDF_MemSet (buf, 0, HPDF_TMP_BUF_SIZ);
2009 
2010     pbuf = HPDF_FToA (pbuf, x - ray, eptr);
2011     *pbuf++ = ' ';
2012     pbuf = HPDF_FToA (pbuf, y, eptr);
2013     pbuf = (char *)HPDF_StrCpy (pbuf, " m\012", eptr);
2014 
2015     pbuf = QuarterCircleA (pbuf, eptr, x, y, ray);
2016     pbuf = QuarterCircleB (pbuf, eptr, x, y, ray);
2017     pbuf = QuarterCircleC (pbuf, eptr, x, y, ray);
2018     QuarterCircleD (pbuf, eptr, x, y, ray);
2019 
2020     if (HPDF_Stream_WriteStr (attr->stream, buf) != HPDF_OK)
2021         return HPDF_CheckError (page->error);
2022 
2023     attr->cur_pos.x = x - ray;
2024     attr->cur_pos.y = y;
2025     attr->str_pos = attr->cur_pos;
2026     attr->gmode = HPDF_GMODE_PATH_OBJECT;
2027 
2028     return ret;
2029 }
2030 
2031 
2032 static char*
QuarterEllipseA(char * pbuf,char * eptr,HPDF_REAL x,HPDF_REAL y,HPDF_REAL xray,HPDF_REAL yray)2033 QuarterEllipseA  (char      *pbuf,
2034                   char      *eptr,
2035                   HPDF_REAL  x,
2036                   HPDF_REAL  y,
2037                   HPDF_REAL  xray,
2038                   HPDF_REAL  yray)
2039 {
2040     pbuf = HPDF_FToA (pbuf, x - xray, eptr);
2041     *pbuf++ = ' ';
2042     pbuf = HPDF_FToA (pbuf, y + yray * KAPPA, eptr);
2043     *pbuf++ = ' ';
2044     pbuf = HPDF_FToA (pbuf, x -xray * KAPPA, eptr);
2045     *pbuf++ = ' ';
2046     pbuf = HPDF_FToA (pbuf, y + yray, eptr);
2047     *pbuf++ = ' ';
2048     pbuf = HPDF_FToA (pbuf, x, eptr);
2049     *pbuf++ = ' ';
2050     pbuf = HPDF_FToA (pbuf, y + yray, eptr);
2051     return (char *)HPDF_StrCpy (pbuf, " c\012", eptr);
2052 }
2053 
2054 static char*
QuarterEllipseB(char * pbuf,char * eptr,HPDF_REAL x,HPDF_REAL y,HPDF_REAL xray,HPDF_REAL yray)2055 QuarterEllipseB  (char      *pbuf,
2056                   char      *eptr,
2057                   HPDF_REAL  x,
2058                   HPDF_REAL  y,
2059                   HPDF_REAL  xray,
2060                   HPDF_REAL  yray)
2061 {
2062     pbuf = HPDF_FToA (pbuf, x + xray * KAPPA, eptr);
2063     *pbuf++ = ' ';
2064     pbuf = HPDF_FToA (pbuf, y + yray, eptr);
2065     *pbuf++ = ' ';
2066     pbuf = HPDF_FToA (pbuf, x + xray, eptr);
2067     *pbuf++ = ' ';
2068     pbuf = HPDF_FToA (pbuf, y + yray * KAPPA, eptr);
2069     *pbuf++ = ' ';
2070     pbuf = HPDF_FToA (pbuf, x + xray, eptr);
2071     *pbuf++ = ' ';
2072     pbuf = HPDF_FToA (pbuf, y, eptr);
2073     return (char *)HPDF_StrCpy (pbuf, " c\012", eptr);
2074 }
2075 
2076 static char*
QuarterEllipseC(char * pbuf,char * eptr,HPDF_REAL x,HPDF_REAL y,HPDF_REAL xray,HPDF_REAL yray)2077 QuarterEllipseC  (char      *pbuf,
2078                   char      *eptr,
2079                   HPDF_REAL  x,
2080                   HPDF_REAL  y,
2081                   HPDF_REAL  xray,
2082                   HPDF_REAL  yray)
2083 {
2084     pbuf = HPDF_FToA (pbuf, x + xray, eptr);
2085     *pbuf++ = ' ';
2086     pbuf = HPDF_FToA (pbuf, y - yray * KAPPA, eptr);
2087     *pbuf++ = ' ';
2088     pbuf = HPDF_FToA (pbuf, x + xray * KAPPA, eptr);
2089     *pbuf++ = ' ';
2090     pbuf = HPDF_FToA (pbuf, y - yray, eptr);
2091     *pbuf++ = ' ';
2092     pbuf = HPDF_FToA (pbuf, x, eptr);
2093     *pbuf++ = ' ';
2094     pbuf = HPDF_FToA (pbuf, y - yray, eptr);
2095     return (char *)HPDF_StrCpy (pbuf, " c\012", eptr);
2096 }
2097 
2098 static char*
QuarterEllipseD(char * pbuf,char * eptr,HPDF_REAL x,HPDF_REAL y,HPDF_REAL xray,HPDF_REAL yray)2099 QuarterEllipseD  (char      *pbuf,
2100                   char      *eptr,
2101                   HPDF_REAL  x,
2102                   HPDF_REAL  y,
2103                   HPDF_REAL  xray,
2104                   HPDF_REAL  yray)
2105 {
2106     pbuf = HPDF_FToA (pbuf, x - xray * KAPPA, eptr);
2107     *pbuf++ = ' ';
2108     pbuf = HPDF_FToA (pbuf, y - yray, eptr);
2109     *pbuf++ = ' ';
2110     pbuf = HPDF_FToA (pbuf, x - xray, eptr);
2111     *pbuf++ = ' ';
2112     pbuf = HPDF_FToA (pbuf, y - yray * KAPPA, eptr);
2113     *pbuf++ = ' ';
2114     pbuf = HPDF_FToA (pbuf, x - xray, eptr);
2115     *pbuf++ = ' ';
2116     pbuf = HPDF_FToA (pbuf, y, eptr);
2117     return (char *)HPDF_StrCpy (pbuf, " c\012", eptr);
2118 }
2119 
2120 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_Ellipse(HPDF_Page page,HPDF_REAL x,HPDF_REAL y,HPDF_REAL xray,HPDF_REAL yray)2121 HPDF_Page_Ellipse  (HPDF_Page   page,
2122                     HPDF_REAL   x,
2123                     HPDF_REAL   y,
2124                     HPDF_REAL  xray,
2125                     HPDF_REAL  yray)
2126 {
2127     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PAGE_DESCRIPTION |
2128             HPDF_GMODE_PATH_OBJECT);
2129     char buf[HPDF_TMP_BUF_SIZ];
2130     char *pbuf = buf;
2131     char *eptr = buf + HPDF_TMP_BUF_SIZ - 1;
2132     HPDF_PageAttr attr;
2133 
2134     HPDF_PTRACE ((" HPDF_Page_Ellipse\n"));
2135 
2136     if (ret != HPDF_OK)
2137         return ret;
2138 
2139     attr = (HPDF_PageAttr)page->attr;
2140 
2141     HPDF_MemSet (buf, 0, HPDF_TMP_BUF_SIZ);
2142 
2143     pbuf = HPDF_FToA (pbuf, x - xray, eptr);
2144     *pbuf++ = ' ';
2145     pbuf = HPDF_FToA (pbuf, y, eptr);
2146     pbuf = (char *)HPDF_StrCpy (pbuf, " m\012", eptr);
2147 
2148     pbuf = QuarterEllipseA (pbuf, eptr, x, y, xray, yray);
2149     pbuf = QuarterEllipseB (pbuf, eptr, x, y, xray, yray);
2150     pbuf = QuarterEllipseC (pbuf, eptr, x, y, xray, yray);
2151     QuarterEllipseD (pbuf, eptr, x, y, xray, yray);
2152 
2153     if (HPDF_Stream_WriteStr (attr->stream, buf) != HPDF_OK)
2154         return HPDF_CheckError (page->error);
2155 
2156     attr->cur_pos.x = x - xray;
2157     attr->cur_pos.y = y;
2158     attr->str_pos = attr->cur_pos;
2159     attr->gmode = HPDF_GMODE_PATH_OBJECT;
2160 
2161     return ret;
2162 }
2163 
2164 
2165 /*
2166  * this function is based on the code which is contributed by Riccardo Cohen.
2167  *
2168  * from http://www.tinaja.com/glib/bezarc1.pdf coming from
2169  * http://www.whizkidtech.redprince.net/bezier/circle/
2170  */
2171 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_Arc(HPDF_Page page,HPDF_REAL x,HPDF_REAL y,HPDF_REAL ray,HPDF_REAL ang1,HPDF_REAL ang2)2172 HPDF_Page_Arc  (HPDF_Page    page,
2173                 HPDF_REAL    x,
2174                 HPDF_REAL    y,
2175                 HPDF_REAL    ray,
2176                 HPDF_REAL    ang1,
2177                 HPDF_REAL    ang2)
2178 {
2179     HPDF_BOOL cont_flg = HPDF_FALSE;
2180 
2181     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PAGE_DESCRIPTION |
2182                     HPDF_GMODE_PATH_OBJECT);
2183 
2184     HPDF_PTRACE ((" HPDF_Page_Arc\n"));
2185 
2186     if (fabs(ang2 - ang1) >= 360)
2187         HPDF_RaiseError (page->error, HPDF_PAGE_OUT_OF_RANGE, 0);
2188 
2189     if (ret != HPDF_OK)
2190         return ret;
2191 
2192     while (ang1 < 0 || ang2 < 0) {
2193         ang1 = ang1 + 360;
2194         ang2 = ang2 + 360;
2195     }
2196 
2197 
2198     for (;;) {
2199         if (fabs(ang2 - ang1) <= 90)
2200             return InternalArc (page, x, y, ray, ang1, ang2, cont_flg);
2201         else {
2202 	    HPDF_REAL tmp_ang = (ang2 > ang1 ? ang1 + 90 : ang1 - 90);
2203 
2204             if ((ret = InternalArc (page, x, y, ray, ang1, tmp_ang, cont_flg))
2205                     != HPDF_OK)
2206                 return ret;
2207 
2208             ang1 = tmp_ang;
2209         }
2210 
2211         if (fabs(ang1 - ang2) < 0.1)
2212             break;
2213 
2214         cont_flg = HPDF_TRUE;
2215     }
2216 
2217     return HPDF_OK;
2218 }
2219 
2220 
2221 static HPDF_STATUS
InternalArc(HPDF_Page page,HPDF_REAL x,HPDF_REAL y,HPDF_REAL ray,HPDF_REAL ang1,HPDF_REAL ang2,HPDF_BOOL cont_flg)2222 InternalArc  (HPDF_Page    page,
2223               HPDF_REAL    x,
2224               HPDF_REAL    y,
2225               HPDF_REAL    ray,
2226               HPDF_REAL    ang1,
2227               HPDF_REAL    ang2,
2228               HPDF_BOOL    cont_flg)
2229 {
2230     const HPDF_REAL PIE = 3.14159F;
2231 
2232     char buf[HPDF_TMP_BUF_SIZ];
2233     char *pbuf = buf;
2234     char *eptr = buf + HPDF_TMP_BUF_SIZ - 1;
2235     HPDF_PageAttr attr;
2236     HPDF_STATUS ret;
2237 
2238     HPDF_DOUBLE rx0, ry0, rx1, ry1, rx2, ry2, rx3, ry3;
2239     HPDF_DOUBLE x0, y0, x1, y1, x2, y2, x3, y3;
2240     HPDF_DOUBLE delta_angle;
2241     HPDF_DOUBLE new_angle;
2242 
2243     HPDF_PTRACE ((" HPDF_Page_InternalArc\n"));
2244 
2245     attr = (HPDF_PageAttr)page->attr;
2246 
2247     HPDF_MemSet (buf, 0, HPDF_TMP_BUF_SIZ);
2248 
2249     delta_angle = (90 - (HPDF_DOUBLE)(ang1 + ang2) / 2) / 180 * PIE;
2250     new_angle = (HPDF_DOUBLE)(ang2 - ang1) / 2 / 180 * PIE;
2251 
2252     rx0 = ray * HPDF_COS (new_angle);
2253     ry0 = ray * HPDF_SIN (new_angle);
2254     rx2 = (ray * 4.0 - rx0) / 3.0;
2255     ry2 = ((ray * 1.0 - rx0) * (rx0 - ray * 3.0)) / (3.0 * ry0);
2256     rx1 = rx2;
2257     ry1 = -ry2;
2258     rx3 = rx0;
2259     ry3 = -ry0;
2260 
2261     x0 = rx0 * HPDF_COS (delta_angle) - ry0 * HPDF_SIN (delta_angle) + x;
2262     y0 = rx0 * HPDF_SIN (delta_angle) + ry0 * HPDF_COS (delta_angle) + y;
2263     x1 = rx1 * HPDF_COS (delta_angle) - ry1 * HPDF_SIN (delta_angle) + x;
2264     y1 = rx1 * HPDF_SIN (delta_angle) + ry1 * HPDF_COS (delta_angle) + y;
2265     x2 = rx2 * HPDF_COS (delta_angle) - ry2 * HPDF_SIN (delta_angle) + x;
2266     y2 = rx2 * HPDF_SIN (delta_angle) + ry2 * HPDF_COS (delta_angle) + y;
2267     x3 = rx3 * HPDF_COS (delta_angle) - ry3 * HPDF_SIN (delta_angle) + x;
2268     y3 = rx3 * HPDF_SIN (delta_angle) + ry3 * HPDF_COS (delta_angle) + y;
2269 
2270     if (!cont_flg) {
2271         pbuf = HPDF_FToA (pbuf, (HPDF_REAL)x0, eptr);
2272         *pbuf++ = ' ';
2273         pbuf = HPDF_FToA (pbuf, (HPDF_REAL)y0, eptr);
2274 
2275 	if (attr->gmode == HPDF_GMODE_PATH_OBJECT)
2276 	  pbuf = (char *)HPDF_StrCpy (pbuf, " l\012", eptr);
2277 	else
2278 	  pbuf = (char *)HPDF_StrCpy (pbuf, " m\012", eptr);
2279     }
2280 
2281     pbuf = HPDF_FToA (pbuf, (HPDF_REAL)x1, eptr);
2282     *pbuf++ = ' ';
2283     pbuf = HPDF_FToA (pbuf, (HPDF_REAL)y1, eptr);
2284     *pbuf++ = ' ';
2285     pbuf = HPDF_FToA (pbuf, (HPDF_REAL)x2, eptr);
2286     *pbuf++ = ' ';
2287     pbuf = HPDF_FToA (pbuf, (HPDF_REAL)y2, eptr);
2288     *pbuf++ = ' ';
2289     pbuf = HPDF_FToA (pbuf, (HPDF_REAL)x3, eptr);
2290     *pbuf++ = ' ';
2291     pbuf = HPDF_FToA (pbuf, (HPDF_REAL)y3, eptr);
2292     HPDF_StrCpy (pbuf, " c\012", eptr);
2293 
2294     if ((ret = HPDF_Stream_WriteStr (attr->stream, buf)) != HPDF_OK)
2295         return HPDF_CheckError (page->error);
2296 
2297     attr->cur_pos.x = (HPDF_REAL)x3;
2298     attr->cur_pos.y = (HPDF_REAL)y3;
2299     attr->str_pos = attr->cur_pos;
2300     attr->gmode = HPDF_GMODE_PATH_OBJECT;
2301 
2302     return ret;
2303 }
2304 
2305 
2306 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_DrawImage(HPDF_Page page,HPDF_Image image,HPDF_REAL x,HPDF_REAL y,HPDF_REAL width,HPDF_REAL height)2307 HPDF_Page_DrawImage  (HPDF_Page    page,
2308                       HPDF_Image   image,
2309                       HPDF_REAL    x,
2310                       HPDF_REAL    y,
2311                       HPDF_REAL    width,
2312                       HPDF_REAL    height)
2313 {
2314     HPDF_STATUS ret;
2315 
2316     if ((ret = HPDF_Page_GSave (page)) != HPDF_OK)
2317         return ret;
2318 
2319     if ((ret = HPDF_Page_Concat (page, width, 0, 0, height, x, y)) != HPDF_OK)
2320         return ret;
2321 
2322     if ((ret = HPDF_Page_ExecuteXObject (page, image)) != HPDF_OK)
2323         return ret;
2324 
2325     return HPDF_Page_GRestore (page);
2326 }
2327 
2328 
2329 static HPDF_STATUS
InternalWriteText(HPDF_PageAttr attr,const char * text)2330 InternalWriteText  (HPDF_PageAttr      attr,
2331                     const char        *text)
2332 {
2333     HPDF_FontAttr font_attr = (HPDF_FontAttr)attr->gstate->font->attr;
2334     HPDF_STATUS ret;
2335 
2336     HPDF_PTRACE ((" InternalWriteText\n"));
2337 
2338     if (font_attr->type == HPDF_FONT_TYPE0_TT ||
2339             font_attr->type == HPDF_FONT_TYPE0_CID) {
2340         HPDF_Encoder encoder;
2341 	HPDF_UINT len;
2342 
2343         if ((ret = HPDF_Stream_WriteStr (attr->stream, "<")) != HPDF_OK)
2344             return ret;
2345 
2346         encoder = font_attr->encoder;
2347         len = HPDF_StrLen (text, HPDF_LIMIT_MAX_STRING_LEN);
2348 
2349         if (encoder->encode_text_fn == NULL) {
2350 	    if ((ret = HPDF_Stream_WriteBinary (attr->stream, (HPDF_BYTE *)text,
2351 						len, NULL))
2352 		!= HPDF_OK)
2353 	        return ret;
2354         } else {
2355 	    char *encoded;
2356 	    HPDF_UINT length;
2357 
2358 	    encoded = (encoder->encode_text_fn)(encoder, text, len, &length);
2359 
2360 	    ret = HPDF_Stream_WriteBinary (attr->stream, (HPDF_BYTE *)encoded,
2361 					   length, NULL);
2362 
2363 	    free(encoded);
2364 
2365 	    if (ret != HPDF_OK)
2366                 return ret;
2367         }
2368 
2369         return HPDF_Stream_WriteStr (attr->stream, ">");
2370     }
2371 
2372     return HPDF_Stream_WriteEscapeText (attr->stream, text);
2373 }
2374 
2375 
2376 /*
2377  * Convert a user space text position from absolute to relative coordinates.
2378  * Absolute values are passed in xAbs and yAbs, relative values are returned
2379  * to xRel and yRel. The latter two must not be NULL.
2380  */
2381 static void
TextPos_AbsToRel(HPDF_TransMatrix text_matrix,HPDF_REAL xAbs,HPDF_REAL yAbs,HPDF_REAL * xRel,HPDF_REAL * yRel)2382 TextPos_AbsToRel (HPDF_TransMatrix text_matrix,
2383                   HPDF_REAL xAbs,
2384                   HPDF_REAL yAbs,
2385                   HPDF_REAL *xRel,
2386                   HPDF_REAL *yRel)
2387 {
2388     if (text_matrix.a == 0) {
2389         *xRel = (yAbs - text_matrix.y - (xAbs - text_matrix.x) *
2390             text_matrix.d / text_matrix.c) / text_matrix.b;
2391         *yRel  = (xAbs - text_matrix.x) / text_matrix.c;
2392     } else {
2393         HPDF_REAL y = (yAbs - text_matrix.y - (xAbs - text_matrix.x) *
2394             text_matrix.b / text_matrix.a) / (text_matrix.d -
2395             text_matrix.c * text_matrix.b / text_matrix.a);
2396         *xRel = (xAbs - text_matrix.x - y * text_matrix.c) /
2397             text_matrix.a;
2398         *yRel = y;
2399     }
2400 }
2401 
2402 
2403 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_TextOut(HPDF_Page page,HPDF_REAL xpos,HPDF_REAL ypos,const char * text)2404 HPDF_Page_TextOut  (HPDF_Page    page,
2405                     HPDF_REAL    xpos,
2406                     HPDF_REAL    ypos,
2407                     const char  *text)
2408 {
2409     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_TEXT_OBJECT);
2410     HPDF_REAL x;
2411     HPDF_REAL y;
2412     HPDF_PageAttr attr;
2413 
2414     HPDF_PTRACE ((" HPDF_Page_TextOut\n"));
2415 
2416     if (ret != HPDF_OK)
2417         return ret;
2418 
2419     attr = (HPDF_PageAttr)page->attr;
2420     TextPos_AbsToRel (attr->text_matrix, xpos, ypos, &x, &y);
2421     if ((ret = HPDF_Page_MoveTextPos (page, x, y)) != HPDF_OK)
2422         return ret;
2423 
2424     return  HPDF_Page_ShowText (page, text);
2425 }
2426 
2427 
2428 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_TextRect(HPDF_Page page,HPDF_REAL left,HPDF_REAL top,HPDF_REAL right,HPDF_REAL bottom,const char * text,HPDF_TextAlignment align,HPDF_UINT * len)2429 HPDF_Page_TextRect  (HPDF_Page            page,
2430                      HPDF_REAL            left,
2431                      HPDF_REAL            top,
2432                      HPDF_REAL            right,
2433                      HPDF_REAL            bottom,
2434                      const char          *text,
2435                      HPDF_TextAlignment   align,
2436                      HPDF_UINT           *len
2437                      )
2438 {
2439     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_TEXT_OBJECT);
2440     HPDF_PageAttr attr;
2441     const char *ptr = text;
2442     HPDF_BOOL pos_initialized = HPDF_FALSE;
2443     HPDF_REAL save_char_space = 0;
2444     HPDF_BOOL is_insufficient_space = HPDF_FALSE;
2445     HPDF_UINT num_rest;
2446     HPDF_Box bbox;
2447     HPDF_BOOL char_space_changed = HPDF_FALSE;
2448 
2449     HPDF_PTRACE ((" HPDF_Page_TextRect\n"));
2450 
2451     if (ret != HPDF_OK)
2452         return ret;
2453 
2454     attr = (HPDF_PageAttr )page->attr;
2455 
2456     /* no font exists */
2457     if (!attr->gstate->font) {
2458         return HPDF_RaiseError (page->error, HPDF_PAGE_FONT_NOT_FOUND, 0);
2459     }
2460 
2461     bbox = HPDF_Font_GetBBox (attr->gstate->font);
2462 
2463     if (len)
2464         *len = 0;
2465     num_rest = HPDF_StrLen (text, HPDF_LIMIT_MAX_STRING_LEN + 1);
2466 
2467     if (num_rest > HPDF_LIMIT_MAX_STRING_LEN) {
2468         return HPDF_RaiseError (page->error, HPDF_STRING_OUT_OF_RANGE, 0);
2469     } else if (!num_rest)
2470         return HPDF_OK;
2471 
2472     if (attr->gstate->text_leading == 0)
2473         HPDF_Page_SetTextLeading (page, (bbox.top - bbox.bottom) / 1000 *
2474                 attr->gstate->font_size);
2475 
2476     top = top - bbox.top / 1000 * attr->gstate->font_size +
2477                 attr->gstate->text_leading;
2478     bottom = bottom - bbox.bottom / 1000 * attr->gstate->font_size;
2479 
2480     if (align == HPDF_TALIGN_JUSTIFY) {
2481         save_char_space = attr->gstate->char_space;
2482         attr->gstate->char_space = 0;
2483     }
2484 
2485     for (;;) {
2486         HPDF_REAL x, y;
2487         HPDF_UINT line_len, tmp_len;
2488         HPDF_REAL rw;
2489         HPDF_BOOL LineBreak;
2490 
2491         attr->gstate->char_space = 0;
2492         line_len = tmp_len = HPDF_Page_MeasureText (page, ptr, right - left, HPDF_TRUE, &rw);
2493         if (line_len == 0) {
2494             is_insufficient_space = HPDF_TRUE;
2495             break;
2496         }
2497 
2498         if (len)
2499             *len += line_len;
2500         num_rest -= line_len;
2501 
2502         /* Shorten tmp_len by trailing whitespace and control characters. */
2503         LineBreak = HPDF_FALSE;
2504         while (tmp_len > 0 && HPDF_IS_WHITE_SPACE(ptr[tmp_len - 1])) {
2505             tmp_len--;
2506             if (ptr[tmp_len] == 0x0A || ptr[tmp_len] == 0x0D) {
2507                 LineBreak = HPDF_TRUE;
2508             }
2509         }
2510 
2511         switch (align) {
2512 
2513             case HPDF_TALIGN_RIGHT:
2514                 TextPos_AbsToRel (attr->text_matrix, right - rw, top, &x, &y);
2515                 if (!pos_initialized) {
2516                     pos_initialized = HPDF_TRUE;
2517                 } else {
2518                     y = 0;
2519                 }
2520                 if ((ret = HPDF_Page_MoveTextPos (page, x, y)) != HPDF_OK)
2521                     return ret;
2522                 break;
2523 
2524             case HPDF_TALIGN_CENTER:
2525                 TextPos_AbsToRel (attr->text_matrix, left + (right - left - rw) / 2, top, &x, &y);
2526                 if (!pos_initialized) {
2527                     pos_initialized = HPDF_TRUE;
2528                 } else {
2529                     y = 0;
2530                 }
2531                 if ((ret = HPDF_Page_MoveTextPos (page, x, y)) != HPDF_OK)
2532                     return ret;
2533                 break;
2534 
2535             case HPDF_TALIGN_JUSTIFY:
2536                 if (!pos_initialized) {
2537                     pos_initialized = HPDF_TRUE;
2538                     TextPos_AbsToRel (attr->text_matrix, left, top, &x, &y);
2539                     if ((ret = HPDF_Page_MoveTextPos (page, x, y)) != HPDF_OK)
2540                         return ret;
2541                 }
2542 
2543                 /* Do not justify last line of paragraph or text. */
2544                 if (LineBreak || num_rest <= 0) {
2545                     if ((ret = HPDF_Page_SetCharSpace (page, save_char_space))
2546                                     != HPDF_OK)
2547                         return ret;
2548                     char_space_changed = HPDF_FALSE;
2549                 } else {
2550                     HPDF_REAL x_adjust;
2551                     HPDF_ParseText_Rec state;
2552                     HPDF_UINT i = 0;
2553                     HPDF_UINT num_char = 0;
2554                     HPDF_Encoder encoder = ((HPDF_FontAttr)attr->gstate->font->attr)->encoder;
2555                     const char *tmp_ptr = ptr;
2556                     HPDF_Encoder_SetParseText (encoder, &state, (HPDF_BYTE *)tmp_ptr, tmp_len);
2557                     while (*tmp_ptr) {
2558                         HPDF_ByteType btype = HPDF_Encoder_ByteType (encoder, &state);
2559                         if (btype != HPDF_BYTE_TYPE_TRIAL)
2560                             num_char++;
2561                         i++;
2562                         if (i >= tmp_len)
2563                             break;
2564                         tmp_ptr++;
2565                     }
2566 
2567                     x_adjust = num_char == 0 ? 0 : (right - left - rw) / (num_char - 1);
2568                     if ((ret = HPDF_Page_SetCharSpace (page, x_adjust)) != HPDF_OK)
2569                         return ret;
2570                     char_space_changed = HPDF_TRUE;
2571                 }
2572                 break;
2573 
2574             default:
2575                 if (!pos_initialized) {
2576                     pos_initialized = HPDF_TRUE;
2577                     TextPos_AbsToRel (attr->text_matrix, left, top, &x, &y);
2578                     if ((ret = HPDF_Page_MoveTextPos (page, x, y)) != HPDF_OK)
2579                         return ret;
2580                 }
2581         }
2582 
2583         if (InternalShowTextNextLine (page, ptr, tmp_len) != HPDF_OK)
2584             return HPDF_CheckError (page->error);
2585 
2586         if (num_rest <= 0)
2587             break;
2588 
2589         if (attr->text_pos.y - attr->gstate->text_leading < bottom) {
2590             is_insufficient_space = HPDF_TRUE;
2591             break;
2592         }
2593 
2594         ptr += line_len;
2595     }
2596 
2597     if (char_space_changed && save_char_space != attr->gstate->char_space) {
2598         if ((ret = HPDF_Page_SetCharSpace (page, save_char_space)) != HPDF_OK)
2599             return ret;
2600     }
2601 
2602     if (is_insufficient_space)
2603         return HPDF_PAGE_INSUFFICIENT_SPACE;
2604     else
2605         return HPDF_OK;
2606 }
2607 
2608 
2609 static HPDF_STATUS
InternalShowTextNextLine(HPDF_Page page,const char * text,HPDF_UINT len)2610 InternalShowTextNextLine  (HPDF_Page    page,
2611                            const char  *text,
2612                            HPDF_UINT    len)
2613 {
2614     HPDF_STATUS ret;
2615     HPDF_PageAttr attr;
2616     HPDF_REAL tw;
2617     HPDF_FontAttr font_attr;
2618 
2619     HPDF_PTRACE ((" ShowTextNextLine\n"));
2620 
2621     attr = (HPDF_PageAttr)page->attr;
2622     font_attr = (HPDF_FontAttr)attr->gstate->font->attr;
2623 
2624     if (font_attr->type == HPDF_FONT_TYPE0_TT ||
2625             font_attr->type == HPDF_FONT_TYPE0_CID) {
2626         HPDF_Encoder encoder = font_attr->encoder;
2627 
2628         if ((ret = HPDF_Stream_WriteStr (attr->stream, "<")) != HPDF_OK)
2629             return ret;
2630 
2631         if (encoder->encode_text_fn == NULL) {
2632 	    if ((ret = HPDF_Stream_WriteBinary (attr->stream, (HPDF_BYTE *)text,
2633 						len, NULL))
2634 		!= HPDF_OK)
2635 	        return ret;
2636         } else {
2637 	    char *encoded;
2638 	    HPDF_UINT length;
2639 
2640 	    encoded = (encoder->encode_text_fn)(encoder, text, len, &length);
2641 	    ret = HPDF_Stream_WriteBinary (attr->stream, (HPDF_BYTE *)encoded,
2642 					   length, NULL);
2643 	    free(encoded);
2644 
2645 	    if (ret != HPDF_OK)
2646 	        return ret;
2647         }
2648 
2649         if ((ret = HPDF_Stream_WriteStr (attr->stream, ">")) != HPDF_OK)
2650             return ret;
2651     } else  if ((ret = HPDF_Stream_WriteEscapeText2 (attr->stream, text,
2652                 len)) != HPDF_OK)
2653         return ret;
2654 
2655     if ((ret = HPDF_Stream_WriteStr (attr->stream, " \'\012")) != HPDF_OK)
2656         return ret;
2657 
2658     tw = HPDF_Page_TextWidth (page, text);
2659 
2660     /* calculate the reference point of text */
2661     attr->text_matrix.x -= attr->gstate->text_leading * attr->text_matrix.c;
2662     attr->text_matrix.y -= attr->gstate->text_leading * attr->text_matrix.d;
2663 
2664     attr->text_pos.x = attr->text_matrix.x;
2665     attr->text_pos.y = attr->text_matrix.y;
2666 
2667     if (attr->gstate->writing_mode == HPDF_WMODE_HORIZONTAL) {
2668         attr->text_pos.x += tw * attr->text_matrix.a;
2669         attr->text_pos.y += tw * attr->text_matrix.b;
2670     } else {
2671         attr->text_pos.x -= tw * attr->text_matrix.b;
2672         attr->text_pos.y -= tw * attr->text_matrix.a;
2673     }
2674 
2675     return ret;
2676 }
2677 
2678 
2679 /*
2680  *  This function is contributed by Adrian Nelson (adenelson).
2681  */
2682 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_SetSlideShow(HPDF_Page page,HPDF_TransitionStyle type,HPDF_REAL disp_time,HPDF_REAL trans_time)2683 HPDF_Page_SetSlideShow  (HPDF_Page            page,
2684                          HPDF_TransitionStyle   type,
2685                          HPDF_REAL            disp_time,
2686                          HPDF_REAL            trans_time)
2687     {
2688     HPDF_STATUS ret = HPDF_OK;
2689     HPDF_Dict dict;
2690 
2691     HPDF_PTRACE((" HPDF_Page_SetSlideShow\n"));
2692 
2693     if (!HPDF_Page_Validate (page))
2694         return HPDF_INVALID_PAGE;
2695 
2696     if (disp_time < 0)
2697         return HPDF_RaiseError (page->error, HPDF_PAGE_INVALID_DISPLAY_TIME,
2698                     (HPDF_STATUS)disp_time);
2699 
2700     if (trans_time < 0)
2701         return HPDF_RaiseError (page->error, HPDF_PAGE_INVALID_TRANSITION_TIME,
2702                     (HPDF_STATUS)trans_time);
2703 
2704     dict = HPDF_Dict_New(page->mmgr);
2705 
2706     if (!dict)
2707         return HPDF_Error_GetCode (page->error);
2708 
2709     if (HPDF_Dict_AddName (dict, "Type", "Trans") != HPDF_OK)
2710         goto Fail;
2711 
2712     if (HPDF_Dict_AddReal (dict, "D", trans_time) != HPDF_OK)
2713         goto Fail;
2714 
2715     switch (type) {
2716         case HPDF_TS_WIPE_RIGHT:
2717             ret += HPDF_Dict_AddName (dict, "S", "Wipe");
2718             ret += HPDF_Dict_AddNumber (dict, "Di", 0);
2719             break;
2720         case HPDF_TS_WIPE_UP:
2721             ret += HPDF_Dict_AddName (dict, "S", "Wipe");
2722             ret += HPDF_Dict_AddNumber (dict, "Di", 90);
2723             break;
2724         case HPDF_TS_WIPE_LEFT:
2725             ret += HPDF_Dict_AddName (dict, "S", "Wipe");
2726             ret += HPDF_Dict_AddNumber (dict, "Di", 180);
2727             break;
2728         case HPDF_TS_WIPE_DOWN:
2729             ret += HPDF_Dict_AddName (dict, "S", "Wipe");
2730             ret += HPDF_Dict_AddNumber    (dict, "Di", 270);
2731             break;
2732         case HPDF_TS_BARN_DOORS_HORIZONTAL_OUT:
2733             ret += HPDF_Dict_AddName (dict, "S", "Split");
2734             ret += HPDF_Dict_AddName (dict, "Dm", "H");
2735             ret += HPDF_Dict_AddName (dict, "M", "O");
2736             break;
2737         case HPDF_TS_BARN_DOORS_HORIZONTAL_IN:
2738             ret += HPDF_Dict_AddName (dict, "S", "Split");
2739             ret += HPDF_Dict_AddName (dict, "Dm", "H");
2740             ret += HPDF_Dict_AddName (dict, "M", "I");
2741             break;
2742         case HPDF_TS_BARN_DOORS_VERTICAL_OUT:
2743             ret += HPDF_Dict_AddName (dict, "S", "Split");
2744             ret += HPDF_Dict_AddName (dict, "Dm", "V");
2745             ret += HPDF_Dict_AddName (dict, "M", "O");
2746             break;
2747         case HPDF_TS_BARN_DOORS_VERTICAL_IN:
2748             ret += HPDF_Dict_AddName (dict, "S", "Split");
2749             ret += HPDF_Dict_AddName (dict, "Dm", "V");
2750             ret += HPDF_Dict_AddName (dict, "M", "I");
2751             break;
2752         case HPDF_TS_BOX_OUT:
2753             ret += HPDF_Dict_AddName (dict, "S", "Box");
2754             ret += HPDF_Dict_AddName (dict, "M", "O");
2755             break;
2756         case HPDF_TS_BOX_IN:
2757             ret += HPDF_Dict_AddName (dict, "S", "Box");
2758             ret += HPDF_Dict_AddName (dict, "M", "I");
2759             break;
2760         case HPDF_TS_BLINDS_HORIZONTAL:
2761             ret += HPDF_Dict_AddName (dict, "S", "Blinds");
2762             ret += HPDF_Dict_AddName (dict, "Dm", "H");
2763             break;
2764         case HPDF_TS_BLINDS_VERTICAL:
2765             ret += HPDF_Dict_AddName (dict, "S", "Blinds");
2766             ret += HPDF_Dict_AddName (dict, "Dm", "V");
2767             break;
2768         case HPDF_TS_DISSOLVE:
2769             ret += HPDF_Dict_AddName (dict, "S", "Dissolve");
2770             break;
2771         case HPDF_TS_GLITTER_RIGHT:
2772             ret += HPDF_Dict_AddName (dict, "S", "Glitter");
2773             ret += HPDF_Dict_AddNumber (dict, "Di", 0);
2774             break;
2775         case HPDF_TS_GLITTER_DOWN:
2776             ret += HPDF_Dict_AddName (dict, "S", "Glitter");
2777             ret += HPDF_Dict_AddNumber (dict, "Di", 270);
2778             break;
2779         case HPDF_TS_GLITTER_TOP_LEFT_TO_BOTTOM_RIGHT:
2780             ret += HPDF_Dict_AddName (dict, "S", "Glitter");
2781             ret += HPDF_Dict_AddNumber (dict, "Di", 315);
2782             break;
2783         case HPDF_TS_REPLACE:
2784             ret += HPDF_Dict_AddName  (dict, "S", "R");
2785             break;
2786         default:
2787             ret += HPDF_SetError(page->error, HPDF_INVALID_PAGE_SLIDESHOW_TYPE, 0);
2788     }
2789 
2790     if (ret != HPDF_OK)
2791         goto Fail;
2792 
2793     if (HPDF_Dict_AddReal (page, "Dur", disp_time) != HPDF_OK)
2794         goto Fail;
2795 
2796     if ((ret = HPDF_Dict_Add (page, "Trans", dict)) != HPDF_OK)
2797         return ret;
2798 
2799     return HPDF_OK;
2800 
2801 Fail:
2802     HPDF_Dict_Free (dict);
2803     return HPDF_Error_GetCode (page->error);
2804 }
2805 
2806 
2807 /*
2808  *  This function is contributed by Finn Arildsen.
2809  */
2810 
2811 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_New_Content_Stream(HPDF_Page page,HPDF_Dict * new_stream)2812 HPDF_Page_New_Content_Stream  (HPDF_Page page,
2813                                HPDF_Dict* new_stream)
2814 {
2815     /* Call this function to start a new content stream on a page. The
2816        handle is returned to new_stream.
2817        new_stream can later be used on other pages as a shared content stream;
2818        insert using HPDF_Page_Insert_Shared_Content_Stream */
2819 
2820     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PAGE_DESCRIPTION |
2821                     HPDF_GMODE_TEXT_OBJECT);
2822     HPDF_PageAttr attr;
2823     HPDF_UINT filter;
2824     HPDF_Array contents_array;
2825 
2826     HPDF_PTRACE((" HPDF_Page_New_Content_Stream\n"));
2827 
2828     attr = (HPDF_PageAttr)page->attr;
2829     filter = attr->contents->filter;
2830 
2831     /* check if there is already an array of contents */
2832     contents_array = (HPDF_Array) HPDF_Dict_GetItem(page,"Contents", HPDF_OCLASS_ARRAY);
2833     if (!contents_array) {
2834         HPDF_Error_Reset (page->error);
2835         /* no contents_array already -- create one
2836            and replace current single contents item */
2837         contents_array = HPDF_Array_New(page->mmgr);
2838         if (!contents_array)
2839             return HPDF_Error_GetCode (page->error);
2840         ret += HPDF_Array_Add(contents_array,attr->contents);
2841         ret += HPDF_Dict_Add (page, "Contents", contents_array);
2842     }
2843 
2844     /* create new contents stream and add it to the page's contents array */
2845     attr->contents = HPDF_DictStream_New (page->mmgr, attr->xref);
2846     attr->contents->filter = filter;
2847     attr->stream = attr->contents->stream;
2848 
2849     if (!attr->contents)
2850         return HPDF_Error_GetCode (page->error);
2851 
2852     ret += HPDF_Array_Add (contents_array,attr->contents);
2853 
2854     /* return the value of the new stream, so that
2855        the application can use it as a shared contents stream */
2856     if (ret == HPDF_OK && new_stream != NULL)
2857         *new_stream = attr->contents;
2858 
2859     return ret;
2860 }
2861 
2862 
2863 /*
2864  *  This function is contributed by Finn Arildsen.
2865  */
2866 
2867 HPDF_EXPORT(HPDF_STATUS)
HPDF_Page_Insert_Shared_Content_Stream(HPDF_Page page,HPDF_Dict shared_stream)2868 HPDF_Page_Insert_Shared_Content_Stream  (HPDF_Page page,
2869                                HPDF_Dict shared_stream)
2870 {
2871     /* Call this function to insert a previously (with HPDF_New_Content_Stream) created content stream
2872        as a shared content stream on this page */
2873 
2874     HPDF_STATUS ret = HPDF_Page_CheckState (page, HPDF_GMODE_PAGE_DESCRIPTION |
2875                     HPDF_GMODE_TEXT_OBJECT);
2876     HPDF_Array contents_array;
2877 
2878     HPDF_PTRACE((" HPDF_Page_Insert_Shared_Content_Stream\n"));
2879 
2880     /* check if there is already an array of contents */
2881     contents_array = (HPDF_Array) HPDF_Dict_GetItem(page,"Contents", HPDF_OCLASS_ARRAY);
2882     if (!contents_array) {
2883         HPDF_PageAttr attr;
2884         HPDF_Error_Reset (page->error);
2885         /* no contents_array already -- create one
2886            and replace current single contents item */
2887         contents_array = HPDF_Array_New(page->mmgr);
2888         if (!contents_array)
2889             return HPDF_Error_GetCode (page->error);
2890         attr = (HPDF_PageAttr)page->attr;
2891         ret += HPDF_Array_Add(contents_array,attr->contents);
2892         ret += HPDF_Dict_Add (page, "Contents", contents_array);
2893     }
2894 
2895     ret += HPDF_Array_Add (contents_array,shared_stream);
2896 
2897     /* Continue with a new stream */
2898     ret += HPDF_Page_New_Content_Stream (page, NULL);
2899 
2900     return ret;
2901 }
2902