Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. #include "fitz.h"
  2. #include "mupdf.h"
  3.  
  4. void
  5. pdf_free_link(pdf_link *link)
  6. {
  7.         if (link->next)
  8.                 pdf_free_link(link->next);
  9.         if (link->dest)
  10.                 fz_drop_obj(link->dest);
  11.         fz_free(link);
  12. }
  13.  
  14. static fz_obj *
  15. resolve_dest(pdf_xref *xref, fz_obj *dest)
  16. {
  17.         if (fz_is_name(dest) || fz_is_string(dest))
  18.         {
  19.                 dest = pdf_lookup_dest(xref, dest);
  20.                 return resolve_dest(xref, dest);
  21.         }
  22.  
  23.         else if (fz_is_array(dest))
  24.         {
  25.                 return dest;
  26.         }
  27.  
  28.         else if (fz_is_dict(dest))
  29.         {
  30.                 dest = fz_dict_gets(dest, "D");
  31.                 return resolve_dest(xref, dest);
  32.         }
  33.  
  34.         else if (fz_is_indirect(dest))
  35.                 return dest;
  36.  
  37.         return NULL;
  38. }
  39.  
  40. pdf_link *
  41. pdf_load_link(pdf_xref *xref, fz_obj *dict)
  42. {
  43.         fz_obj *dest;
  44.         fz_obj *action;
  45.         fz_obj *obj;
  46.         fz_rect bbox;
  47.         pdf_link_kind kind;
  48.  
  49.         dest = NULL;
  50.  
  51.         obj = fz_dict_gets(dict, "Rect");
  52.         if (obj)
  53.                 bbox = pdf_to_rect(obj);
  54.         else
  55.                 bbox = fz_empty_rect;
  56.  
  57.         obj = fz_dict_gets(dict, "Dest");
  58.         if (obj)
  59.         {
  60.                 kind = PDF_LINK_GOTO;
  61.                 dest = resolve_dest(xref, obj);
  62.         }
  63.  
  64.         action = fz_dict_gets(dict, "A");
  65.  
  66.         /* fall back to additional action button's down/up action */
  67.         if (!action)
  68.                 action = fz_dict_getsa(fz_dict_gets(dict, "AA"), "U", "D");
  69.  
  70.         if (action)
  71.         {
  72.                 obj = fz_dict_gets(action, "S");
  73.                 if (fz_is_name(obj) && !strcmp(fz_to_name(obj), "GoTo"))
  74.                 {
  75.                         kind = PDF_LINK_GOTO;
  76.                         dest = resolve_dest(xref, fz_dict_gets(action, "D"));
  77.                 }
  78.                 else if (fz_is_name(obj) && !strcmp(fz_to_name(obj), "URI"))
  79.                 {
  80.                         kind = PDF_LINK_URI;
  81.                         dest = fz_dict_gets(action, "URI");
  82.                 }
  83.                 else if (fz_is_name(obj) && !strcmp(fz_to_name(obj), "Launch"))
  84.                 {
  85.                         kind = PDF_LINK_LAUNCH;
  86.                         dest = fz_dict_gets(action, "F");
  87.                 }
  88.                 else if (fz_is_name(obj) && !strcmp(fz_to_name(obj), "Named"))
  89.                 {
  90.                         kind = PDF_LINK_NAMED;
  91.                         dest = fz_dict_gets(action, "N");
  92.                 }
  93.                 else if (fz_is_name(obj) && (!strcmp(fz_to_name(obj), "GoToR")))
  94.                 {
  95.                         kind = PDF_LINK_ACTION;
  96.                         dest = action;
  97.                 }
  98.                 else
  99.                 {
  100.                         dest = NULL;
  101.                 }
  102.         }
  103.  
  104.         if (dest)
  105.         {
  106.                 pdf_link *link = fz_malloc(sizeof(pdf_link));
  107.                 link->kind = kind;
  108.                 link->rect = bbox;
  109.                 link->dest = fz_keep_obj(dest);
  110.                 link->next = NULL;
  111.                 return link;
  112.         }
  113.  
  114.         return NULL;
  115. }
  116.  
  117. void
  118. pdf_load_links(pdf_link **linkp, pdf_xref *xref, fz_obj *annots)
  119. {
  120.         pdf_link *link, *head, *tail;
  121.         fz_obj *obj;
  122.         int i;
  123.  
  124.         head = tail = NULL;
  125.         link = NULL;
  126.  
  127.         for (i = 0; i < fz_array_len(annots); i++)
  128.         {
  129.                 obj = fz_array_get(annots, i);
  130.                 link = pdf_load_link(xref, obj);
  131.                 if (link)
  132.                 {
  133.                         if (!head)
  134.                                 head = tail = link;
  135.                         else
  136.                         {
  137.                                 tail->next = link;
  138.                                 tail = link;
  139.                         }
  140.                 }
  141.         }
  142.  
  143.         *linkp = head;
  144. }
  145.  
  146. void
  147. pdf_free_annot(pdf_annot *annot)
  148. {
  149.         if (annot->next)
  150.                 pdf_free_annot(annot->next);
  151.         if (annot->ap)
  152.                 pdf_drop_xobject(annot->ap);
  153.         if (annot->obj)
  154.                 fz_drop_obj(annot->obj);
  155.         fz_free(annot);
  156. }
  157.  
  158. static void
  159. pdf_transform_annot(pdf_annot *annot)
  160. {
  161.         fz_matrix matrix = annot->ap->matrix;
  162.         fz_rect bbox = annot->ap->bbox;
  163.         fz_rect rect = annot->rect;
  164.         float w, h, x, y;
  165.  
  166.         bbox = fz_transform_rect(matrix, bbox);
  167.         w = (rect.x1 - rect.x0) / (bbox.x1 - bbox.x0);
  168.         h = (rect.y1 - rect.y0) / (bbox.y1 - bbox.y0);
  169.         x = rect.x0 - bbox.x0;
  170.         y = rect.y0 - bbox.y0;
  171.  
  172.         annot->matrix = fz_concat(fz_scale(w, h), fz_translate(x, y));
  173. }
  174.  
  175. void
  176. pdf_load_annots(pdf_annot **annotp, pdf_xref *xref, fz_obj *annots)
  177. {
  178.         pdf_annot *annot, *head, *tail;
  179.         fz_obj *obj, *ap, *as, *n, *rect;
  180.         pdf_xobject *form;
  181.         fz_error error;
  182.         int i;
  183.  
  184.         head = tail = NULL;
  185.         annot = NULL;
  186.  
  187.         for (i = 0; i < fz_array_len(annots); i++)
  188.         {
  189.                 obj = fz_array_get(annots, i);
  190.  
  191.                 rect = fz_dict_gets(obj, "Rect");
  192.                 ap = fz_dict_gets(obj, "AP");
  193.                 as = fz_dict_gets(obj, "AS");
  194.                 if (fz_is_dict(ap))
  195.                 {
  196.                         n = fz_dict_gets(ap, "N"); /* normal state */
  197.  
  198.                         /* lookup current state in sub-dictionary */
  199.                         if (!pdf_is_stream(xref, fz_to_num(n), fz_to_gen(n)))
  200.                                 n = fz_dict_get(n, as);
  201.  
  202.                         if (pdf_is_stream(xref, fz_to_num(n), fz_to_gen(n)))
  203.                         {
  204.                                 error = pdf_load_xobject(&form, xref, n);
  205.                                 if (error)
  206.                                 {
  207.                                         fz_catch(error, "ignoring broken annotation");
  208.                                         continue;
  209.                                 }
  210.  
  211.                                 annot = fz_malloc(sizeof(pdf_annot));
  212.                                 annot->obj = fz_keep_obj(obj);
  213.                                 annot->rect = pdf_to_rect(rect);
  214.                                 annot->ap = form;
  215.                                 annot->next = NULL;
  216.  
  217.                                 pdf_transform_annot(annot);
  218.  
  219.                                 if (annot)
  220.                                 {
  221.                                         if (!head)
  222.                                                 head = tail = annot;
  223.                                         else
  224.                                         {
  225.                                                 tail->next = annot;
  226.                                                 tail = annot;
  227.                                         }
  228.                                 }
  229.                         }
  230.                 }
  231.         }
  232.  
  233.         *annotp = head;
  234. }
  235.