pdf_page * pdf_create_page(pdf_document *doc, fz_rect mediabox, int res, int rotate) { pdf_page *page = NULL; pdf_obj *pageobj; float userunit = 1; fz_context *ctx = doc->ctx; fz_matrix ctm, tmp; fz_rect realbox; page = fz_malloc_struct(ctx, pdf_page); fz_try(ctx) { page->resources = NULL; page->contents = NULL; page->transparency = 0; page->links = NULL; page->annots = NULL; page->me = pageobj = pdf_new_dict(doc, 4); pdf_dict_puts_drop(pageobj, "Type", pdf_new_name(doc, "Page")); page->mediabox.x0 = fz_min(mediabox.x0, mediabox.x1) * userunit; page->mediabox.y0 = fz_min(mediabox.y0, mediabox.y1) * userunit; page->mediabox.x1 = fz_max(mediabox.x0, mediabox.x1) * userunit; page->mediabox.y1 = fz_max(mediabox.y0, mediabox.y1) * userunit; pdf_dict_puts_drop(pageobj, "MediaBox", pdf_new_rect(doc, &page->mediabox)); /* Snap page->rotate to 0, 90, 180 or 270 */ if (page->rotate < 0) page->rotate = 360 - ((-page->rotate) % 360); if (page->rotate >= 360) page->rotate = page->rotate % 360; page->rotate = 90*((page->rotate + 45)/90); if (page->rotate > 360) page->rotate = 0; pdf_dict_puts_drop(pageobj, "Rotate", pdf_new_int(doc, page->rotate)); fz_pre_rotate(fz_scale(&ctm, 1, -1), -page->rotate); realbox = page->mediabox; fz_transform_rect(&realbox, &ctm); fz_pre_scale(fz_translate(&tmp, -realbox.x0, -realbox.y0), userunit, userunit); fz_concat(&ctm, &ctm, &tmp); page->ctm = ctm; /* Do not create a Contents, as an empty Contents dict is not * valid. See Bug 694712 */ } fz_catch(ctx) { pdf_drop_obj(page->me); fz_free(ctx, page); fz_rethrow_message(ctx, "Failed to create page"); } return page; }
void pdf_set_annot_rect(fz_context *ctx, pdf_annot *annot, const fz_rect *rect) { pdf_document *doc = annot->page->doc; fz_rect trect = *rect; fz_matrix page_ctm, inv_page_ctm; pdf_page_transform(ctx, annot->page, NULL, &page_ctm); fz_invert_matrix(&inv_page_ctm, &page_ctm); fz_transform_rect(&trect, &inv_page_ctm); pdf_dict_put_drop(ctx, annot->obj, PDF_NAME_Rect, pdf_new_rect(ctx, doc, &trect)); annot->changed = 1; }
void pdf_set_text_annot_position(fz_context *ctx, pdf_document *doc, pdf_annot *annot, fz_point pt) { fz_matrix ctm; fz_rect rect; int flags; fz_invert_matrix(&ctm, &annot->page->ctm); rect.x0 = pt.x; rect.x1 = pt.x + TEXT_ANNOT_SIZE; rect.y0 = pt.y; rect.y1 = pt.y + TEXT_ANNOT_SIZE; fz_transform_rect(&rect, &ctm); pdf_dict_put_drop(ctx, annot->obj, PDF_NAME_Rect, pdf_new_rect(ctx, doc, &rect)); flags = pdf_to_int(ctx, pdf_dict_get(ctx, annot->obj, PDF_NAME_F)); flags |= (F_NoZoom|F_NoRotate); pdf_dict_put_drop(ctx, annot->obj, PDF_NAME_F, pdf_new_int(ctx, doc, flags)); update_rect(ctx, annot); }
void pdf_set_text_annot_position(fz_context *ctx, pdf_annot *annot, fz_point pt) { pdf_document *doc = annot->page->doc; fz_matrix page_ctm, inv_page_ctm; fz_rect rect; int flags; pdf_page_transform(ctx, annot->page, NULL, &page_ctm); fz_invert_matrix(&inv_page_ctm, &page_ctm); rect.x0 = pt.x; rect.x1 = pt.x + TEXT_ANNOT_SIZE; rect.y0 = pt.y; rect.y1 = pt.y + TEXT_ANNOT_SIZE; fz_transform_rect(&rect, &inv_page_ctm); pdf_dict_put_drop(ctx, annot->obj, PDF_NAME_Rect, pdf_new_rect(ctx, doc, &rect)); flags = pdf_to_int(ctx, pdf_dict_get(ctx, annot->obj, PDF_NAME_F)); flags |= (PDF_ANNOT_IS_NO_ZOOM|PDF_ANNOT_IS_NO_ROTATE); pdf_dict_put_drop(ctx, annot->obj, PDF_NAME_F, pdf_new_int(ctx, doc, flags)); }
pdf_annot * pdf_create_annot(fz_context *ctx, pdf_page *page, fz_annot_type type) { pdf_annot *annot = NULL; pdf_document *doc = page->doc; pdf_obj *annot_obj = pdf_new_dict(ctx, doc, 0); pdf_obj *ind_obj = NULL; fz_var(annot); fz_var(ind_obj); fz_try(ctx) { int ind_obj_num; fz_rect rect = {0.0f, 0.0f, 0.0f, 0.0f}; const char *type_str; pdf_obj *annot_arr; type_str = pdf_string_from_annot_type(ctx, type); if (type == PDF_ANNOT_UNKNOWN) fz_throw(ctx, FZ_ERROR_GENERIC, "cannot create unknown annotation"); annot_arr = pdf_dict_get(ctx, page->obj, PDF_NAME_Annots); if (annot_arr == NULL) { annot_arr = pdf_new_array(ctx, doc, 0); pdf_dict_put_drop(ctx, page->obj, PDF_NAME_Annots, annot_arr); } pdf_dict_put_drop(ctx, annot_obj, PDF_NAME_Type, PDF_NAME_Annot); pdf_dict_put_drop(ctx, annot_obj, PDF_NAME_Subtype, pdf_new_name(ctx, doc, type_str)); pdf_dict_put_drop(ctx, annot_obj, PDF_NAME_Rect, pdf_new_rect(ctx, doc, &rect)); /* Make printable as default */ pdf_dict_put_drop(ctx, annot_obj, PDF_NAME_F, pdf_new_int(ctx, doc, PDF_ANNOT_IS_PRINT)); annot = pdf_new_annot(ctx, page); annot->ap = NULL; /* Both annotation object and annotation structure are now created. Insert the object in the hierarchy and the structure in the page's array. */ ind_obj_num = pdf_create_object(ctx, doc); pdf_update_object(ctx, doc, ind_obj_num, annot_obj); ind_obj = pdf_new_indirect(ctx, doc, ind_obj_num, 0); pdf_array_push(ctx, annot_arr, ind_obj); annot->obj = pdf_keep_obj(ctx, ind_obj); /* Linking must be done after any call that might throw because pdf_drop_annots below actually frees a list. Put the new annot at the end of the list, so that it will be drawn last. */ *page->annot_tailp = annot; page->annot_tailp = &annot->next; doc->dirty = 1; } fz_always(ctx) { pdf_drop_obj(ctx, annot_obj); pdf_drop_obj(ctx, ind_obj); } fz_catch(ctx) { pdf_drop_annots(ctx, annot); fz_rethrow(ctx); } return annot; }
void pdf_set_free_text_details(fz_context *ctx, pdf_annot *annot, fz_point *pos, char *text, char *font_name, float font_size, float color[3]) { pdf_document *doc = annot->page->doc; char nbuf[32]; pdf_obj *dr; pdf_obj *form_fonts; pdf_obj *font = NULL; pdf_obj *ref; pdf_font_desc *font_desc = NULL; fz_matrix page_ctm, inv_page_ctm; pdf_da_info da_info; fz_buffer *fzbuf = NULL; fz_point page_pos; pdf_page_transform(ctx, annot->page, NULL, &page_ctm); fz_invert_matrix(&inv_page_ctm, &page_ctm); dr = pdf_dict_get(ctx, annot->page->obj, PDF_NAME_Resources); if (!dr) { dr = pdf_new_dict(ctx, doc, 1); pdf_dict_put_drop(ctx, annot->page->obj, PDF_NAME_Resources, dr); } /* Ensure the resource dictionary includes a font dict */ form_fonts = pdf_dict_get(ctx, dr, PDF_NAME_Font); if (!form_fonts) { form_fonts = pdf_new_dict(ctx, doc, 1); pdf_dict_put_drop(ctx, dr, PDF_NAME_Font, form_fonts); /* form_fonts is still valid if execution continues past the above call */ } fz_var(fzbuf); fz_var(font); fz_try(ctx) { unsigned char *da_str; size_t da_len; fz_rect bounds; find_free_font_name(ctx, form_fonts, nbuf, sizeof(nbuf)); font = pdf_new_dict(ctx, doc, 5); ref = pdf_add_object(ctx, doc, font); pdf_dict_puts_drop(ctx, form_fonts, nbuf, ref); pdf_dict_put_drop(ctx, font, PDF_NAME_Type, PDF_NAME_Font); pdf_dict_put_drop(ctx, font, PDF_NAME_Subtype, PDF_NAME_Type1); pdf_dict_put_drop(ctx, font, PDF_NAME_BaseFont, pdf_new_name(ctx, doc, font_name)); pdf_dict_put_drop(ctx, font, PDF_NAME_Encoding, PDF_NAME_WinAnsiEncoding); memcpy(da_info.col, color, sizeof(float)*3); da_info.col_size = 3; da_info.font_name = nbuf; da_info.font_size = font_size; fzbuf = fz_new_buffer(ctx, 0); pdf_fzbuf_print_da(ctx, fzbuf, &da_info); da_len = fz_buffer_storage(ctx, fzbuf, &da_str); pdf_dict_put_drop(ctx, annot->obj, PDF_NAME_DA, pdf_new_string(ctx, doc, (char *)da_str, da_len)); /* FIXME: should convert to WinAnsiEncoding */ pdf_dict_put_drop(ctx, annot->obj, PDF_NAME_Contents, pdf_new_string(ctx, doc, text, strlen(text))); font_desc = pdf_load_font(ctx, doc, NULL, font, 0); pdf_measure_text(ctx, font_desc, (unsigned char *)text, strlen(text), &bounds); page_pos = *pos; fz_transform_point(&page_pos, &inv_page_ctm); bounds.x0 *= font_size; bounds.x1 *= font_size; bounds.y0 *= font_size; bounds.y1 *= font_size; bounds.x0 += page_pos.x; bounds.x1 += page_pos.x; bounds.y0 += page_pos.y; bounds.y1 += page_pos.y; pdf_dict_put_drop(ctx, annot->obj, PDF_NAME_Rect, pdf_new_rect(ctx, doc, &bounds)); } fz_always(ctx) { pdf_drop_obj(ctx, font); fz_drop_buffer(ctx, fzbuf); pdf_drop_font(ctx, font_desc); } fz_catch(ctx) { fz_rethrow(ctx); } }
pdf_annot * pdf_create_annot(fz_context *ctx, pdf_document *doc, pdf_page *page, fz_annot_type type) { pdf_annot *annot = NULL; pdf_obj *annot_obj = pdf_new_dict(ctx, doc, 0); pdf_obj *ind_obj = NULL; fz_var(annot); fz_var(ind_obj); fz_try(ctx) { int ind_obj_num; fz_rect rect = {0.0, 0.0, 0.0, 0.0}; const char *type_str = annot_type_str(type); pdf_obj *annot_arr = pdf_dict_get(ctx, page->me, PDF_NAME_Annots); if (annot_arr == NULL) { annot_arr = pdf_new_array(ctx, doc, 0); pdf_dict_put_drop(ctx, page->me, PDF_NAME_Annots, annot_arr); } pdf_dict_put_drop(ctx, annot_obj, PDF_NAME_Type, PDF_NAME_Annot); pdf_dict_put_drop(ctx, annot_obj, PDF_NAME_Subtype, pdf_new_name(ctx, doc, type_str)); pdf_dict_put_drop(ctx, annot_obj, PDF_NAME_Rect, pdf_new_rect(ctx, doc, &rect)); /* Make printable as default */ pdf_dict_put_drop(ctx, annot_obj, PDF_NAME_F, pdf_new_int(ctx, doc, F_Print)); annot = fz_malloc_struct(ctx, pdf_annot); annot->page = page; annot->rect = rect; annot->pagerect = rect; annot->ap = NULL; annot->widget_type = PDF_WIDGET_TYPE_NOT_WIDGET; annot->annot_type = type; /* Both annotation object and annotation structure are now created. Insert the object in the hierarchy and the structure in the page's array. */ ind_obj_num = pdf_create_object(ctx, doc); pdf_update_object(ctx, doc, ind_obj_num, annot_obj); ind_obj = pdf_new_indirect(ctx, doc, ind_obj_num, 0); pdf_array_push(ctx, annot_arr, ind_obj); annot->obj = pdf_keep_obj(ctx, ind_obj); /* Linking must be done after any call that might throw because pdf_drop_annot below actually frees a list. Put the new annot at the end of the list, so that it will be drawn last. */ *page->annot_tailp = annot; page->annot_tailp = &annot->next; doc->dirty = 1; } fz_always(ctx) { pdf_drop_obj(ctx, annot_obj); pdf_drop_obj(ctx, ind_obj); } fz_catch(ctx) { pdf_drop_annot(ctx, annot); fz_rethrow(ctx); } return annot; }
void pdf_set_ink_annot_list(fz_context *ctx, pdf_document *doc, pdf_annot *annot, fz_point *pts, int *counts, int ncount, float color[3], float thickness) { fz_matrix ctm; pdf_obj *list = pdf_new_array(ctx, doc, ncount); pdf_obj *bs, *col; fz_rect rect; int i, k = 0; fz_invert_matrix(&ctm, &annot->page->ctm); pdf_dict_put_drop(ctx, annot->obj, PDF_NAME_InkList, list); for (i = 0; i < ncount; i++) { int j; pdf_obj *arc = pdf_new_array(ctx, doc, counts[i]); pdf_array_push_drop(ctx, list, arc); for (j = 0; j < counts[i]; j++) { fz_point pt = pts[k]; fz_transform_point(&pt, &ctm); if (i == 0 && j == 0) { rect.x0 = rect.x1 = pt.x; rect.y0 = rect.y1 = pt.y; } else { fz_include_point_in_rect(&rect, &pt); } pdf_array_push_drop(ctx, arc, pdf_new_real(ctx, doc, pt.x)); pdf_array_push_drop(ctx, arc, pdf_new_real(ctx, doc, pt.y)); k++; } } /* Expand the rectangle by thickness all around. We cannot use fz_expand_rect because the rectangle might be empty in the single point case */ if (k > 0) { rect.x0 -= thickness; rect.y0 -= thickness; rect.x1 += thickness; rect.y1 += thickness; } pdf_dict_put_drop(ctx, annot->obj, PDF_NAME_Rect, pdf_new_rect(ctx, doc, &rect)); update_rect(ctx, annot); bs = pdf_new_dict(ctx, doc, 1); pdf_dict_put_drop(ctx, annot->obj, PDF_NAME_BS, bs); pdf_dict_put_drop(ctx, bs, PDF_NAME_W, pdf_new_real(ctx, doc, thickness)); col = pdf_new_array(ctx, doc, 3); pdf_dict_put_drop(ctx, annot->obj, PDF_NAME_C, col); for (i = 0; i < 3; i++) pdf_array_push_drop(ctx, col, pdf_new_real(ctx, doc, color[i])); }
void pdf_set_free_text_details(pdf_document *doc, pdf_annot *annot, fz_point *pos, char *text, char *font_name, float font_size, float color[3]) { fz_context *ctx = doc->ctx; char nbuf[32]; pdf_obj *dr; pdf_obj *form_fonts; pdf_obj *font = NULL; pdf_obj *ref; pdf_font_desc *font_desc = NULL; pdf_da_info da_info; fz_buffer *fzbuf = NULL; fz_matrix ctm; fz_point page_pos; fz_invert_matrix(&ctm, &annot->page->ctm); dr = pdf_dict_gets(annot->page->me, "Resources"); if (!dr) { dr = pdf_new_dict(doc, 1); pdf_dict_putp_drop(annot->page->me, "Resources", dr); } /* Ensure the resource dictionary includes a font dict */ form_fonts = pdf_dict_gets(dr, "Font"); if (!form_fonts) { form_fonts = pdf_new_dict(doc, 1); pdf_dict_puts_drop(dr, "Font", form_fonts); /* form_fonts is still valid if execution continues past the above call */ } fz_var(fzbuf); fz_var(font); fz_try(ctx) { unsigned char *da_str; int da_len; fz_rect bounds; find_free_font_name(form_fonts, nbuf, sizeof(nbuf)); font = pdf_new_dict(doc, 5); ref = pdf_new_ref(doc, font); pdf_dict_puts_drop(form_fonts, nbuf, ref); pdf_dict_puts_drop(font, "Type", pdf_new_name(doc, "Font")); pdf_dict_puts_drop(font, "Subtype", pdf_new_name(doc, "Type1")); pdf_dict_puts_drop(font, "BaseFont", pdf_new_name(doc, font_name)); pdf_dict_puts_drop(font, "Encoding", pdf_new_name(doc, "WinAnsiEncoding")); memcpy(da_info.col, color, sizeof(float)*3); da_info.col_size = 3; da_info.font_name = nbuf; da_info.font_size = font_size; fzbuf = fz_new_buffer(ctx, 0); pdf_fzbuf_print_da(ctx, fzbuf, &da_info); da_len = fz_buffer_storage(ctx, fzbuf, &da_str); pdf_dict_puts_drop(annot->obj, "DA", pdf_new_string(doc, (char *)da_str, da_len)); /* FIXME: should convert to WinAnsiEncoding */ pdf_dict_puts_drop(annot->obj, "Contents", pdf_new_string(doc, text, strlen(text))); font_desc = pdf_load_font(doc, NULL, font, 0); pdf_measure_text(ctx, font_desc, (unsigned char *)text, strlen(text), &bounds); page_pos = *pos; fz_transform_point(&page_pos, &ctm); bounds.x0 *= font_size; bounds.x1 *= font_size; bounds.y0 *= font_size; bounds.y1 *= font_size; bounds.x0 += page_pos.x; bounds.x1 += page_pos.x; bounds.y0 += page_pos.y; bounds.y1 += page_pos.y; pdf_dict_puts_drop(annot->obj, "Rect", pdf_new_rect(doc, &bounds)); update_rect(ctx, annot); } fz_always(ctx) { pdf_drop_obj(font); fz_drop_buffer(ctx, fzbuf); pdf_drop_font(ctx, font_desc); } fz_catch(ctx) { fz_rethrow(ctx); } }
pdf_obj * pdf_new_xobject(pdf_document *doc, const fz_rect *bbox, const fz_matrix *mat) { int idict_num; pdf_obj *idict = NULL; pdf_obj *dict = NULL; pdf_xobject *form = NULL; pdf_obj *obj = NULL; pdf_obj *res = NULL; pdf_obj *procset = NULL; fz_context *ctx = doc->ctx; fz_var(idict); fz_var(dict); fz_var(form); fz_var(obj); fz_var(res); fz_var(procset); fz_try(ctx) { dict = pdf_new_dict(doc, 0); obj = pdf_new_rect(doc, bbox); pdf_print_obj(obj); pdf_dict_puts(dict, "BBox", obj); pdf_drop_obj(obj); obj = NULL; obj = pdf_new_int(doc, 1); pdf_dict_puts(dict, "FormType", obj); pdf_drop_obj(obj); obj = NULL; obj = pdf_new_int(doc, 0); pdf_dict_puts(dict, "Length", obj); pdf_drop_obj(obj); obj = NULL; obj = pdf_new_matrix(doc, mat); pdf_dict_puts(dict, "Matrix", obj); pdf_drop_obj(obj); obj = NULL; res = pdf_new_dict(doc, 0); procset = pdf_new_array(doc, 2); obj = pdf_new_name(doc, "PDF"); pdf_array_push(procset, obj); pdf_drop_obj(obj); obj = NULL; obj = pdf_new_name(doc, "Text"); pdf_array_push(procset, obj); pdf_drop_obj(obj); obj = NULL; pdf_dict_puts(res, "ProcSet", procset); pdf_drop_obj(procset); procset = NULL; pdf_dict_puts(dict, "Resources", res); obj = pdf_new_name(doc, "Form"); pdf_dict_puts(dict, "Subtype", obj); pdf_drop_obj(obj); obj = NULL; obj = pdf_new_name(doc, "XObject"); pdf_dict_puts(dict, "Type", obj); pdf_drop_obj(obj); obj = NULL; form = fz_malloc_struct(ctx, pdf_xobject); FZ_INIT_STORABLE(form, 1, pdf_free_xobject_imp); form->resources = NULL; form->contents = NULL; form->colorspace = NULL; form->me = NULL; form->iteration = 0; form->bbox = *bbox; form->matrix = *mat; form->isolated = 0; form->knockout = 0; form->transparency = 0; form->resources = res; res = NULL; idict_num = pdf_create_object(doc); pdf_update_object(doc, idict_num, dict); idict = pdf_new_indirect(doc, idict_num, 0); pdf_drop_obj(dict); dict = NULL; pdf_store_item(ctx, idict, form, pdf_xobject_size(form)); form->contents = pdf_keep_obj(idict); form->me = pdf_keep_obj(idict); pdf_drop_xobject(ctx, form); form = NULL; } fz_catch(ctx) { pdf_drop_obj(procset); pdf_drop_obj(res); pdf_drop_obj(obj); pdf_drop_obj(dict); pdf_drop_obj(idict); pdf_drop_xobject(ctx, form); fz_rethrow_message(ctx, "failed to create xobject)"); } return idict; }