1 | /* |
2 | * << Haru Free PDF Library >> -- hpdf_u3d.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 | #include "hpdf_conf.h" |
18 | #include "hpdf_utils.h" |
19 | #include "hpdf.h" |
20 | |
21 | #include <string.h> |
22 | |
23 | #ifndef M_PI |
24 | /* Not defined in MSVC6 */ |
25 | #define M_PI 3.14159265358979323846 |
26 | #endif |
27 | |
28 | HPDF_U3D |
29 | HPDF_U3D_LoadU3D (HPDF_MMgr mmgr, |
30 | HPDF_Stream u3d_data, |
31 | HPDF_Xref xref); |
32 | |
33 | static const char u3d[] = "U3D" ; |
34 | static const char prc[] = "PRC" ; |
35 | |
36 | static HPDF_STATUS Get3DStreamType (HPDF_Stream stream, const char **type) |
37 | { |
38 | HPDF_BYTE tag[4]; |
39 | HPDF_UINT len; |
40 | |
41 | HPDF_PTRACE ((" HPDF_U3D_Get3DStreamType\n" )); |
42 | |
43 | len = 4; |
44 | if (HPDF_Stream_Read (stream, tag, &len) != HPDF_OK) { |
45 | return HPDF_Error_GetCode (stream->error); |
46 | } |
47 | |
48 | if (HPDF_Stream_Seek (stream, 0, HPDF_SEEK_SET) != HPDF_OK) { |
49 | return HPDF_Error_GetCode (stream->error); |
50 | } |
51 | |
52 | if (HPDF_MemCmp(tag, (HPDF_BYTE *)u3d, 4/* yes, \0 is required */) == 0) { |
53 | *type = u3d; |
54 | return HPDF_OK; |
55 | } |
56 | |
57 | if (HPDF_MemCmp(tag, (HPDF_BYTE *)prc, 3) == 0) { |
58 | *type = prc; |
59 | return HPDF_OK; |
60 | } |
61 | |
62 | return HPDF_INVALID_U3D_DATA; |
63 | } |
64 | |
65 | |
66 | HPDF_U3D |
67 | HPDF_U3D_LoadU3DFromMem ( HPDF_MMgr mmgr, |
68 | const HPDF_BYTE *buf, |
69 | HPDF_UINT size, |
70 | HPDF_Xref xref ) |
71 | { |
72 | HPDF_Dict image; |
73 | HPDF_STATUS ret = HPDF_OK; |
74 | |
75 | HPDF_PTRACE ((" HPDF_U3D_LoadU3DFromMem\n" )); |
76 | |
77 | image = HPDF_DictStream_New (mmgr, xref); |
78 | if (!image) { |
79 | return NULL; |
80 | } |
81 | |
82 | image->header.obj_class |= HPDF_OSUBCLASS_XOBJECT; |
83 | ret = HPDF_Dict_AddName (image, "Type" , "XObject" ); |
84 | if (ret != HPDF_OK) { |
85 | HPDF_Dict_Free(image); |
86 | return NULL; |
87 | } |
88 | |
89 | ret = HPDF_Dict_AddName (image, "Subtype" , "Image" ); |
90 | if (ret != HPDF_OK) { |
91 | HPDF_Dict_Free(image); |
92 | return NULL; |
93 | } |
94 | |
95 | if (HPDF_Stream_Write (image->stream, buf, size) != HPDF_OK) { |
96 | HPDF_Dict_Free(image); |
97 | return NULL; |
98 | } |
99 | |
100 | return image; |
101 | } |
102 | |
103 | |
104 | HPDF_EXPORT(HPDF_Image) |
105 | HPDF_LoadU3DFromFile (HPDF_Doc pdf, |
106 | const char *filename) |
107 | { |
108 | HPDF_Stream imagedata; |
109 | HPDF_Image image; |
110 | |
111 | HPDF_PTRACE ((" HPDF_LoadU3DFromFile\n" )); |
112 | |
113 | if (!HPDF_HasDoc (pdf)) { |
114 | return NULL; |
115 | } |
116 | |
117 | /* create file stream */ |
118 | imagedata = HPDF_FileReader_New (pdf->mmgr, filename); |
119 | |
120 | if (HPDF_Stream_Validate (imagedata)) { |
121 | image = HPDF_U3D_LoadU3D (pdf->mmgr, imagedata, pdf->xref); |
122 | } else { |
123 | image = NULL; |
124 | } |
125 | |
126 | /* destroy file stream */ |
127 | HPDF_Stream_Free (imagedata); |
128 | |
129 | if (!image) { |
130 | HPDF_CheckError (&pdf->error); |
131 | } |
132 | return image; |
133 | } |
134 | |
135 | HPDF_EXPORT(HPDF_Image) |
136 | HPDF_LoadU3DFromMem (HPDF_Doc pdf, |
137 | const HPDF_BYTE *buffer, |
138 | HPDF_UINT size) |
139 | { |
140 | HPDF_Stream imagedata; |
141 | HPDF_Image image; |
142 | |
143 | HPDF_PTRACE ((" HPDF_LoadU3DFromMem\n" )); |
144 | |
145 | if (!HPDF_HasDoc (pdf)) { |
146 | return NULL; |
147 | } |
148 | |
149 | /* create file stream */ |
150 | imagedata = HPDF_MemStream_New (pdf->mmgr, size); |
151 | |
152 | if (!HPDF_Stream_Validate (imagedata)) { |
153 | HPDF_RaiseError (&pdf->error, HPDF_INVALID_STREAM, 0); |
154 | return NULL; |
155 | } |
156 | |
157 | if (HPDF_Stream_Write (imagedata, buffer, size) != HPDF_OK) { |
158 | HPDF_Stream_Free (imagedata); |
159 | return NULL; |
160 | } |
161 | |
162 | if (HPDF_Stream_Validate (imagedata)) { |
163 | image = HPDF_U3D_LoadU3D (pdf->mmgr, imagedata, pdf->xref); |
164 | } else { |
165 | image = NULL; |
166 | } |
167 | |
168 | /* destroy file stream */ |
169 | HPDF_Stream_Free (imagedata); |
170 | |
171 | if (!image) { |
172 | HPDF_CheckError (&pdf->error); |
173 | } |
174 | return image; |
175 | } |
176 | |
177 | HPDF_U3D |
178 | HPDF_U3D_LoadU3D (HPDF_MMgr mmgr, |
179 | HPDF_Stream u3d_data, |
180 | HPDF_Xref xref) |
181 | { |
182 | HPDF_Dict u3d; |
183 | const char *type; |
184 | |
185 | HPDF_PTRACE ((" HPDF_U3D_LoadU3D\n" )); |
186 | |
187 | u3d = HPDF_DictStream_New (mmgr, xref); |
188 | if (!u3d) { |
189 | return NULL; |
190 | } |
191 | |
192 | u3d->header.obj_class |= HPDF_OSUBCLASS_XOBJECT; |
193 | |
194 | /* add required elements */ |
195 | u3d->filter = HPDF_STREAM_FILTER_NONE; |
196 | |
197 | if (HPDF_Dict_AddName (u3d, "Type" , "3D" ) != HPDF_OK) { |
198 | HPDF_Dict_Free(u3d); |
199 | return NULL; |
200 | } |
201 | |
202 | if (Get3DStreamType (u3d_data, &type) != HPDF_OK) { |
203 | HPDF_Dict_Free(u3d); |
204 | return NULL; |
205 | } |
206 | |
207 | if (HPDF_Dict_AddName (u3d, "Subtype" , type) != HPDF_OK) { |
208 | HPDF_Dict_Free(u3d); |
209 | return NULL; |
210 | } |
211 | |
212 | for (;;) { |
213 | HPDF_BYTE buf[HPDF_STREAM_BUF_SIZ]; |
214 | HPDF_UINT len = HPDF_STREAM_BUF_SIZ; |
215 | HPDF_STATUS ret = HPDF_Stream_Read (u3d_data, buf, &len); |
216 | |
217 | if (ret != HPDF_OK) { |
218 | if (ret == HPDF_STREAM_EOF) { |
219 | if (len > 0) { |
220 | ret = HPDF_Stream_Write (u3d->stream, buf, len); |
221 | if (ret != HPDF_OK) { |
222 | HPDF_Dict_Free(u3d); |
223 | return NULL; |
224 | } |
225 | } |
226 | break; |
227 | } else { |
228 | HPDF_Dict_Free(u3d); |
229 | return NULL; |
230 | } |
231 | } |
232 | |
233 | if (HPDF_Stream_Write (u3d->stream, buf, len) != HPDF_OK) { |
234 | HPDF_Dict_Free(u3d); |
235 | return NULL; |
236 | } |
237 | } |
238 | |
239 | return u3d; |
240 | } |
241 | |
242 | HPDF_EXPORT(HPDF_Dict) HPDF_Create3DView(HPDF_MMgr mmgr, const char *name) |
243 | { |
244 | HPDF_STATUS ret = HPDF_OK; |
245 | HPDF_Dict view; |
246 | |
247 | HPDF_PTRACE ((" HPDF_Create3DView\n" )); |
248 | |
249 | if (name == NULL || name[0] == '\0') { |
250 | return NULL; |
251 | } |
252 | |
253 | view = HPDF_Dict_New (mmgr); |
254 | if (!view) { |
255 | return NULL; |
256 | } |
257 | |
258 | ret = HPDF_Dict_AddName (view, "TYPE" , "3DView" ); |
259 | if (ret != HPDF_OK) { |
260 | HPDF_Dict_Free (view); |
261 | return NULL; |
262 | } |
263 | |
264 | ret = HPDF_Dict_Add (view, "XN" , HPDF_String_New (mmgr, name, NULL)); |
265 | if (ret != HPDF_OK) { |
266 | HPDF_Dict_Free (view); |
267 | return NULL; |
268 | } |
269 | |
270 | ret = HPDF_Dict_Add (view, "IN" , HPDF_String_New (mmgr, name, NULL)); |
271 | if (ret != HPDF_OK) { |
272 | HPDF_Dict_Free (view); |
273 | return NULL; |
274 | } |
275 | |
276 | return view; |
277 | } |
278 | |
279 | HPDF_EXPORT(HPDF_STATUS) HPDF_U3D_Add3DView(HPDF_U3D u3d, HPDF_Dict view) |
280 | { |
281 | HPDF_Array views = NULL; |
282 | HPDF_STATUS ret = HPDF_OK; |
283 | |
284 | HPDF_PTRACE ((" HPDF_Add3DView\n" )); |
285 | |
286 | if (u3d == NULL || view == NULL) { |
287 | return HPDF_INVALID_U3D_DATA; |
288 | } |
289 | |
290 | views = (HPDF_Array)HPDF_Dict_GetItem (u3d, "VA" , HPDF_OCLASS_ARRAY); |
291 | if (views == NULL) { |
292 | views = HPDF_Array_New (u3d->mmgr); |
293 | if (!views) { |
294 | return HPDF_Error_GetCode (u3d->error); |
295 | } |
296 | |
297 | ret = HPDF_Dict_Add (u3d, "VA" , views); |
298 | if (ret == HPDF_OK) { |
299 | ret = HPDF_Dict_AddNumber (u3d, "DV" , 0); |
300 | } else { |
301 | HPDF_Array_Free (views); |
302 | return ret; |
303 | } |
304 | } |
305 | |
306 | if (ret == HPDF_OK) { |
307 | ret = HPDF_Array_Add( views, view); |
308 | } |
309 | |
310 | return ret; |
311 | } |
312 | |
313 | |
314 | HPDF_EXPORT(HPDF_STATUS) HPDF_U3D_AddOnInstanciate(HPDF_U3D u3d, HPDF_JavaScript javascript) |
315 | { |
316 | HPDF_STATUS ret = HPDF_OK; |
317 | |
318 | HPDF_PTRACE ((" HPDF_U3D_AddOnInstanciate\n" )); |
319 | |
320 | if (u3d == NULL || javascript == NULL) { |
321 | return HPDF_INVALID_U3D_DATA; |
322 | } |
323 | |
324 | ret = HPDF_Dict_Add(u3d, "OnInstantiate" , javascript); |
325 | |
326 | return ret; |
327 | } |
328 | |
329 | |
330 | HPDF_EXPORT(HPDF_STATUS) HPDF_U3D_SetDefault3DView(HPDF_U3D u3d, const char *name) |
331 | { |
332 | HPDF_STATUS ret = HPDF_OK; |
333 | |
334 | HPDF_PTRACE ((" HPDF_U3D_SetDefault3DView\n" )); |
335 | |
336 | if (u3d == NULL || name == NULL || name[0] == '\0') { |
337 | return HPDF_INVALID_U3D_DATA; |
338 | } |
339 | |
340 | ret = HPDF_Dict_Add (u3d, "DV" , HPDF_String_New (u3d->mmgr, name, NULL)); |
341 | return ret; |
342 | } |
343 | |
344 | HPDF_EXPORT(HPDF_STATUS) HPDF_3DView_AddNode(HPDF_Dict view, const char *name, HPDF_REAL opacity, HPDF_BOOL visible) |
345 | { |
346 | HPDF_Array nodes = NULL; |
347 | HPDF_Dict node; |
348 | HPDF_STATUS ret = HPDF_OK; |
349 | |
350 | HPDF_PTRACE ((" HPDF_3DView_AddNode\n" )); |
351 | |
352 | if (view == NULL || opacity < 0 || opacity > 1 || name == NULL || name[0] == '\0') { |
353 | return HPDF_INVALID_U3D_DATA; |
354 | } |
355 | |
356 | nodes = (HPDF_Array)HPDF_Dict_GetItem (view, "NA" , HPDF_OCLASS_ARRAY); |
357 | if (nodes == NULL) { |
358 | nodes = HPDF_Array_New (view->mmgr); |
359 | if (!nodes) { |
360 | return HPDF_Error_GetCode (view->error); |
361 | } |
362 | |
363 | ret = HPDF_Dict_Add (view, "NA" , nodes); |
364 | if (ret != HPDF_OK) { |
365 | HPDF_Array_Free (nodes); |
366 | return ret; |
367 | } |
368 | } |
369 | |
370 | node = HPDF_Dict_New (view->mmgr); |
371 | if (!node) { |
372 | HPDF_Array_Free (nodes); |
373 | return HPDF_Error_GetCode (view->error); |
374 | } |
375 | |
376 | ret = HPDF_Dict_AddName (node, "Type" , "3DNode" ); |
377 | if (ret != HPDF_OK) { |
378 | HPDF_Array_Free (nodes); |
379 | HPDF_Dict_Free (node); |
380 | return ret; |
381 | } |
382 | |
383 | ret = HPDF_Dict_Add (node, "N" , HPDF_String_New (view->mmgr, name, NULL)); |
384 | if (ret != HPDF_OK) { |
385 | HPDF_Array_Free (nodes); |
386 | HPDF_Dict_Free (node); |
387 | return ret; |
388 | } |
389 | |
390 | ret = HPDF_Dict_AddReal (node, "O" , opacity); |
391 | if (ret != HPDF_OK) { |
392 | HPDF_Array_Free (nodes); |
393 | HPDF_Dict_Free (node); |
394 | return ret; |
395 | } |
396 | |
397 | ret = HPDF_Dict_AddBoolean (node, "V" , visible); |
398 | if (ret != HPDF_OK) { |
399 | HPDF_Dict_Free (node); |
400 | HPDF_Array_Free (nodes); |
401 | return ret; |
402 | } |
403 | |
404 | ret = HPDF_Array_Add(nodes, node); |
405 | if (ret != HPDF_OK) { |
406 | HPDF_Dict_Free (node); |
407 | HPDF_Array_Free (nodes); |
408 | return ret; |
409 | } |
410 | return ret; |
411 | } |
412 | |
413 | HPDF_EXPORT(HPDF_STATUS) HPDF_3DView_SetLighting(HPDF_Dict view, const char *scheme) |
414 | { |
415 | HPDF_STATUS ret = HPDF_OK; |
416 | HPDF_Dict lighting; |
417 | int i; |
418 | static const char * const schemes[] = |
419 | { "Artwork" , "None" , "White" , "Day" , "Night" , "Hard" , "Primary" , "Blue" , "Red" , "Cube" , "CAD" , "Headlamp" }; |
420 | |
421 | HPDF_PTRACE ((" HPDF_3DView_SetLighting\n" )); |
422 | |
423 | if (view == NULL || scheme == NULL || scheme[0] == '\0') { |
424 | return HPDF_INVALID_U3D_DATA; |
425 | } |
426 | |
427 | for (i = 0; i < 12; i++) { |
428 | if (!strcmp(scheme, schemes[i])) { |
429 | break; |
430 | } |
431 | } |
432 | |
433 | if (i == 12) { |
434 | return HPDF_INVALID_U3D_DATA; |
435 | } |
436 | |
437 | lighting = HPDF_Dict_New (view->mmgr); |
438 | if (!lighting) { |
439 | return HPDF_Error_GetCode (view->error); |
440 | } |
441 | |
442 | ret = HPDF_Dict_AddName (lighting, "Type" , "3DLightingScheme" ); |
443 | if (ret != HPDF_OK) { |
444 | HPDF_Dict_Free (lighting); |
445 | return ret; |
446 | } |
447 | |
448 | ret = HPDF_Dict_AddName (lighting, "Subtype" , scheme); |
449 | if (ret != HPDF_OK) { |
450 | HPDF_Dict_Free (lighting); |
451 | return ret; |
452 | } |
453 | |
454 | ret = HPDF_Dict_Add (view, "LS" , lighting); |
455 | if (ret != HPDF_OK) { |
456 | HPDF_Dict_Free (lighting); |
457 | return ret; |
458 | } |
459 | return ret; |
460 | } |
461 | |
462 | HPDF_EXPORT(HPDF_STATUS) HPDF_3DView_SetBackgroundColor(HPDF_Dict view, HPDF_REAL r, HPDF_REAL g, HPDF_REAL b) |
463 | { |
464 | HPDF_Array color; |
465 | HPDF_STATUS ret = HPDF_OK; |
466 | HPDF_Dict background; |
467 | |
468 | HPDF_PTRACE ((" HPDF_3DView_SetBackgroundColor\n" )); |
469 | |
470 | if (view == NULL || r < 0 || r > 1 || g < 0 || g > 1 || b < 0 || b > 1) { |
471 | return HPDF_INVALID_U3D_DATA; |
472 | } |
473 | |
474 | background = HPDF_Dict_New (view->mmgr); |
475 | if (!background) { |
476 | return HPDF_Error_GetCode (view->error); |
477 | } |
478 | |
479 | color = HPDF_Array_New (view->mmgr); |
480 | if (!color) { |
481 | HPDF_Dict_Free (background); |
482 | return HPDF_Error_GetCode (view->error); |
483 | } |
484 | |
485 | ret = HPDF_Array_AddReal (color, r); |
486 | if (ret != HPDF_OK) { |
487 | HPDF_Array_Free (color); |
488 | HPDF_Dict_Free (background); |
489 | return ret; |
490 | } |
491 | |
492 | ret = HPDF_Array_AddReal (color, g); |
493 | if (ret != HPDF_OK) { |
494 | HPDF_Array_Free (color); |
495 | HPDF_Dict_Free (background); |
496 | return ret; |
497 | } |
498 | |
499 | ret = HPDF_Array_AddReal (color, b); |
500 | if (ret != HPDF_OK) { |
501 | HPDF_Array_Free (color); |
502 | HPDF_Dict_Free (background); |
503 | return ret; |
504 | } |
505 | |
506 | |
507 | ret = HPDF_Dict_AddName (background, "Type" , "3DBG" ); |
508 | if (ret != HPDF_OK) { |
509 | HPDF_Array_Free (color); |
510 | HPDF_Dict_Free (background); |
511 | return ret; |
512 | } |
513 | |
514 | ret = HPDF_Dict_Add (background, "C" , color); |
515 | if (ret != HPDF_OK) { |
516 | HPDF_Array_Free (color); |
517 | HPDF_Dict_Free (background); |
518 | return ret; |
519 | } |
520 | |
521 | ret = HPDF_Dict_Add (view, "BG" , background); |
522 | if (ret != HPDF_OK) { |
523 | HPDF_Array_Free (color); |
524 | HPDF_Dict_Free (background); |
525 | return ret; |
526 | } |
527 | return ret; |
528 | } |
529 | |
530 | HPDF_EXPORT(HPDF_STATUS) HPDF_3DView_SetPerspectiveProjection(HPDF_Dict view, HPDF_REAL fov) |
531 | { |
532 | HPDF_STATUS ret = HPDF_OK; |
533 | HPDF_Dict projection; |
534 | |
535 | HPDF_PTRACE ((" HPDF_3DView_SetPerspectiveProjection\n" )); |
536 | |
537 | if (view == NULL || fov < 0 || fov > 180) { |
538 | return HPDF_INVALID_U3D_DATA; |
539 | } |
540 | |
541 | projection = HPDF_Dict_New (view->mmgr); |
542 | if (!projection) { |
543 | return HPDF_Error_GetCode (view->error); |
544 | } |
545 | |
546 | ret = HPDF_Dict_AddName (projection, "Subtype" , "P" ); |
547 | if (ret != HPDF_OK) { |
548 | HPDF_Dict_Free (projection); |
549 | return ret; |
550 | } |
551 | |
552 | ret = HPDF_Dict_AddName (projection, "PS" , "Min" ); |
553 | if (ret != HPDF_OK) { |
554 | HPDF_Dict_Free (projection); |
555 | return ret; |
556 | } |
557 | |
558 | ret = HPDF_Dict_AddReal (projection, "FOV" , fov); |
559 | if (ret != HPDF_OK) { |
560 | HPDF_Dict_Free (projection); |
561 | return ret; |
562 | } |
563 | |
564 | ret = HPDF_Dict_Add (view, "P" , projection); |
565 | if (ret != HPDF_OK) { |
566 | HPDF_Dict_Free (projection); |
567 | return ret; |
568 | } |
569 | return ret; |
570 | } |
571 | |
572 | HPDF_EXPORT(HPDF_STATUS) HPDF_3DView_SetOrthogonalProjection(HPDF_Dict view, HPDF_REAL mag) |
573 | { |
574 | HPDF_STATUS ret = HPDF_OK; |
575 | HPDF_Dict projection; |
576 | |
577 | HPDF_PTRACE ((" HPDF_3DView_SetOrthogonalProjection\n" )); |
578 | |
579 | if (view == NULL || mag <= 0) { |
580 | return HPDF_INVALID_U3D_DATA; |
581 | } |
582 | |
583 | projection = HPDF_Dict_New (view->mmgr); |
584 | if (!projection) { |
585 | return HPDF_Error_GetCode (view->error); |
586 | } |
587 | |
588 | ret = HPDF_Dict_AddName (projection, "Subtype" , "O" ); |
589 | if (ret != HPDF_OK) { |
590 | HPDF_Dict_Free (projection); |
591 | return ret; |
592 | } |
593 | |
594 | ret = HPDF_Dict_AddReal (projection, "OS" , mag); |
595 | if (ret != HPDF_OK) { |
596 | HPDF_Dict_Free (projection); |
597 | return ret; |
598 | } |
599 | |
600 | ret = HPDF_Dict_Add (view, "P" , projection); |
601 | if (ret != HPDF_OK) { |
602 | HPDF_Dict_Free (projection); |
603 | return ret; |
604 | } |
605 | return ret; |
606 | } |
607 | |
608 | #define normalize(x, y, z) \ |
609 | { \ |
610 | HPDF_REAL modulo; \ |
611 | modulo = (float)sqrt((float)(x*x) + (float)(y*y) + (float)(z*z)); \ |
612 | if (modulo != 0.0) \ |
613 | { \ |
614 | x = x/modulo; \ |
615 | y = y/modulo; \ |
616 | z = z/modulo; \ |
617 | } \ |
618 | } |
619 | |
620 | /* building the transformation matrix*/ |
621 | /* #1,#2,#3 centre of orbit coordinates (coo)*/ |
622 | /* #4,#5,#6 centre of orbit to camera direction vector (c2c)*/ |
623 | /* #7 orbital radius (roo)*/ |
624 | /* #8 camera roll (roll)*/ |
625 | |
626 | HPDF_EXPORT(HPDF_STATUS) HPDF_3DView_SetCamera(HPDF_Dict view, HPDF_REAL coox, HPDF_REAL cooy, HPDF_REAL cooz, HPDF_REAL c2cx, HPDF_REAL c2cy, HPDF_REAL c2cz, HPDF_REAL roo, HPDF_REAL roll) |
627 | { |
628 | HPDF_REAL viewx, viewy, viewz; |
629 | HPDF_REAL leftx, lefty, leftz; |
630 | HPDF_REAL upx, upy, upz; |
631 | HPDF_REAL transx, transy, transz; |
632 | |
633 | HPDF_Array matrix; |
634 | HPDF_STATUS ret = HPDF_OK; |
635 | |
636 | HPDF_PTRACE ((" HPDF_3DView_SetCamera\n" )); |
637 | |
638 | if (view == NULL) { |
639 | return HPDF_INVALID_U3D_DATA; |
640 | } |
641 | |
642 | /* view vector (opposite to c2c) */ |
643 | viewx = -c2cx; |
644 | viewy = -c2cy; |
645 | viewz = -c2cz; |
646 | |
647 | /* c2c = (0, -1, 0) by default */ |
648 | if (viewx == 0.0 && viewy == 0.0 && viewz == 0.0) { |
649 | viewy = 1.0; |
650 | } |
651 | /* normalize view vector */ |
652 | normalize(viewx, viewy, viewz); |
653 | |
654 | /* rotation matrix */ |
655 | |
656 | /* top and bottom views */ |
657 | leftx = -1.0f; |
658 | lefty = 0.0f; |
659 | leftz = 0.0f; |
660 | |
661 | /* up-vector */ |
662 | if (viewz < 0.0) /* top view*/ |
663 | { |
664 | upx = 0.0f; |
665 | upy = 1.0f; |
666 | upz = 0.0f; |
667 | } |
668 | else /* bottom view*/ |
669 | { |
670 | upx = 0.0f; |
671 | upy =-1.0f; |
672 | upz = 0.0f; |
673 | } |
674 | |
675 | if ( fabs(viewx) + fabs(viewy) != 0.0f) /* other views than top and bottom*/ |
676 | { |
677 | /* up-vector = up_world - (up_world dot view) view*/ |
678 | upx = -viewz*viewx; |
679 | upy = -viewz*viewy; |
680 | upz = -viewz*viewz + 1.0f; |
681 | /* normalize up-vector*/ |
682 | normalize(upx, upy, upz); |
683 | /* left vector = up x view*/ |
684 | leftx = viewz*upy - viewy*upz; |
685 | lefty = viewx*upz - viewz*upx; |
686 | leftz = viewy*upx - viewx*upy; |
687 | /* normalize left vector*/ |
688 | normalize(leftx, lefty, leftz); |
689 | } |
690 | /* apply camera roll*/ |
691 | { |
692 | HPDF_REAL leftxprime, leftyprime, leftzprime; |
693 | HPDF_REAL upxprime, upyprime, upzprime; |
694 | HPDF_REAL sinroll, cosroll; |
695 | |
696 | sinroll = (HPDF_REAL)sin((roll/180.0f)*M_PI); |
697 | cosroll = (HPDF_REAL)cos((roll/180.0f)*M_PI); |
698 | leftxprime = leftx*cosroll + upx*sinroll; |
699 | leftyprime = lefty*cosroll + upy*sinroll; |
700 | leftzprime = leftz*cosroll + upz*sinroll; |
701 | upxprime = upx*cosroll + leftx*sinroll; |
702 | upyprime = upy*cosroll + lefty*sinroll; |
703 | upzprime = upz*cosroll + leftz*sinroll; |
704 | leftx = leftxprime; |
705 | lefty = leftyprime; |
706 | leftz = leftzprime; |
707 | upx = upxprime; |
708 | upy = upyprime; |
709 | upz = upzprime; |
710 | } |
711 | |
712 | /* translation vector*/ |
713 | roo = (HPDF_REAL)fabs(roo); |
714 | if (roo == 0.0) { |
715 | roo = (HPDF_REAL)0.000000000000000001; |
716 | } |
717 | transx = coox - roo*viewx; |
718 | transy = cooy - roo*viewy; |
719 | transz = cooz - roo*viewz; |
720 | |
721 | /* transformation matrix*/ |
722 | matrix = HPDF_Array_New (view->mmgr); |
723 | if (!matrix) { |
724 | return HPDF_Error_GetCode (view->error); |
725 | } |
726 | |
727 | ret = HPDF_Array_AddReal (matrix, leftx); |
728 | if (ret != HPDF_OK) goto failed; |
729 | |
730 | ret = HPDF_Array_AddReal (matrix, lefty); |
731 | if (ret != HPDF_OK) goto failed; |
732 | |
733 | ret = HPDF_Array_AddReal (matrix, leftz); |
734 | if (ret != HPDF_OK) goto failed; |
735 | |
736 | ret = HPDF_Array_AddReal (matrix, upx); |
737 | if (ret != HPDF_OK) goto failed; |
738 | |
739 | ret = HPDF_Array_AddReal (matrix, upy); |
740 | if (ret != HPDF_OK) goto failed; |
741 | |
742 | ret = HPDF_Array_AddReal (matrix, upz); |
743 | if (ret != HPDF_OK) goto failed; |
744 | |
745 | ret = HPDF_Array_AddReal (matrix, viewx); |
746 | if (ret != HPDF_OK) goto failed; |
747 | |
748 | ret = HPDF_Array_AddReal (matrix, viewy); |
749 | if (ret != HPDF_OK) goto failed; |
750 | |
751 | ret = HPDF_Array_AddReal (matrix, viewz); |
752 | if (ret != HPDF_OK) goto failed; |
753 | |
754 | ret = HPDF_Array_AddReal (matrix, transx); |
755 | if (ret != HPDF_OK) goto failed; |
756 | |
757 | ret = HPDF_Array_AddReal (matrix, transy); |
758 | if (ret != HPDF_OK) goto failed; |
759 | |
760 | ret = HPDF_Array_AddReal (matrix, transz); |
761 | if (ret != HPDF_OK) goto failed; |
762 | |
763 | ret = HPDF_Dict_AddName (view, "MS" , "M" ); |
764 | if (ret != HPDF_OK) goto failed; |
765 | |
766 | ret = HPDF_Dict_Add (view, "C2W" , matrix); |
767 | if (ret != HPDF_OK) goto failed; |
768 | |
769 | ret = HPDF_Dict_AddNumber (view, "CO" , (HPDF_INT32)roo); |
770 | |
771 | failed: |
772 | if (ret != HPDF_OK) { |
773 | HPDF_Array_Free (matrix); |
774 | return ret; |
775 | } |
776 | return ret; |
777 | } |
778 | |
779 | HPDF_Dict HPDF_3DView_New( HPDF_MMgr mmgr, HPDF_Xref xref, HPDF_U3D u3d, const char *name) |
780 | { |
781 | HPDF_STATUS ret = HPDF_OK; |
782 | HPDF_Dict view; |
783 | |
784 | HPDF_PTRACE ((" HPDF_3DView_New\n" )); |
785 | |
786 | if (name == NULL || name[0] == '\0') { |
787 | return NULL; |
788 | } |
789 | |
790 | view = HPDF_Dict_New (mmgr); |
791 | if (!view) { |
792 | return NULL; |
793 | } |
794 | |
795 | if (HPDF_Xref_Add (xref, view) != HPDF_OK) |
796 | return NULL; |
797 | |
798 | ret = HPDF_Dict_AddName (view, "TYPE" , "3DView" ); |
799 | if (ret != HPDF_OK) { |
800 | HPDF_Dict_Free (view); |
801 | return NULL; |
802 | } |
803 | |
804 | ret = HPDF_Dict_Add (view, "XN" , HPDF_String_New (mmgr, name, NULL)); |
805 | if (ret != HPDF_OK) { |
806 | HPDF_Dict_Free (view); |
807 | return NULL; |
808 | } |
809 | |
810 | ret = HPDF_Dict_Add (view, "IN" , HPDF_String_New (mmgr, name, NULL)); |
811 | if (ret != HPDF_OK) { |
812 | HPDF_Dict_Free (view); |
813 | return NULL; |
814 | } |
815 | |
816 | ret = HPDF_U3D_Add3DView( u3d, view); |
817 | if (ret != HPDF_OK) { |
818 | HPDF_Dict_Free (view); |
819 | return NULL; |
820 | } |
821 | |
822 | return view; |
823 | } |
824 | |
825 | |
826 | HPDF_EXPORT(HPDF_STATUS) |
827 | HPDF_3DView_Add3DC3DMeasure(HPDF_Dict view, |
828 | HPDF_3DMeasure measure) |
829 | { |
830 | |
831 | HPDF_STATUS ret = HPDF_OK; |
832 | HPDF_Array array; |
833 | void* a; |
834 | |
835 | a = HPDF_Dict_GetItem (view, "MA" , HPDF_OCLASS_ARRAY); |
836 | |
837 | if ( a ) |
838 | { |
839 | array = (HPDF_Array)a; |
840 | } |
841 | else |
842 | { |
843 | array = HPDF_Array_New (view->mmgr); |
844 | if (!array) |
845 | return 0; |
846 | |
847 | if (HPDF_Dict_Add (view, "MA" , array) != HPDF_OK) |
848 | return 0; |
849 | } |
850 | |
851 | ret = HPDF_Array_Add(array, measure); |
852 | |
853 | return ret; |
854 | } |
855 | |
856 | |
857 | HPDF_EXPORT(HPDF_JavaScript) HPDF_CreateJavaScript( HPDF_Doc pdf, const char *code ) |
858 | { |
859 | HPDF_JavaScript javaScript; |
860 | int len ; |
861 | |
862 | HPDF_PTRACE ((" HPDF_CreateJavaScript\n" )); |
863 | |
864 | javaScript = (HPDF_JavaScript) HPDF_DictStream_New(pdf->mmgr, pdf->xref); |
865 | if (!javaScript) { |
866 | return NULL; |
867 | } |
868 | |
869 | len = (HPDF_UINT)strlen(code); |
870 | if (HPDF_Stream_Write (javaScript->stream, (HPDF_BYTE *)code, len) != HPDF_OK) { |
871 | HPDF_Dict_Free(javaScript); |
872 | return NULL; |
873 | } |
874 | |
875 | return javaScript; |
876 | } |
877 | |
878 | |
879 | #undef normalize |
880 | |
881 | |