void write_enc(char **glyph_names, struct avl_table *tx_tree, integer fe_objnum) { int i_old, *p; struct avl_traverser t; assert(glyph_names != NULL); assert(tx_tree != NULL); assert(fe_objnum != 0); pdf_begin_dict(fe_objnum, 1); pdf_puts("/Type /Encoding\n"); pdf_printf("/Differences ["); avl_t_init(&t, tx_tree); for (i_old = -2, p = (int *) avl_t_first(&t, tx_tree); p != NULL; p = (int *) avl_t_next(&t)) { if (*p == i_old + 1) /* no gap */ pdf_printf("/%s", glyph_names[*p]); else { if (i_old == -2) pdf_printf("%i/%s", *p, glyph_names[*p]); else pdf_printf(" %i/%s", *p, glyph_names[*p]); } i_old = *p; } pdf_puts("]\n"); pdf_end_dict(); }
static void pdf_write_pnode(PDF *p, id node_id, id parent_id, id *kids, int n_kids, int n_pages) { pdf_begin_obj(p, node_id); pdf_begin_dict(p); pdf_puts(p, "/Type/Pages\n"); pdf_printf(p, "/Count %d\n", n_pages); if (parent_id != BAD_ID) pdf_printf(p, "/Parent %d 0 R\n", parent_id); pdf_puts(p, "/Kids["); do { pdf_printf(p, "%ld 0 R", *kids++); pdf_putc(p, PDF_NEWLINE); } while (--n_kids > 0); pdf_puts(p, "]"); pdf_end_dict(p); pdf_end_obj(p); }
static void set_font(PDF pdf) { pdfstructure *p = pdf->pstruct; if (p->need_width != 0) { pdf_printf(pdf, "%0.3f w\n",((7227.0/7200.0)/1000.0) * p->need_width ); p->done_width = 1; } else if (p->done_width) { pdf_puts(pdf, "0 w\n"); p->done_width = 0; } if (p->need_mode != 0) { pdf_printf(pdf, "%d Tr\n", (int) p->need_mode); p->done_mode = 1; } else if (p->done_mode) { pdf_puts(pdf, "0 Tr\n"); p->done_mode = 0; } pdf_printf(pdf, "/F%d", (int) p->f_pdf); pdf_print_resname_prefix(pdf); pdf_out(pdf, ' '); print_pdffloat(pdf, p->fs); pdf_puts(pdf, " Tf\n"); p->f_pdf_cur = p->f_pdf; p->fs_cur.m = p->fs.m; p->need_tf = false; /*tex Always follow |Tf| by |Tm|: */ p->need_tm = true; }
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++; }
void pdf_write_xobjects(PDF *p) { if (p->xobjects_number > 0) { pdf_bool hit = pdf_false; int i; for (i = 0; i < p->xobjects_capacity; ++i) { if (p->xobjects[i].flags & xobj_flag_write) { if (!hit) { pdf_puts(p, "/XObject"); pdf_begin_dict(p); hit = pdf_true; } pdf_printf(p, "/I%d %ld 0 R\n", i, p->xobjects[i].obj_id); p->xobjects[i].flags &= ~xobj_flag_write; } } if (hit) pdf_end_dict(p); } }
void pdf_write_annots_root(PDF *p) { pdf_annot *ann; /* Annotations array */ if (p->annots) { pdf_puts(p, "/Annots["); for (ann = p->annots; ann != NULL; ann = ann->next) { ann->obj_id = pdf_alloc_id(p); pdf_printf(p, "%ld 0 R ", ann->obj_id); } pdf_puts(p, "]\n"); } }
static void write_fontname(fd_entry * fd, const char *key) { assert(fd->fontname != NULL); pdf_puts("/"); if (key != NULL) pdf_printf("%s /", key); if (fd->subset_tag != NULL) pdf_printf("%s+", fd->subset_tag); pdf_printf("%s\n", fd->fontname); }
static void pdf_write_header(PDF *p) { /* Write the document header */ /* * Although the %PDF-1.3 header also works with older Acrobat viewers, * we need a 1.2 header for special applications (controlled by the * client). */ if (p->compatibility == PDF_1_4) pdf_puts(p, "%PDF-1.4\n"); /* PDF 1.4 header */ else if (p->compatibility == PDF_1_3) pdf_puts(p, "%PDF-1.3\n"); /* PDF 1.3 header */ else pdf_puts(p, "%PDF-1.2\n"); /* PDF 1.2 header */ /* binary magic number */ pdf_write(p, PDF_MAGIC_BINARY, sizeof(PDF_MAGIC_BINARY) - 1); }
/* Write annotation border style and color */ static void pdf_write_border_style(PDF *p, pdf_annot *ann) { /* don't write the default values */ if (ann->border_style == border_solid && ann->border_width == (float) 1.0 && p->border_red == (float) 0.0 && p->border_green == (float) 0.0 && p->border_blue == (float) 0.0 && p->border_dash1 == (float) 3.0 && p->border_dash2 == (float) 3.0) return; if (ann->type != ann_attach) { pdf_puts(p, "/BS"); pdf_begin_dict(p); /* BS dict */ pdf_puts(p, "/Type/Border\n"); if (ann->border_style != border_solid) pdf_printf(p, "/S/%s\n", pdf_border_style_names[ann->border_style]); if (ann->border_style == border_dashed) pdf_printf(p, "/D[%f %f]\n", ann->border_dash1, ann->border_dash2); pdf_end_dict(p); /* BS dict */ /* Write the Border key in old-style PDF 1.1 format */ pdf_printf(p, "/Border[0 0 %f", ann->border_width); if (ann->border_style == border_dashed && (ann->border_dash1 != (float) 0.0 || ann->border_dash2 != (float) 0.0)) /* set dashed border */ pdf_printf(p, "[%f %f]", ann->border_dash1, ann->border_dash2); pdf_puts(p, "]\n"); } /* write annotation color */ pdf_printf(p, "/C[%f %f %f]\n", ann->border_red, ann->border_green, ann->border_blue); }
void write_jpg(integer img) { long unsigned l; FILE *f; pdf_puts("/Type /XObject\n/Subtype /Image\n"); pdf_printf("/Width %i\n/Height %i\n/BitsPerComponent %i\n/Length %i\n", (int) img_width(img), (int) img_height(img), (int) jpg_ptr(img)->bits_per_component, (int) jpg_ptr(img)->length); pdf_puts("/ColorSpace "); if (img_colorspace_ref(img) != 0) { pdf_printf("%i 0 R\n", (int) img_colorspace_ref(img)); } else { switch (jpg_ptr(img)->color_space) { case JPG_GRAY: pdf_puts("/DeviceGray\n"); break; case JPG_RGB: pdf_puts("/DeviceRGB\n"); break; case JPG_CMYK: pdf_puts("/DeviceCMYK\n/Decode [1 0 1 0 1 0 1 0]\n"); break; default: pdftex_fail("Unsupported color space %i", (int) jpg_ptr(img)->color_space); } } pdf_puts("/Filter /DCTDecode\n>>\nstream\n"); for (l = jpg_ptr(img)->length, f = jpg_ptr(img)->file; l > 0; l--) pdfout(xgetc(f)); pdfendstream(); }
void pdf_printf(PDF *p, const char *fmt, ...) { char buf[LINEBUFLEN]; /* formatting buffer */ va_list ap; va_start(ap, fmt); vsprintf(buf, fmt, ap); pdf_puts(p, buf); va_end(ap); }
void epdf_write_enc(char **glyph_names, integer fe_objnum) { int i, i_old; assert(glyph_names != NULL); assert(fe_objnum != 0); pdf_begin_dict(fe_objnum, 1); pdf_puts("/Type /Encoding\n"); pdf_printf("/Differences ["); for (i = 0, i_old = -2; i < 256; i++) if (glyph_names[i] != notdef) { if (i == i_old + 1) /* no gap */ pdf_printf("/%s", glyph_names[i]); else { if (i_old == -2) pdf_printf("%i/%s", i, glyph_names[i]); else pdf_printf(" %i/%s", i, glyph_names[i]); } i_old = i; } pdf_puts("]\n"); pdf_end_dict(); }
static void set_textmatrix(PDF pdf, scaledpos pos) { boolean move; pdfstructure *p = pdf->pstruct; if (!is_textmode(p)) normal_error("pdf backend","text mode expected in set_textmatrix"); move = calc_pdfpos(p, pos); if (p->need_tm || move) { print_pdf_matrix(pdf, p->tm); pdf_puts(pdf, " Tm "); /*tex |Tm| replaces */ p->pdf.h.m = p->pdf_bt_pos.h.m + p->tm[4].m; p->pdf.v.m = p->pdf_bt_pos.v.m + p->tm[5].m; p->need_tm = false; } p->tm0_cur.m = p->tm[0].m; }
void pdf_write_page_procsets(PDF *p) { pdf_puts(p, "/ProcSet[/PDF"); if (p->procset & ImageB) pdf_puts(p, "/ImageB"); if (p->procset & ImageC) pdf_puts(p, "/ImageC"); if (p->procset & ImageI) pdf_puts(p, "/ImageI"); if (p->procset & Text) pdf_puts(p, "/Text"); pdf_puts(p, "]\n"); }
void pdf_write_page_colorspaces(PDF *p) { int i, total = 0; for (i = 0; i < p->colorspaces_number; i++) if (p->colorspaces[i].used_on_current_page) total++; if (total > 0) { pdf_puts(p, "/ColorSpace"); pdf_begin_dict(p); /* color space names */ for (i = 0; i < p->colorspaces_number; i++) { if (p->colorspaces[i].used_on_current_page) { p->colorspaces[i].used_on_current_page = pdf_false; /* reset */ pdf_printf(p, "/CS%d %ld 0 R\n", i, p->colorspaces[i].obj_id); } } pdf_end_dict(p); /* color space names */ } }
void pdf_write_page_pattern(PDF *p) { int i, total = 0; for (i = 0; i < p->pattern_number; i++) if (p->pattern[i].used_on_current_page) total++; if (total > 0) { pdf_puts(p, "/Pattern"); pdf_begin_dict(p); /* pattern */ for (i = 0; i < p->pattern_number; i++) { if (p->pattern[i].used_on_current_page) { p->pattern[i].used_on_current_page = pdf_false; /* reset */ pdf_printf(p, "/P%d %ld 0 R\n", i, p->pattern[i].obj_id); } } pdf_end_dict(p); /* pattern */ } }
/* Write all pending document information up to the xref table and trailer */ static void pdf_wrapup_document(PDF *p) { static const char bin2hex[] = PDF_STRING_0123456789ABCDEF; long pos; id i; id pages_id; unsigned char digest[MD5_DIGEST_LENGTH]; pdf_write_info(p); pdf_write_doc_fonts(p); /* font objects */ pdf_write_doc_colorspaces(p); /* color space resources */ pages_id = pdf_make_tree(p, BAD_ID, p->pnodes, p->pages+1, p->current_page); pdf_begin_obj(p, p->root_id); /* Catalog or Root object */ pdf_begin_dict(p); pdf_puts(p, "/Type/Catalog\n"); /* * specify the open action (display of the first page) * default = retain: top of the first page at default zoom level */ if (p->open_action == fitpage) { pdf_printf(p, "/OpenAction[%ld 0 R/Fit]\n", p->pages[1]); } else if (p->open_action == fitwidth) { pdf_printf(p, "/OpenAction[%ld 0 R/FitH]\n", p->pages[1]); } else if (p->open_action == fitheight) { pdf_printf(p, "/OpenAction[%ld 0 R/FitV 0]\n", p->pages[1]); } else if (p->open_action == fitbbox) { pdf_printf(p, "/OpenAction[%ld 0 R/FitB]\n", p->pages[1]); } /* * specify the document's open mode * default = open_none: open document with neither bookmarks nor * thumbnails visible */ if (p->open_mode == open_bookmarks) { pdf_printf(p, "/PageMode/UseOutlines\n"); } else if (p->open_mode == open_thumbnails) { pdf_printf(p, "/PageMode/UseThumbs\n"); } else if (p->open_mode == open_fullscreen) { pdf_printf(p, "/PageMode/FullScreen\n"); } if (p->base) { pdf_printf(p, "/URI<</Base", p->base); pdf_quote_string(p, p->base); pdf_printf(p, ">>\n", p->base); } /* Pages object */ pdf_printf(p, "/Pages %ld 0 R\n", pages_id); pdf_write_outline_root(p); pdf_end_dict(p); /* Catalog */ pdf_end_obj(p); pdf_write_outlines(p); #ifdef DEBUG if (p->debug['s']) { fprintf(stderr, "PDF document statistics:\n"); fprintf(stderr, " %d pages\n", p->current_page); fprintf(stderr, " %d fonts\n", p->fonts_number); fprintf(stderr, " %d xobjects\n", p->xobjects_number); fprintf(stderr, " %ld objects\n", p->currentobj + 1); } #endif /* Don't write any object after this check! */ for (i = 1; i <= p->currentobj; i++) { if (p->file_offset[i] == BAD_ID) { pdf_error(p, PDF_NonfatalError, "Object %ld allocated but not used", i); pdf_begin_obj(p, i); pdf_end_obj(p); } } pos = pdf_tell(p); /* xref table */ pdf_puts(p, "xref\n"); pdf_printf(p, "0 %ld\n", p->currentobj + 1); pdf_puts(p, "0000000000 65535 f \n"); for (i = 1; i <= p->currentobj; i++) { pdf_printf(p, "%010ld 00000 n \n", p->file_offset[i]); } pdf_puts(p, "trailer\n"); pdf_begin_dict(p); /* trailer */ pdf_printf(p, "/Size %ld\n", p->currentobj + 1); pdf_printf(p, "/Info %ld 0 R\n", p->info_id); pdf_printf(p, "/Root %ld 0 R\n", p->root_id); /* put some more data into the MD5 digest */ MD5_Update(p->md5, (unsigned char *) &pos, sizeof pos); MD5_Update(p->md5, (unsigned char *) p, sizeof (PDF)); if (p->filename && strcmp(p->filename, "-") != 0) MD5_Update(p->md5, (unsigned char *) p->filename, strlen(p->filename)); /* write the digest to the ID array */ MD5_Final(digest, p->md5); pdf_puts(p, "/ID[<"); for (i = 0; i < MD5_DIGEST_LENGTH; ++i) { pdf_putc(p, bin2hex[digest[i] >> 4]); pdf_putc(p, bin2hex[digest[i] & 0x0F]); } pdf_puts(p, "><"); for (i = 0; i < MD5_DIGEST_LENGTH; ++i) { pdf_putc(p, bin2hex[digest[i] >> 4]); pdf_putc(p, bin2hex[digest[i] & 0x0F]); } pdf_puts(p, ">]\n"); pdf_end_dict(p); /* trailer */ pdf_puts(p, "startxref\n"); pdf_printf(p, "%ld\n", pos); pdf_puts(p, "%%EOF\n"); }
void pdf_place_rule(PDF pdf,halfword q,scaledpos size,int callback_id) { pdfpos dim; pdfstructure*p= pdf->pstruct; scaledpos pos= pdf->posstruct->pos; if(subtype(q)==box_rule){ pdf_place_form(pdf,q); }else if(subtype(q)==image_rule){ pdf_place_image(pdf,q); }else if(subtype(q)==empty_rule){ }else if(subtype(q)==user_rule){ if(callback_id!=0){ pdf_goto_pagemode(pdf); pdf_puts(pdf,"q\n"); pdf_set_pos_temp(pdf,pos); run_callback(callback_id,"Ndd->",q,size.h,size.v); pdf_puts(pdf,"\nQ\n"); } }else{ pdf_goto_pagemode(pdf); dim.h.m= i64round(size.h*p->k1); dim.h.e= p->pdf.h.e; dim.v.m= i64round(size.v*p->k1); dim.v.e= p->pdf.v.e; pdf_puts(pdf,"q\n"); if(size.v<=one_bp){ pos.v+= i64round(0.5*size.v); pdf_set_pos_temp(pdf,pos); pdf_puts(pdf,"[]0 d 0 J "); print_pdffloat(pdf,dim.v); pdf_puts(pdf," w 0 0 m "); print_pdffloat(pdf,dim.h); pdf_puts(pdf," 0 l S\n"); }else if(size.h<=one_bp){ pos.h+= i64round(0.5*size.h); pdf_set_pos_temp(pdf,pos); pdf_puts(pdf,"[]0 d 0 J "); print_pdffloat(pdf,dim.h); pdf_puts(pdf," w 0 0 m 0 "); print_pdffloat(pdf,dim.v); pdf_puts(pdf," l S\n"); }else{ pdf_set_pos_temp(pdf,pos); pdf_puts(pdf,"0 0 "); print_pdffloat(pdf,dim.h); pdf_out(pdf,' '); print_pdffloat(pdf,dim.v); pdf_puts(pdf," re f\n"); } pdf_puts(pdf,"Q\n"); } }/*:2*/
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); }
PDFLIB_API void PDFLIB_CALL PDF_end_page(PDF *p) { static const char fn[] = "PDF_end_page"; int index; PDF_TRACE(("%s\t(pdf[%p]);\n", fn, (void *) p)); if (PDF_SANITY_CHECK_FAILED(p)) return; PDF_CHECK_SCOPE(p, fn, pdf_state_page); /* check whether PDF_save() and PDF_restore() calls are balanced */ if (p->sl > 0) pdf_error(p, PDF_RuntimeError, "Unmatched save level at end of page"); /* restore text parameter and color defaults for out-of-page usage. */ pdf_init_tstate(p); pdf_init_cstate(p); pdf_end_contents_section(p); /* Page object */ pdf_begin_obj(p, p->pages[p->current_page]); pdf_begin_dict(p); pdf_puts(p, "/Type/Page\n"); pdf_printf(p, "/Parent %ld 0 R\n", pdf_get_pnode_id(p)); p->res_id = pdf_alloc_id(p); pdf_printf(p, "/Resources %ld 0 R\n", p->res_id); pdf_printf(p, "/MediaBox[0 0 %f %f]\n", p->width, p->height); if (p->CropBox.llx != (float) 0 || p->CropBox.lly != (float) 0 || p->CropBox.urx != (float) 0 || p->CropBox.ury != (float) 0 ) { if (p->CropBox.urx <= p->CropBox.llx || p->CropBox.ury <= p->CropBox.lly) pdf_error(p, PDF_ValueError, "Illegal CropBox dimensions"); pdf_printf(p, "/CropBox[%f %f %f %f]\n", p->CropBox.llx, p->CropBox.lly, p->CropBox.urx, p->CropBox.ury); } if (p->BleedBox.llx != (float) 0 || p->BleedBox.lly != (float) 0 || p->BleedBox.urx != (float) 0 || p->BleedBox.ury != (float) 0 ) { if (p->BleedBox.urx <= p->BleedBox.llx || p->BleedBox.ury <= p->BleedBox.lly) pdf_error(p, PDF_ValueError, "Illegal BleedBox dimensions"); pdf_printf(p, "/BleedBox[%f %f %f %f]\n", p->BleedBox.llx, p->BleedBox.lly, p->BleedBox.urx, p->BleedBox.ury); } if (p->TrimBox.llx != (float) 0 || p->TrimBox.lly != (float) 0 || p->TrimBox.urx != (float) 0 || p->TrimBox.ury != (float) 0 ) { if (p->TrimBox.urx <= p->TrimBox.llx || p->TrimBox.ury <= p->TrimBox.lly) pdf_error(p, PDF_ValueError, "Illegal TrimBox dimensions"); pdf_printf(p, "/TrimBox[%f %f %f %f]\n", p->TrimBox.llx, p->TrimBox.lly, p->TrimBox.urx, p->TrimBox.ury); } if (p->ArtBox.llx != (float) 0 || p->ArtBox.lly != (float) 0 || p->ArtBox.urx != (float) 0 || p->ArtBox.ury != (float) 0 ) { if (p->ArtBox.urx <= p->ArtBox.llx || p->ArtBox.ury <= p->ArtBox.lly) pdf_error(p, PDF_ValueError, "Illegal ArtBox dimensions"); pdf_printf(p, "/ArtBox[%f %f %f %f]\n", p->ArtBox.llx, p->ArtBox.lly, p->ArtBox.urx, p->ArtBox.ury); } /* * The duration can be placed in the transition dictionary (/D) * or in the page dictionary (/Dur). We put it here so it can * be used without setting a transition effect. */ if (p->duration > 0) pdf_printf(p, "/Dur %f\n", p->duration); pdf_write_page_transition(p); pdf_puts(p, "/Contents["); for (index = 0; index < p->next_content; index++) { pdf_printf(p, "%ld 0 R", p->contents_ids[index]); pdf_putc(p, (char) (index + 1 % 8 ? PDF_SPACE : PDF_NEWLINE)); } pdf_puts(p, "]\n"); /* Thumbnail image */ if (p->thumb_id != BAD_ID) pdf_printf(p, "/Thumb %ld 0 R\n", p->thumb_id); pdf_write_annots_root(p); pdf_end_dict(p); /* Page object */ pdf_end_obj(p); pdf_write_page_annots(p); /* Annotation dicts */ pdf_begin_obj(p, p->res_id); /* resource object */ pdf_begin_dict(p); /* resource dict */ pdf_write_page_procsets(p); /* ProcSet resources */ pdf_write_page_fonts(p); /* Font resources */ pdf_write_page_colorspaces(p); /* Color space resources */ pdf_write_page_pattern(p); /* Pattern resources */ pdf_write_xobjects(p); /* XObject resources */ pdf_end_dict(p); /* resource dict */ pdf_end_obj(p); /* resource object */ pdf_cleanup_page(p); PDF_SET_STATE(p, fn, pdf_state_document); if (p->flush & PDF_FLUSH_PAGE) pdf_flush_stream(p); }
void place_img(PDF pdf, image_dict * idict, scaled_whd dim, int transform) { /*tex A transformation matrix: */ double a[6]; double xoff, yoff, tmp; pdfstructure *p = pdf->pstruct; scaledpos pos = pdf->posstruct->pos; /*tex The number of digits after the decimal point: */ int r; int k; scaledpos tmppos; pdffloat cm[6]; int groupref; a[0] = a[3] = 1.0e6; a[1] = a[2] = 0; if (img_type(idict) == IMG_TYPE_PDF || img_type(idict) == IMG_TYPE_PDFMEMSTREAM || img_type(idict) == IMG_TYPE_PDFSTREAM) { a[0] /= (double) img_xsize(idict); a[3] /= (double) img_ysize(idict); xoff = (double) img_xorig(idict) / (double) img_xsize(idict); yoff = (double) img_yorig(idict) / (double) img_ysize(idict); r = 6; } else { if (img_type(idict) == IMG_TYPE_PNG) { groupref = img_group_ref(idict); if ((groupref > 0) && (pdf->img_page_group_val == 0)) pdf->img_page_group_val = groupref; } a[0] /= (double) one_hundred_bp; a[3] = a[0]; xoff = yoff = 0; r = 4; } if ((transform & 7) > 3) { /*tex Mirror cases: */ a[0] *= -1; xoff *= -1; } switch ((transform + img_rotation(idict)) & 3) { case 0: /*tex No transform. */ break; case 1: /*tex rotation over 90 degrees (counterclockwise) */ a[1] = a[0]; a[2] = -a[3]; a[3] = a[0] = 0; tmp = yoff; yoff = xoff; xoff = -tmp; break; case 2: /*tex rotation over 180 degrees (counterclockwise) */ a[0] *= -1; a[3] *= -1; xoff *= -1; yoff *= -1; break; case 3: /*tex rotation over 270 degrees (counterclockwise) */ a[1] = -a[0]; a[2] = a[3]; a[3] = a[0] = 0; tmp = yoff; yoff = -xoff; xoff = tmp; break; default:; } xoff *= (double) dim.wd; yoff *= (double) (dim.ht + dim.dp); a[0] *= (double) dim.wd; a[1] *= (double) (dim.ht + dim.dp); a[2] *= (double) dim.wd; a[3] *= (double) (dim.ht + dim.dp); a[4] = (double) pos.h - xoff; a[5] = (double) pos.v - yoff; k = transform + img_rotation(idict); if ((transform & 7) > 3) k++; switch (k & 3) { case 0: /*tex No transform */ break; case 1: /*tex rotation over 90 degrees (counterclockwise) */ a[4] += (double) dim.wd; break; case 2: /*tex rotation over 180 degrees (counterclockwise) */ a[4] += (double) dim.wd; a[5] += (double) (dim.ht + dim.dp); break; case 3: /*tex rotation over 270 degrees (counterclockwise) */ a[5] += (double) (dim.ht + dim.dp); break; default:; } setpdffloat(cm[0], i64round(a[0]), r); setpdffloat(cm[1], i64round(a[1]), r); setpdffloat(cm[2], i64round(a[2]), r); setpdffloat(cm[3], i64round(a[3]), r); tmppos.h = round(a[4]); tmppos.v = round(a[5]); pdf_goto_pagemode(pdf); (void) calc_pdfpos(p, tmppos); cm[4] = p->cm[4]; cm[5] = p->cm[5]; if (pdf->img_page_group_val == 0) pdf->img_page_group_val = img_group_ref(idict); pdf_puts(pdf, "q\n"); pdf_print_cm(pdf, cm); pdf_puts(pdf, "/Im"); pdf_print_int(pdf, img_index(idict)); pdf_print_resname_prefix(pdf); pdf_puts(pdf, " Do\nQ\n"); addto_page_resources(pdf, obj_type_ximage, img_objnum(idict)); if (img_state(idict) < DICT_OUTIMG) img_state(idict) = DICT_OUTIMG; }
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); } }
void pdf_write_doc_colorspaces(PDF *p) { int i; pdf_csresource *cs; for (i = 0; i < p->colorspaces_number; i++) { cs = &p->colorspaces[i]; pdf_begin_obj(p, cs->obj_id); /* color space resource */ /* Separation color space, or pattern based on separation */ if (cs->cs == Separation || (cs->cs == PatternCS && cs->alternate.cs == Separation)) { const char *name; if (cs->cs == PatternCS) { pdf_printf(p, "[/Pattern"); /* pattern color space */ name = p->colorspaces[cs->alternate.val.sep.cs].name; } else name = cs->name; pdf_puts(p, "[/Separation/"); pdf_puts(p, name); /* this is already quoted */ pdf_puts(p, "\n"); if (cs->alternate.cs == DeviceGray) { pdf_puts(p, "/DeviceGray<<\n"); pdf_puts(p, "/Range[0 1]\n"); pdf_printf(p, "/C0[0]\n"); pdf_printf(p, "/C1[%f]\n", cs->alternate.val.gray); } else if (cs->alternate.cs == DeviceRGB) { pdf_puts(p, "/DeviceRGB<<\n"); pdf_puts(p, "/Range[0 1 0 1 0 1]\n"); pdf_printf(p, "/C0[0 0 0]\n"); pdf_printf(p, "/C1[%f %f %f]\n", cs->alternate.val.rgb.r, cs->alternate.val.rgb.g, cs->alternate.val.rgb.b); } else if (cs->alternate.cs == DeviceCMYK) { pdf_puts(p, "/DeviceCMYK<<\n"); pdf_puts(p, "/Range[0 1 0 1 0 1 0 1]\n"); pdf_printf(p, "/C0[0 0 0 0]\n"); pdf_printf(p, "/C1[%f %f %f %f]\n", cs->alternate.val.cmyk.c, cs->alternate.val.cmyk.m, cs->alternate.val.cmyk.y, cs->alternate.val.cmyk.k); } else if (cs->alternate.cs != Separation) pdf_error(p, PDF_SystemError, "Unknown alternate color space in pdf_write_doc_colorspaces"); pdf_puts(p, "/FunctionType 2\n"); pdf_puts(p, "/Domain[0 1]\n"); pdf_puts(p, "/N 1\n"); pdf_end_dict(p); /* alternate color space */ pdf_puts(p, "]\n"); /* separation color space */ if (cs->cs == PatternCS) pdf_puts(p, "]\n"); /* pattern color space */ /* Pattern color space based on simple color space */ } else if (cs->cs == PatternCS) { pdf_printf(p, "[/Pattern/%s]\n", pdf_colorspace_names[cs->alternate.cs]); } else { pdf_error(p, PDF_SystemError, "Unknown base or alternate color space in pdf_write_doc_colorspaces"); } pdf_end_obj(p); /* color space resource */ } }
/* 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_setpatterncolor(PDF *p, const char *type, int pattern) { if (PDF_SANITY_CHECK_FAILED(p)) return; if (!type || !*type) pdf_error(p, PDF_ValueError, "Missing type in pdf_setspotcolor"); if (strcmp(type, "fill") && strcmp(type, "stroke") && strcmp(type, "both")) pdf_error(p, PDF_ValueError, "Unknown type in pdf_spotcolor"); if (pattern < 0 || pattern >= p->pattern_number) pdf_error(p, PDF_ValueError, "Invalid pattern number %d in PDF_setcolor", pattern); if (PDF_GET_STATE(p) == pdf_state_pattern && pattern == p->pattern_number-1) { pdf_error(p, PDF_ValueError, "Can't use pattern within its own definition"); } if (!strcmp(type, "fill") || !strcmp(type, "both")) { if (p->pattern[pattern].painttype == 1) { pdf_puts(p, "/Pattern cs\n"); } else if (p->pattern[pattern].painttype == 2) { /* TODO: find spot color name */ if (p->cstate[p->sl].fill.cs == Separation) pdf_error(p, PDF_ValueError, "Separation NYI for patterns"); pdf_printf(p, "/CS%d cs\n", pdf_add_colorspace(p, PatternCS, (char *) NULL)); /* TODO: add spot name if based on separation color space */ pdf_write_pattern_color(p, pdf_true); } pdf_printf(p, "/P%d scn\n", pattern); if (p->pattern[pattern].painttype == 1) { p->cstate[p->sl].fill.cs = PatternCS; p->cstate[p->sl].fill.val.pattern = pattern; } else if (p->pattern[pattern].painttype == 2) { /* TODO: deal with color */ } } if (!strcmp(type, "stroke") || !strcmp(type, "both")) { if (p->pattern[pattern].painttype == 1) { pdf_puts(p, "/Pattern CS\n"); } else if (p->pattern[pattern].painttype == 2) { /* TODO */ if (p->cstate[p->sl].fill.cs == Separation) pdf_error(p, PDF_ValueError, "Separation NYI for patterns"); pdf_printf(p, "/CS%d CS\n", pdf_add_colorspace(p, PatternCS, (char *) NULL)); /* TODO: add spot name if based on separation color space */ pdf_write_pattern_color(p, pdf_false); } pdf_printf(p, "/P%d SCN\n", pattern); if (p->pattern[pattern].painttype == 1) { p->cstate[p->sl].stroke.cs = PatternCS; p->cstate[p->sl].stroke.val.pattern = pattern; } else if (p->pattern[pattern].painttype == 2) { /* TODO */ } } p->pattern[pattern].used_on_current_page = pdf_true; }