📄 xo-print.c
字号:
obj = get_pdfobj(pdfbuf, xref, get_dict_entry(pgtree, "/Resources")); if (obj!=NULL) { free_pdfobj(pages->resources); pages->resources = obj; } obj = get_pdfobj(pdfbuf, xref, get_dict_entry(pgtree, "/MediaBox")); if (obj!=NULL) { free_pdfobj(pages->mediabox); pages->mediabox = obj; } obj = get_pdfobj(pdfbuf, xref, get_dict_entry(pgtree, "/Rotate")); if (obj!=NULL && obj->type == PDFTYPE_INT) pages->rotate = obj->intval; free_pdfobj(obj); return 1; } else if (!strcmp(obj->str, "/Pages")) { free_pdfobj(obj); obj = get_pdfobj(pdfbuf, xref, get_dict_entry(pgtree, "/Count")); if (obj!=NULL && obj->type == PDFTYPE_INT && obj->intval>0 && obj->intval<=nmax) count = obj->intval; else count = 0; free_pdfobj(obj); obj = get_pdfobj(pdfbuf, xref, get_dict_entry(pgtree, "/Resources")); if (obj!=NULL) for (i=0; i<count; i++) { free_pdfobj(pages[i].resources); pages[i].resources = dup_pdfobj(obj); } free_pdfobj(obj); obj = get_pdfobj(pdfbuf, xref, get_dict_entry(pgtree, "/MediaBox")); if (obj!=NULL) for (i=0; i<count; i++) { free_pdfobj(pages[i].mediabox); pages[i].mediabox = dup_pdfobj(obj); } free_pdfobj(obj); obj = get_pdfobj(pdfbuf, xref, get_dict_entry(pgtree, "/Rotate")); if (obj!=NULL && obj->type == PDFTYPE_INT) for (i=0; i<count; i++) pages[i].rotate = obj->intval; free_pdfobj(obj); obj = get_pdfobj(pdfbuf, xref, get_dict_entry(pgtree, "/Kids")); if (obj!=NULL && obj->type == PDFTYPE_ARRAY) { for (i=0; i<obj->num; i++) { kid = get_pdfobj(pdfbuf, xref, obj->elts[i]); if (kid!=NULL) { j = pdf_getpageinfo(pdfbuf, xref, kid, nmax, pages); nmax -= j; pages += j; free_pdfobj(kid); } } } free_pdfobj(obj); return count; } return 0;}// parse a PDF file in memorygboolean pdf_parse_info(GString *pdfbuf, struct PdfInfo *pdfinfo, struct XrefTable *xref){ char *p; int i, offs; struct PdfObj *obj, *pages; xref->n_alloc = xref->last = 0; xref->data = NULL; p = pdfbuf->str + pdfbuf->len-1; while (*p!='s' && p!=pdfbuf->str) p--; if (strncmp(p, "startxref", 9)) return FALSE; // fail p+=9; while (ispdfspace(*p) && p!=pdfbuf->str+pdfbuf->len) p++; offs = strtol(p, NULL, 10); if (offs <= 0 || offs > pdfbuf->len) return FALSE; // fail pdfinfo->startxref = offs; pdfinfo->trailerdict = parse_xref_table(pdfbuf, xref, offs); if (pdfinfo->trailerdict == NULL) return FALSE; // fail obj = get_pdfobj(pdfbuf, xref, get_dict_entry(pdfinfo->trailerdict, "/Root")); if (obj == NULL) { free_pdfobj(pdfinfo->trailerdict); return FALSE; } pages = get_pdfobj(pdfbuf, xref, get_dict_entry(obj, "/Pages")); free_pdfobj(obj); if (pages == NULL) { free_pdfobj(pdfinfo->trailerdict); return FALSE; } obj = get_pdfobj(pdfbuf, xref, get_dict_entry(pages, "/Count")); if (obj == NULL || obj->type != PDFTYPE_INT || obj->intval<=0) { free_pdfobj(pdfinfo->trailerdict); free_pdfobj(pages); free_pdfobj(obj); return FALSE; } pdfinfo->npages = obj->intval; free_pdfobj(obj); pdfinfo->pages = g_malloc0(pdfinfo->npages*sizeof(struct PdfPageDesc)); pdf_getpageinfo(pdfbuf, xref, pages, pdfinfo->npages, pdfinfo->pages); free_pdfobj(pages); return TRUE;}// add an entry to the xref tablevoid make_xref(struct XrefTable *xref, int nobj, int offset){ if (xref->n_alloc <= nobj) { xref->n_alloc = nobj + 10; xref->data = g_realloc(xref->data, xref->n_alloc*sizeof(int)); } if (xref->last < nobj) xref->last = nobj; xref->data[nobj] = offset;}// a wrapper for deflateGString *do_deflate(char *in, int len){ GString *out; z_stream zs; zs.zalloc = Z_NULL; zs.zfree = Z_NULL; deflateInit(&zs, Z_DEFAULT_COMPRESSION); zs.next_in = (Bytef *)in; zs.avail_in = len; zs.avail_out = deflateBound(&zs, len); out = g_string_sized_new(zs.avail_out); zs.next_out = (Bytef *)out->str; deflate(&zs, Z_FINISH); out->len = zs.total_out; deflateEnd(&zs); return out;}// prefix to scale the original pageGString *make_pdfprefix(struct PdfPageDesc *pgdesc, double width, double height){ GString *str; double v[4], t, xscl, yscl; int i; // push 3 times in case code to be annotated has unbalanced q/Q (B of A., ...) str = g_string_new("q q q "); if (pgdesc->rotate == 90) { g_string_append_printf(str, "0 -1 1 0 0 %.2f cm ", height); t = height; height = width; width = t; } if (pgdesc->rotate == 270) { g_string_append_printf(str, "0 1 -1 0 %.2f 0 cm ", width); t = height; height = width; width = t; } if (pgdesc->rotate == 180) { g_string_append_printf(str, "-1 0 0 -1 %.2f %.2f cm ", width, height); } if (pgdesc->mediabox==NULL || pgdesc->mediabox->type != PDFTYPE_ARRAY || pgdesc->mediabox->num != 4) return str; for (i=0; i<4; i++) { if (pgdesc->mediabox->elts[i]->type == PDFTYPE_INT) v[i] = pgdesc->mediabox->elts[i]->intval; else if (pgdesc->mediabox->elts[i]->type == PDFTYPE_REAL) v[i] = pgdesc->mediabox->elts[i]->realval; else return str; } if (v[0]>v[2]) { t = v[0]; v[0] = v[2]; v[2] = t; } if (v[1]>v[3]) { t = v[1]; v[1] = v[3]; v[3] = t; } if (v[2]-v[0] < 1. || v[3]-v[1] < 1.) return str; xscl = width/(v[2]-v[0]); yscl = height/(v[3]-v[1]); g_string_append_printf(str, "%.4f 0 0 %.4f %.2f %.2f cm ", xscl, yscl, -v[0]*xscl, -v[1]*yscl); return str;}// add an entry to a subentry of a directorystruct PdfObj *mk_pdfname(char *name){ struct PdfObj *obj; obj = g_malloc(sizeof(struct PdfObj)); obj->type = PDFTYPE_NAME; obj->str = g_strdup(name); return obj;}struct PdfObj *mk_pdfref(int num){ struct PdfObj *obj; obj = g_malloc(sizeof(struct PdfObj)); obj->type = PDFTYPE_REF; obj->intval = num; obj->num = 0; return obj;}gboolean iseq_obj(struct PdfObj *a, struct PdfObj *b){ if (a==NULL || b==NULL) return (a==b); if (a->type!=b->type) return FALSE; if (a->type == PDFTYPE_CST || a->type == PDFTYPE_INT) return (a->intval == b->intval); if (a->type == PDFTYPE_REAL) return (a->realval == b->realval); if (a->type == PDFTYPE_NAME) return !strcmp(a->str, b->str); if (a->type == PDFTYPE_REF) return (a->intval == b->intval && a->num == b->num); return FALSE;}void add_dict_subentry(GString *pdfbuf, struct XrefTable *xref, struct PdfObj *obj, char *section, int type, char *name, struct PdfObj *entry){ struct PdfObj *sec; int i, subpos; subpos = -1; for (i=0; i<obj->num; i++) if (!strcmp(obj->names[i], section)) subpos = i; if (subpos == -1) { subpos = obj->num; obj->num++; obj->elts = g_realloc(obj->elts, obj->num*sizeof(struct PdfObj*)); obj->names = g_realloc(obj->names, obj->num*sizeof(char *)); obj->names[subpos] = g_strdup(section); obj->elts[subpos] = NULL; } if (obj->elts[subpos]!=NULL && obj->elts[subpos]->type==PDFTYPE_REF) { sec = get_pdfobj(pdfbuf, xref, obj->elts[subpos]); free_pdfobj(obj->elts[subpos]); obj->elts[subpos] = sec; } if (obj->elts[subpos]!=NULL && obj->elts[subpos]->type!=type) { free_pdfobj(obj->elts[subpos]); obj->elts[subpos] = NULL; } if (obj->elts[subpos] == NULL) { obj->elts[subpos] = sec = g_malloc(sizeof(struct PdfObj)); sec->type = type; sec->num = 0; sec->elts = NULL; sec->names = NULL; } sec = obj->elts[subpos]; subpos = -1; if (type==PDFTYPE_DICT) { for (i=0; i<sec->num; i++) if (!strcmp(sec->names[i], name)) subpos = i; if (subpos == -1) { subpos = sec->num; sec->num++; sec->elts = g_realloc(sec->elts, sec->num*sizeof(struct PdfObj*)); sec->names = g_realloc(sec->names, sec->num*sizeof(char *)); sec->names[subpos] = g_strdup(name); sec->elts[subpos] = NULL; } free_pdfobj(sec->elts[subpos]); sec->elts[subpos] = entry; } if (type==PDFTYPE_ARRAY) { for (i=0; i<sec->num; i++) if (iseq_obj(sec->elts[i], entry)) subpos = i; if (subpos == -1) { subpos = sec->num; sec->num++; sec->elts = g_realloc(sec->elts, sec->num*sizeof(struct PdfObj*)); sec->elts[subpos] = entry; } else free_pdfobj(entry); }}// draw a page's backgroundvoid pdf_draw_solid_background(struct Page *pg, GString *str){ double x, y; g_string_append_printf(str, "%.2f %.2f %.2f rg 0 0 %.2f %.2f re f ", RGBA_RGB(pg->bg->color_rgba), pg->width, pg->height); if (!ui.print_ruling) return; if (pg->bg->ruling == RULING_NONE) return; g_string_append_printf(str, "%.2f %.2f %.2f RG %.2f w ", RGBA_RGB(RULING_COLOR), RULING_THICKNESS); if (pg->bg->ruling == RULING_GRAPH) { for (x=RULING_GRAPHSPACING; x<pg->width-1; x+=RULING_GRAPHSPACING) g_string_append_printf(str, "%.2f 0 m %.2f %.2f l S ", x, x, pg->height); for (y=RULING_GRAPHSPACING; y<pg->height-1; y+=RULING_GRAPHSPACING) g_string_append_printf(str, "0 %.2f m %.2f %.2f l S ", y, pg->width, y); return; } for (y=RULING_TOPMARGIN; y<pg->height-1; y+=RULING_SPACING) g_string_append_printf(str, "0 %.2f m %.2f %.2f l S ", y, pg->width, y); if (pg->bg->ruling == RULING_LINED) g_string_append_printf(str, "%.2f %.2f %.2f RG %.2f 0 m %.2f %.2f l S ", RGBA_RGB(RULING_MARGIN_COLOR), RULING_LEFTMARGIN, RULING_LEFTMARGIN, pg->height);}int pdf_draw_bitmap_background(struct Page *pg, GString *str, struct XrefTable *xref, GString *pdfbuf){ BgPdfPage *pgpdf; GdkPixbuf *pix; GString *zpix; char *buf, *p1, *p2; int height, width, stride, x, y, chan; if (pg->bg->type == BG_PDF) { pgpdf = (struct BgPdfPage *)g_list_nth_data(bgpdf.pages, pg->bg->file_page_seq-1); if (pgpdf == NULL) return -1; if (pgpdf->dpi != PDFTOPPM_PRINTING_DPI) { add_bgpdf_request(pg->bg->file_page_seq, 0, TRUE); while (pgpdf->dpi != PDFTOPPM_PRINTING_DPI && bgpdf.status == STATUS_RUNNING) gtk_main_iteration(); } pix = pgpdf->pixbuf; } else pix = pg->bg->pixbuf; if (gdk_pixbuf_get_bits_per_sample(pix) != 8) return -1; if (gdk_pixbuf_get_colorspace(pix) != GDK_COLORSPACE_RGB) return -1; width = gdk_pixbuf_get_width(pix); height = gdk_pixbuf_get_height(pix); stride = gdk_pixbuf_get_rowstride(pix); chan = gdk_pixbuf_get_n_channels(pix); if (chan!=3 && chan!=4) return -1; g_string_append_printf(str, "q %.2f 0 0 %.2f 0 %.2f cm /ImBg Do Q ", pg->width, -pg->height, pg->height); p2 = buf = (char *)g_malloc(3*width*height); for (y=0; y<height; y++) { p1 = (char *)gdk_pixbuf_get_pixels(pix)+stride*y; for (x=0; x<width; x++) { *(p2++)=*(p1++); *(p2++)=*(p1++); *(p2++)=*(p1++); if (chan==4) p1++; } } zpix = do_deflate(buf, 3*width*height); g_free(buf); make_xref(xref, xref->last+1, pdfbuf->len); g_string_append_printf(pdfbuf, "%d 0 obj\n<< /Length %d /Filter /FlateDecode /Type /Xobject " "/Subtype /Image /Width %d /Height %d /ColorSpace /DeviceRGB " "/BitsPerComponent 8 >> stream\n", xref->last, zpix->len, width, height); g_string_append_len(pdfbuf, zpix->str, zpix->len); g_string_free(zpix, TRUE); g_string_append(pdfbuf, "endstream\nendobj\n"); return xref->last;}// manipulate Pdf fontsstruct PdfFont *new_pdffont(struct XrefTable *xref, GList **fonts, unsigned char *filename, int font_id, FT_Face face, int glyph_page){ GList *list; struct PdfFont *font; int i; const char *s; for (list = *fonts; list!=NULL; list = list->next) { font = (struct PdfFont *)list->data; if (!strcmp(font->filename, filename) && font->font_id == font_id && font->glyph_page == glyph_page) { font->used_in_this_page = TRUE; return font; } } font = g_malloc(sizeof(struct PdfFont)); *fonts = g_list_append(*fonts, font); font->n_obj = xref->last+1; make_xref(xref, xref->last+1, 0); // will give it a value later font->filename = g_strdup(filename); font->font_id = font_id; font->glyph_page = glyph_page; font->used_in_this_page = TRUE; font->num_glyphs_used = 0; for (i=0; i<256; i++) { font->glyphmap[i] = -1; font->advance[i] = 0; font->glyphpsnames[i] = NULL; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -