void write_pdfstream(PDF pdf, image_dict * idict) { pdf_begin_obj(pdf, img_objnum(idict), OBJSTM_NEVER); pdf_begin_dict(pdf); if (!img_notype(idict)) { pdf_dict_add_name(pdf, "Type", "XObject"); pdf_dict_add_name(pdf, "Subtype", "Form"); pdf_dict_add_int(pdf, "FormType", 1); } if (!img_nobbox(idict)) { pdf_add_name(pdf, "BBox"); pdf_begin_array(pdf); pdf_add_real(pdf, sp2bp(img_bbox(idict)[0])); pdf_add_real(pdf, sp2bp(img_bbox(idict)[1])); pdf_add_real(pdf, sp2bp(img_bbox(idict)[2])); pdf_add_real(pdf, sp2bp(img_bbox(idict)[3])); pdf_end_array(pdf); } if (img_attr(idict) != NULL && strlen(img_attr(idict)) > 0) { pdf_printf(pdf, "\n%s\n", img_attr(idict)); } if (!img_nolength(idict)) { pdf_dict_add_streaminfo(pdf); } pdf_end_dict(pdf); pdf_begin_stream(pdf); if (img_pdfstream_stream(idict) != NULL) { pdf_out_block(pdf, (const char *) img_pdfstream_stream(idict), img_pdfstream_size(idict)); } pdf_end_stream(pdf); pdf_end_obj(pdf); }
void pdf_begin_contents_section(PDF *p) { if (p->contents != c_none) return; if (p->next_content >= p->contents_ids_capacity) { p->contents_ids_capacity *= 2; p->contents_ids = (id *) p->realloc(p, p->contents_ids, sizeof(long) * p->contents_ids_capacity, "pdf_begin_contents_section"); } p->contents_ids[p->next_content] = pdf_begin_obj(p, NEW_ID); p->contents = c_page; pdf_begin_dict(p); p->contents_length_id = pdf_alloc_id(p); pdf_printf(p, "/Length %ld 0 R\n", p->contents_length_id); if (p->compresslevel) pdf_puts(p, "/Filter/FlateDecode\n"); pdf_end_dict(p); pdf_begin_stream(p); pdf_compress_init(p); /* Contents object */ p->start_contents_pos = pdf_tell(p); p->next_content++; }
static int l_immediateobj(lua_State * L) { int n, first_arg = 1; int k; lstring buf; const_lstring st1,st2, st3; const char *st1_s = NULL; st1.s = st2.s = st3.s = NULL; check_o_mode(static_pdf, "immediateobj()", 1 << OMODE_PDF, true); if (global_shipping_mode != NOT_SHIPPING) luaL_error(L, "pdf.immediateobj() can not be used with \\latelua"); n = lua_gettop(L); if ((n > 0) && (lua_type(L, 1) == LUA_TNUMBER)) { first_arg++; k = (int) lua_tointeger(L, 1); check_obj_type(static_pdf, obj_type_obj, k); if (is_obj_scheduled(static_pdf, k) || obj_data_ptr(static_pdf, k) != 0) luaL_error(L, "pdf.immediateobj() object in use"); } else { static_pdf->obj_count++; k = pdf_create_obj(static_pdf, obj_type_obj, static_pdf->obj_ptr + 1); } pdf_last_obj = k; switch (n - first_arg + 1) { case 0: luaL_error(L, "pdf.immediateobj() needs at least one argument"); break; case 1: if (!lua_isstring(L, first_arg)) /* or number */ luaL_error(L, "pdf.immediateobj() 1st argument must be string"); pdf_begin_obj(static_pdf, k, OBJSTM_ALWAYS); st1.s = lua_tolstring(L, first_arg, &st1.l); pdf_out_block(static_pdf, st1.s, st1.l); pdf_end_obj(static_pdf); break; case 2: case 3: if (lua_type(L,first_arg) != LUA_TSTRING) luaL_error(L, "pdf.immediateobj() 1st argument must be string"); if (!lua_isstring(L, first_arg + 1)) /* or number */ luaL_error(L, "pdf.immediateobj() 2nd argument must be string"); st1_s = lua_tostring(L, first_arg); st2.s = lua_tolstring(L, first_arg + 1, &st2.l); if (lua_key_eq(st1_s, file)) { if (n == first_arg + 2) luaL_error(L, "pdf.immediateobj() 3rd argument forbidden in file mode"); pdf_begin_obj(static_pdf, k, OBJSTM_ALWAYS); buf.s = fread_to_buf(L, st2.s, &buf.l); pdf_out_block(static_pdf, (const char *) buf.s, buf.l); xfree(buf.s); pdf_end_obj(static_pdf); } else { pdf_begin_obj(static_pdf, k, OBJSTM_NEVER); /* not an object stream candidate! */ pdf_begin_dict(static_pdf); if (n == first_arg + 2) { /* write attr text */ if (!lua_isstring(L, first_arg + 2)) /* or number (maybe only string as it's an attr) */ luaL_error(L, "pdf.immediateobj() 3rd argument must be string"); st3.s = lua_tolstring(L, first_arg + 2, &st3.l); pdf_out_block(static_pdf, st3.s, st3.l); if (st3.s[st3.l - 1] != '\n') pdf_out(static_pdf, '\n'); } pdf_dict_add_streaminfo(static_pdf); pdf_end_dict(static_pdf); pdf_begin_stream(static_pdf); if (lua_key_eq(st1_s, stream)) { pdf_out_block(static_pdf, st2.s, st2.l); } else if (lua_key_eq(st1_s, streamfile)) { buf.s = fread_to_buf(L, st2.s, &buf.l); pdf_out_block(static_pdf, (const char *) buf.s, buf.l); xfree(buf.s); } else luaL_error(L, "pdf.immediateobj() invalid argument"); pdf_end_stream(static_pdf); pdf_end_obj(static_pdf); } break; default: luaL_error(L, "pdf.immediateobj() allows max. 3 arguments"); } lua_pushinteger(L, k); return 1; }
static int table_obj(lua_State * L) { const char *type; int k, obj_compression; int compress_level = -1; /* unset */ int os_threshold = OBJSTM_ALWAYS; /* default: put non-stream objects into object streams */ int saved_compress_level = static_pdf->compress_level; const_lstring attr, st; lstring buf; int immediate = 0; /* default: not immediate */ attr.s = st.s = NULL; attr.l = 0; assert(lua_istable(L, 1)); /* t */ lua_key_rawgeti(type); if (lua_isnil(L, -1)) /* !vs t */ luaL_error(L, "pdf.obj(): object \"type\" missing"); if (lua_type(L,-1) != LUA_TSTRING) /* !vs t */ luaL_error(L, "pdf.obj(): object \"type\" must be string"); type = lua_tostring(L, -1); if (! (lua_key_eq(type, raw) || lua_key_eq(type, stream))) { luaL_error(L, "pdf.obj(): \"%s\" is not a valid object type", type); /* i vs t */ } lua_pop(L, 1); /* t */ lua_key_rawgeti(immediate); if (!lua_isnil(L, -1)) { /* b? t */ if (!lua_isboolean(L, -1)) /* !b t */ luaL_error(L, "pdf.obj(): \"immediate\" must be boolean"); immediate = lua_toboolean(L, -1); /* 0 or 1 */ } lua_pop(L, 1); /* t */ /* is a reserved object referenced by "objnum"? */ lua_key_rawgeti(objnum); if (!lua_isnil(L, -1)) { /* vi? t */ if (lua_type(L,-1) != LUA_TNUMBER) /* !vi t */ luaL_error(L, "pdf.obj(): \"objnum\" must be integer"); k = (int) lua_tointeger(L, -1); /* vi t */ check_obj_type(static_pdf, obj_type_obj, k); if (is_obj_scheduled(static_pdf, k) || obj_data_ptr(static_pdf, k) != 0) luaL_error(L, "pdf.obj() object in use"); } else { static_pdf->obj_count++; k = pdf_create_obj(static_pdf, obj_type_obj, static_pdf->obj_ptr + 1); } pdf_last_obj = k; if (immediate == 0) { obj_data_ptr(static_pdf, k) = pdf_get_mem(static_pdf, pdfmem_obj_size); init_obj_obj(static_pdf, k); } lua_pop(L, 1); /* t */ /* get optional "attr" (allowed only for stream case) */ lua_key_rawgeti(attr); if (!lua_isnil(L, -1)) { /* attr-s? t */ if (! lua_key_eq(type, stream)) luaL_error(L, "pdf.obj(): \"attr\" key not allowed for non-stream object"); if (!lua_isstring(L, -1)) /* or number */ /* !attr-s t */ luaL_error(L, "pdf.obj(): object \"attr\" must be string"); if (immediate == 1) { attr.s = lua_tolstring(L, -1, &attr.l); /* attr-s t */ lua_pop(L, 1); /* t */ } else obj_obj_stream_attr(static_pdf, k) = luaL_ref(Luas, LUA_REGISTRYINDEX); /* t */ } else { lua_pop(L, 1); /* t */ } /* get optional "compresslevel" (allowed only for stream case) */ lua_key_rawgeti(compresslevel); if (!lua_isnil(L, -1)) { /* vi? t */ if (lua_key_eq(type, raw)) luaL_error(L, "pdf.obj(): \"compresslevel\" key not allowed for raw object"); if (lua_type(L, -1) != LUA_TNUMBER) /* !vi t */ luaL_error(L, "pdf.obj(): \"compresslevel\" must be integer"); compress_level = (int) lua_tointeger(L, -1); /* vi t */ if (compress_level > 9) luaL_error(L, "pdf.obj(): \"compresslevel\" must be <= 9"); else if (compress_level < 0) luaL_error(L, "pdf.obj(): \"compresslevel\" must be >= 0"); if (immediate == 0) obj_obj_pdfcompresslevel(static_pdf, k) = compress_level; } lua_pop(L, 1); /* t */ /* get optional "objcompression" (allowed only for non-stream case) */ lua_key_rawgeti(objcompression); if (!lua_isnil(L, -1)) { /* b? t */ if (lua_key_eq(type, stream)) luaL_error(L, "pdf.obj(): \"objcompression\" key not allowed for stream object"); if (!lua_isboolean(L, -1)) /* !b t */ luaL_error(L, "pdf.obj(): \"objcompression\" must be boolean"); obj_compression = lua_toboolean(L, -1); /* 0 or 1 */ /* OBJSTM_NEVER: never into object stream; OBJSTM_ALWAYS: depends then on \pdfobjcompresslevel */ if (obj_compression > 0) os_threshold = OBJSTM_ALWAYS; else os_threshold = OBJSTM_NEVER; if (immediate == 0) obj_obj_objstm_threshold(static_pdf, k) = os_threshold; } lua_pop(L, 1); /* t */ /* now the object contents for all cases are handled */ lua_key_rawgeti(string); lua_key_rawgeti_n(file,-2); if (!lua_isnil(L, -1) && !lua_isnil(L, -2)) /* file-s? string-s? t */ luaL_error(L, "pdf.obj(): \"string\" and \"file\" must not be given together"); if (lua_isnil(L, -1) && lua_isnil(L, -2)) /* nil nil t */ luaL_error(L, "pdf.obj(): no \"string\" or \"file\" given"); if (lua_key_eq(type, raw)) { if (immediate == 1) pdf_begin_obj(static_pdf, k, os_threshold); if (!lua_isnil(L, -2)) { /* file-s? string-s? t */ /* from string */ lua_pop(L, 1); /* string-s? t */ if (!lua_isstring(L, -1)) /* or number */ /* !string-s t */ luaL_error(L, "pdf.obj(): \"string\" must be string for raw object"); if (immediate == 1) { st.s = lua_tolstring(L, -1, &st.l); pdf_out_block(static_pdf, st.s, st.l); } else obj_obj_data(static_pdf, k) = luaL_ref(L, LUA_REGISTRYINDEX); /* t */ } else { /* from file */ if (lua_type(L, -1) != LUA_TSTRING) /* !file-s nil t */ luaL_error(L, "pdf.obj(): \"file\" name must be string for raw object"); if (immediate == 1) { st.s = lua_tolstring(L, -1, &st.l); /* file-s nil t */ buf.s = fread_to_buf(L, st.s, &buf.l); pdf_out_block(static_pdf, (const char *) buf.s, buf.l); /* already in pdf_end_obj: if (buf.s[buf.l - 1] != '\n') pdf_out(static_pdf, '\n'); */ xfree(buf.s); } else { set_obj_obj_is_file(static_pdf, k); obj_obj_data(static_pdf, k) = luaL_ref(L, LUA_REGISTRYINDEX); /* nil t */ } } if (immediate == 1) pdf_end_obj(static_pdf); } else { if (immediate == 1) { pdf_begin_obj(static_pdf, k, OBJSTM_NEVER); /* 0 = not an object stream candidate! */ pdf_begin_dict(static_pdf); if (attr.s != NULL) { pdf_out_block(static_pdf, attr.s, attr.l); if (attr.s[attr.l - 1] != '\n') pdf_out(static_pdf, '\n'); } if (compress_level > -1) static_pdf->compress_level = compress_level; pdf_dict_add_streaminfo(static_pdf); pdf_end_dict(static_pdf); pdf_begin_stream(static_pdf); } else { set_obj_obj_is_stream(static_pdf, k); if (compress_level > -1) obj_obj_pdfcompresslevel(static_pdf, k) = compress_level; } if (!lua_isnil(L, -2)) { /* file-s? string-s? t */ /* from string */ lua_pop(L, 1); /* string-s? t */ if (!lua_isstring(L, -1)) /* or number */ /* !string-s t */ luaL_error(L, "pdf.obj(): \"string\" must be string for stream object"); if (immediate == 1) { st.s = lua_tolstring(L, -1, &st.l); /* string-s t */ pdf_out_block(static_pdf, st.s, st.l); } else obj_obj_data(static_pdf, k) = luaL_ref(L, LUA_REGISTRYINDEX); /* t */ } else { /* from file */ if (lua_type(L, -1) != LUA_TSTRING) /* !file-s nil t */ luaL_error(L, "pdf.obj(): \"file\" name must be string for stream object"); if (immediate == 1) { st.s = lua_tolstring(L, -1, &st.l); /* file-s nil t */ buf.s = fread_to_buf(L, st.s, &buf.l); pdf_out_block(static_pdf, (const char *) buf.s, buf.l); xfree(buf.s); } else { set_obj_obj_is_file(static_pdf, k); obj_obj_data(static_pdf, k) = luaL_ref(L, LUA_REGISTRYINDEX); /* nil t */ } } if (immediate == 1) { pdf_end_stream(static_pdf); pdf_end_obj(static_pdf); } } static_pdf->compress_level = saved_compress_level; return k; }
void pdf_write_page_annots(PDF *p) { pdf_annot *ann; long length, start_pos; id length_id; PDF_data_source src; for (ann = p->annots; ann != NULL; ann = ann->next) { pdf_begin_obj(p, ann->obj_id); /* Annotation object */ pdf_begin_dict(p); /* Annotation dict */ pdf_puts(p, "/Type/Annot\n"); switch (ann->type) { case ann_text: pdf_puts(p, "/Subtype/Text\n"); pdf_printf(p, "/Rect[%f %f %f %f]\n", ann->rect.llx, ann->rect.lly, ann->rect.urx, ann->rect.ury); pdf_write_border_style(p, ann); if (ann->open) pdf_puts(p, "/Open true\n"); if (ann->icon != icon_text_note) /* note is default */ pdf_printf(p, "/Name/%s\n", pdf_icon_names[ann->icon]); /* Contents key is required, but may be empty */ pdf_puts(p, "/Contents"); if (ann->contents) { pdf_quote_string(p, ann->contents); pdf_putc(p, PDF_NEWLINE); } else pdf_puts(p, "()\n"); /* empty contents is OK */ /* title is optional */ if (ann->title) { pdf_puts(p, "/T"); pdf_quote_string(p, ann->title); pdf_putc(p, PDF_NEWLINE); } break; case ann_locallink: pdf_puts(p, "/Subtype/Link\n"); pdf_printf(p, "/Rect[%f %f %f %f]\n", ann->rect.llx, ann->rect.lly, ann->rect.urx, ann->rect.ury); pdf_write_border_style(p, ann); /* preallocate page object id for a later page */ if (ann->dest.page > p->current_page) { while (ann->dest.page >= p->pages_capacity) pdf_grow_pages(p); /* if this page has already been used as a link target * it will already have an object id. */ if (p->pages[ann->dest.page] == BAD_ID) p->pages[ann->dest.page] = pdf_alloc_id(p); } if (ann->dest.type == retain) { pdf_printf(p, "/Dest[%ld 0 R/XYZ null null 0]\n", p->pages[ann->dest.page]); } else if (ann->dest.type == fitpage) { pdf_printf(p, "/Dest[%ld 0 R/Fit]\n", p->pages[ann->dest.page]); } else if (ann->dest.type == fitwidth) { pdf_printf(p, "/Dest[%ld 0 R/FitH 0]\n", p->pages[ann->dest.page]); } else if (ann->dest.type == fitheight) { pdf_printf(p, "/Dest[%ld 0 R/FitV 0]\n", p->pages[ann->dest.page]); } else if (ann->dest.type == fitbbox) { pdf_printf(p, "/Dest[%ld 0 R/FitB]\n", p->pages[ann->dest.page]); } break; case ann_pdflink: pdf_puts(p, "/Subtype/Link\n"); pdf_printf(p, "/Rect[%f %f %f %f]\n", ann->rect.llx, ann->rect.lly, ann->rect.urx, ann->rect.ury); pdf_write_border_style(p, ann); pdf_puts(p, "/A"); pdf_begin_dict(p); /* A dict */ pdf_puts(p, "/Type/Action/S/GoToR\n"); if (ann->dest.type == retain) { pdf_printf(p, "/D[%d 0 R/XYZ null null 0]\n", ann->dest.page-1); /* zero-based */ } else if (ann->dest.type == fitpage) { /* zero-based */ pdf_printf(p, "/D[%d 0 R/Fit]\n", ann->dest.page-1); } else if (ann->dest.type == fitwidth) { /* Trick: we don't know the height of a future page yet, * so we use a "large" value for top which will do for * most pages. If it doesn't work, not much harm is done. */ /* zero-based */ pdf_printf(p, "/D[%d 0 R/FitH 2000]\n", ann->dest.page-1); } else if (ann->dest.type == fitheight) { /* zero-based */ pdf_printf(p, "/D[%d 0 R/FitV 0]\n", ann->dest.page-1); } else if (ann->dest.type == fitbbox) { /* zero-based */ pdf_printf(p, "/D[%d 0 R/FitB]\n", ann->dest.page-1); } pdf_puts(p, "/F"); pdf_begin_dict(p); /* F dict */ pdf_puts(p, "/Type/FileSpec\n"); pdf_printf(p, "/F("); pdf_puts(p, ann->filename); pdf_puts(p,")\n"); pdf_end_dict(p); /* F dict */ pdf_end_dict(p); /* A dict */ break; case ann_launchlink: pdf_puts(p, "/Subtype/Link\n"); pdf_printf(p, "/Rect[%f %f %f %f]\n", ann->rect.llx, ann->rect.lly, ann->rect.urx, ann->rect.ury); pdf_write_border_style(p, ann); pdf_puts(p, "/A"); pdf_begin_dict(p); /* A dict */ pdf_puts(p, "/Type/Action/S/Launch\n"); pdf_puts(p, "/F"); pdf_begin_dict(p); /* F dict */ pdf_puts(p, "/Type/FileSpec\n"); pdf_printf(p, "/F("); pdf_puts(p, ann->filename); pdf_puts(p,")\n"); pdf_end_dict(p); /* F dict */ pdf_end_dict(p); /* A dict */ break; case ann_weblink: pdf_puts(p, "/Subtype/Link\n"); pdf_printf(p, "/Rect[%f %f %f %f]\n", ann->rect.llx, ann->rect.lly, ann->rect.urx, ann->rect.ury); pdf_write_border_style(p, ann); pdf_printf(p, "/A<</S/URI/URI("); pdf_puts(p, ann->filename); pdf_puts(p, ")>>\n"); break; case ann_attach: pdf_puts(p, "/Subtype/FileAttachment\n"); pdf_printf(p, "/Rect[%f %f %f %f]\n", ann->rect.llx, ann->rect.lly, ann->rect.urx, ann->rect.ury); pdf_write_border_style(p, ann); if (ann->icon != icon_file_pushpin) /* pushpin is default */ pdf_printf(p, "/Name/%s\n", pdf_icon_names[ann->icon]); if (ann->title) { pdf_puts(p, "/T"); pdf_quote_string(p, ann->title); pdf_putc(p, PDF_NEWLINE); } if (ann->contents) { pdf_puts(p, "/Contents"); pdf_quote_string(p, ann->contents); pdf_putc(p, PDF_NEWLINE); } /* the icon is too small without these flags (=28) */ pdf_printf(p, "/F %d\n", pdf_ann_flag_print | pdf_ann_flag_nozoom | pdf_ann_flag_norotate); pdf_puts(p, "/FS"); pdf_begin_dict(p); /* FS dict */ pdf_puts(p, "/Type/FileSpec\n"); pdf_printf(p, "/F("); pdf_puts(p, ann->filename); pdf_puts(p, ")\n"); /* alloc id for the actual embedded file stream */ ann->obj_id = pdf_alloc_id(p); pdf_printf(p, "/EF<</F %ld 0 R>>\n", ann->obj_id); pdf_end_dict(p); /* FS dict */ break; default: pdf_error(p, PDF_SystemError, "Unknown annotation type %d", ann->type); } pdf_end_dict(p); /* Annotation dict */ pdf_end_obj(p); /* Annotation object */ } /* Write the actual embedded files with preallocated ids */ for (ann = p->annots; ann != NULL; ann = ann->next) { if (ann->type != ann_attach) continue; pdf_begin_obj(p, ann->obj_id); /* EmbeddedFile */ pdf_puts(p, "<</Type/EmbeddedFile\n"); if (ann->mimetype) pdf_printf(p, "/Subtype (%s)\n", ann->mimetype); if (p->compresslevel) pdf_puts(p, "/Filter/FlateDecode\n"); length_id = pdf_alloc_id(p); pdf_printf(p, "/Length %ld 0 R\n", length_id); pdf_end_dict(p); /* F dict */ pdf_begin_stream(p); /* Embedded file stream */ start_pos = pdf_tell(p); /* write the file in the PDF */ src.private_data = (void *) ann->filename; src.init = pdf_data_source_file_init; src.fill = pdf_data_source_file_fill; src.terminate = pdf_data_source_file_terminate; src.length = (long) 0; src.offset = (long) 0; pdf_compress(p, &src); length = pdf_tell(p) - start_pos; pdf_end_stream(p); /* Embedded file stream */ pdf_end_obj(p); /* EmbeddedFile object */ pdf_begin_obj(p, length_id); /* Length object */ pdf_printf(p, "%ld\n", length); pdf_end_obj(p); /* Length object */ if (p->flush & PDF_FLUSH_CONTENT) pdf_flush_stream(p); } }
/* Start a new pattern definition. */ PDFLIB_API int PDFLIB_CALL PDF_begin_pattern( PDF *p, float width, float height, float xstep, float ystep, int painttype) { static const char fn[] = "PDF_begin_pattern"; PDF_TRACE(("%s\t(pdf[%p], %f, %f, %f, %f, %d);\n", fn, (void *) p, width, height, xstep, ystep, painttype)); if (PDF_SANITY_CHECK_FAILED(p)) return -1; PDF_CHECK_SCOPE(p, fn, pdf_state_document); if (width <= 0 || height <= 0) pdf_error(p, PDF_ValueError, "Pattern size must be positive"); /* Acrobat 3 doesn't display patterns on screen so we disable it */ if (p->compatibility == PDF_1_2) pdf_error(p, PDF_RuntimeError, "Patterns not fully supported in Acrobat 3"); if (painttype != 1 && painttype != 2) pdf_error(p, PDF_ValueError, "Bad pattern paint type %d in PDF_begin_pattern", painttype); if (p->pattern_number == p->pattern_capacity) pdf_grow_pattern(p); p->pattern[p->pattern_number].obj_id = pdf_begin_obj(p, NEW_ID); p->pattern[p->pattern_number].painttype = painttype; p->height = height; p->width = width; p->thumb_id = BAD_ID; PDF_PUSH_STATE(p, fn, pdf_state_pattern); p->next_content = 0; p->contents = c_page; p->procset = 0; p->sl = 0; pdf_init_tstate(p); pdf_init_gstate(p); pdf_init_cstate(p); pdf_begin_dict(p); /* pattern dict*/ p->res_id = pdf_alloc_id(p); pdf_puts(p, "/PatternType 1\n"); /* colored or uncolored pattern */ pdf_printf(p, "/PaintType %d\n", painttype); pdf_puts(p, "/TilingType 1\n"); /* constant spacing */ pdf_printf(p, "/BBox[0 0 %f %f]\n", p->width, p->height); pdf_printf(p, "/XStep %f\n", xstep); pdf_printf(p, "/YStep %f\n", ystep); pdf_printf(p, "/Resources %ld 0 R\n", p->res_id); p->contents_length_id = pdf_alloc_id(p); pdf_printf(p, "/Length %ld 0 R\n", p->contents_length_id); if (p->compresslevel) pdf_puts(p, "/Filter/FlateDecode\n"); pdf_end_dict(p); /* pattern dict*/ pdf_begin_stream(p); pdf_compress_init(p); p->start_contents_pos = pdf_tell(p); p->next_content++; return p->pattern_number++; }
void pdf_put_image(PDF *p, int im, pdf_bool firststrip) { id length_id; long length; pdf_image *image; int i; image = &p->images[im]; /* york: how to check? see also F-imagecolor! switch (image->colorspace) { case ImageMask: case DeviceGray: case Indexed: case DeviceRGB: case DeviceCMYK: break; default: pdf_error(p, PDF_SystemError, "Unknown color space"); break; } */ /* Images may also be written to the output before the first page */ if (PDF_GET_STATE(p) == pdf_state_page) pdf_end_contents_section(p); /* Image object */ image->no = pdf_new_xobject(p, image_xobject, NEW_ID); pdf_begin_dict(p); /* XObject */ pdf_puts(p, "/Type/XObject\n"); pdf_puts(p, "/Subtype/Image\n"); pdf_printf(p,"/Width %d\n", (int) image->width); pdf_printf(p,"/Height %d\n", (int) image->height); pdf_printf(p,"/BitsPerComponent %d\n", image->bpc); /* * Transparency handling */ /* Masking by color: single transparent color value */ if (image->transparent) { if (image->colorspace == Indexed || image->colorspace == DeviceGray) pdf_printf(p,"/Mask[%d %d]\n", (int) image->transval[0], (int) image->transval[0]); else if (image->colorspace == DeviceRGB) pdf_printf(p,"/Mask[%d %d %d %d %d %d]\n", (int) image->transval[0], (int) image->transval[0], (int) image->transval[1], (int) image->transval[1], (int) image->transval[2], (int) image->transval[2]); else if (image->colorspace == DeviceCMYK) pdf_printf(p,"/Mask[%d %d %d %d %d %d %d %d]\n", (int) image->transval[0], (int) image->transval[0], (int) image->transval[1], (int) image->transval[1], (int) image->transval[2], (int) image->transval[2], (int) image->transval[3], (int) image->transval[3]); else pdf_error(p, PDF_SystemError, "Unknown color space with transparency"); /* Masking by position: separate bitmap mask */ } else if (image->mask != -1) { pdf_printf(p, "/Mask %ld 0 R\n", p->xobjects[p->images[image->mask].no].obj_id); } switch (image->colorspace) { case ImageMask: pdf_puts(p, "/ImageMask true\n"); break; case Indexed: if (firststrip) image->colormap_id = pdf_alloc_id(p); pdf_puts(p, "/ColorSpace[/Indexed/DeviceRGB "); pdf_printf(p, "%d %ld 0 R]\n", image->palette_size - 1, image->colormap_id); break; default: /* colorize the image with a spot color */ if (image->colorspace >= LastCS) { /* TODO: reconsider spot color numbering scheme */ int spot = image->colorspace - LastCS; p->colorspaces[spot].used_on_current_page = pdf_true; pdf_printf(p, "/ColorSpace %ld 0 R\n", p->colorspaces[spot].obj_id); /* the following is tricky: /Separation color space * always works as a subtractive color space. The * image, however, is Grayscale, and therefore * additive. */ if (firststrip) { image->invert = !image->invert; } } else { pdf_printf(p, "/ColorSpace/%s\n", pdf_colorspace_names[image->colorspace]); } break; } /* special case: referenced image data instead of direct data */ if (image->reference != pdf_ref_direct) { if (image->compression != none) { pdf_printf(p, "/FFilter[/%s]\n", pdf_filter_names[image->compression]); } if (image->compression == ccitt) { pdf_puts(p, "/FDecodeParms[<<"); if ((int) image->width != 1728) /* CCITT default width */ pdf_printf(p, "/Columns %d", (int) image->width); pdf_printf(p, "/Rows %d", (int) image->height); /* write CCITT parameters if required */ if (image->params) pdf_puts(p, image->params); pdf_puts(p, ">>]\n"); } if (image->reference == pdf_ref_file) { /* LATER: make image file name platform-neutral: * Change : to / on the Mac * Change \ to / on Windows */ pdf_printf(p, "/F(%s)/Length 0", image->filename); } else if (image->reference == pdf_ref_url) { pdf_printf(p, "/F<</FS/URL/F(%s)>>/Length 0", image->filename); } pdf_end_dict(p); /* XObject */ pdf_begin_stream(p); /* dummy image data */ pdf_end_stream(p); /* dummy image data */ if (PDF_GET_STATE(p) == pdf_state_page) pdf_begin_contents_section(p); pdf_end_obj(p); /* XObject */ return; } /* * Now the (more common) handling of actual image * data to be included in the PDF output. */ /* do we need a filter (either ASCII or decompression)? */ if (p->debug['a']) { pdf_puts(p, "/Filter[/ASCIIHexDecode"); if (image->compression != none) pdf_printf(p, "/%s", pdf_filter_names[image->compression]); pdf_puts(p, "]\n"); } else { /* force compression if not a recognized precompressed image format */ if (!image->use_raw && p->compresslevel) image->compression = flate; if (image->compression != none) pdf_printf(p, "/Filter[/%s]\n", pdf_filter_names[image->compression]); } /* prepare precompressed (raw) image data */ if (image->use_raw) { pdf_printf(p, "/DecodeParms[%s<<", (p->debug['a'] ? "null" : "")); /* write EarlyChange or CCITT parameters if required */ if (image->params) pdf_puts(p, image->params); if (image->compression == flate || image->compression == lzw) { if (image->predictor != pred_default) { pdf_printf(p, "/Predictor %d", (int) image->predictor); pdf_printf(p, "/Columns %d", (int) image->width); if (image->bpc != 8) pdf_printf(p, "/BitsPerComponent %d", image->bpc); if (image->colorspace < LastCS) { switch (image->colorspace) { case Indexed: case ImageMask: case DeviceGray: /* 1 is default */ break; case DeviceRGB: pdf_puts(p, "/Colors 3"); break; case DeviceCMYK: pdf_puts(p, "/Colors 4"); break; default: pdf_error(p, PDF_SystemError, "Unknown colorspace (%d)", (int )image->colorspace); break; } } } } if (image->compression == ccitt) { if ((int) image->width != 1728) /* CCITT default width */ pdf_printf(p, "/Columns %d", (int) image->width); pdf_printf(p, "/Rows %d", (int) image->height); } pdf_puts(p, ">>]\n"); /* DecodeParms dict and array */ } if (image->invert) { pdf_puts(p, "/Decode[1 0"); for (i = 1; i < image->components; i++) pdf_puts(p, " 1 0"); pdf_puts(p, "]\n"); } /* Write the actual image data */ length_id = pdf_alloc_id(p); pdf_printf(p,"/Length %ld 0 R\n", length_id); pdf_end_dict(p); /* XObject */ pdf_begin_stream(p); /* image data */ p->start_contents_pos = pdf_tell(p); /* image data */ if (p->debug['a']) pdf_ASCIIHexEncode(p, &image->src); else { if (image->use_raw) pdf_copy(p, &image->src); else pdf_compress(p, &image->src); } length = pdf_tell(p) - p->start_contents_pos; pdf_end_stream(p); /* image data */ pdf_end_obj(p); /* XObject */ pdf_begin_obj(p, length_id); /* Length object */ pdf_printf(p,"%ld\n", length); pdf_end_obj(p); if (p->flush & PDF_FLUSH_CONTENT) pdf_flush_stream(p); /* Image data done */ /* * Write colormap information for indexed color spaces */ if (firststrip && image->colorspace == Indexed) { pdf_begin_obj(p, image->colormap_id); /* colormap object */ pdf_begin_dict(p); if (p->debug['a']) pdf_puts(p, "/Filter[/ASCIIHexDecode]\n"); else if (p->compresslevel) pdf_puts(p, "/Filter[/FlateDecode]\n"); /* Length of colormap object */ length_id = pdf_alloc_id(p); pdf_printf(p,"/Length %ld 0 R\n", length_id); pdf_end_dict(p); pdf_begin_stream(p); /* colormap data */ p->start_contents_pos = pdf_tell(p); if (image->components != 1) { pdf_error(p, PDF_SystemError, "Bogus indexed colorspace (%d color components)", image->components); } image->src.init = pdf_noop; image->src.fill = pdf_data_source_buf_fill; image->src.terminate = pdf_noop; image->src.buffer_start = (unsigned char *) image->colormap; image->src.buffer_length= (size_t) (image->palette_size * 3); image->src.bytes_available = 0; image->src.next_byte = NULL; /* Write colormap data */ if (p->debug['a']) pdf_ASCIIHexEncode(p, &image->src); else { pdf_compress(p, &image->src); } length = pdf_tell(p) - p->start_contents_pos; pdf_end_stream(p); /* Colormap data */ pdf_end_obj(p); /* Colormap object */ pdf_begin_obj(p, length_id); /* Length object for colormap */ pdf_printf(p, "%ld\n", length); pdf_end_obj(p); /* Length object for colormap */ } if (PDF_GET_STATE(p) == pdf_state_page) pdf_begin_contents_section(p); if (p->flush & PDF_FLUSH_CONTENT) pdf_flush_stream(p); }