📄 xo-print.c
字号:
pdfbuf = g_string_new_len(buf, len); g_free(buf); if (pdfbuf->str[7]<'4') pdfbuf->str[7] = '4'; // upgrade to 1.4 annot = pdf_parse_info(pdfbuf, &pdfinfo, &xref); if (!annot) { g_string_free(pdfbuf, TRUE); if (xref.data != NULL) g_free(xref.data); } } if (!annot) { pdfbuf = g_string_new("%PDF-1.4\n%\370\357\365\362\n"); xref.n_alloc = xref.last = 0; xref.data = NULL; } // catalog and page tree n_obj_catalog = xref.last+1; n_obj_pages_offs = xref.last+4; make_xref(&xref, n_obj_catalog, pdfbuf->len); g_string_append_printf(pdfbuf, "%d 0 obj\n<< /Type /Catalog /Pages %d 0 R >> endobj\n", n_obj_catalog, n_obj_catalog+1); make_xref(&xref, n_obj_catalog+1, pdfbuf->len); g_string_append_printf(pdfbuf, "%d 0 obj\n<< /Type /Pages /Kids [", n_obj_catalog+1); for (i=0;i<journal.npages;i++) g_string_append_printf(pdfbuf, "%d 0 R ", n_obj_pages_offs+i); g_string_append_printf(pdfbuf, "] /Count %d >> endobj\n", journal.npages); make_xref(&xref, n_obj_catalog+2, pdfbuf->len); g_string_append_printf(pdfbuf, "%d 0 obj\n<< /Type /ExtGState /CA %.2f >> endobj\n", n_obj_catalog+2, ui.hiliter_opacity); xref.last = n_obj_pages_offs + journal.npages-1; for (pglist = journal.pages, n_page = 0; pglist!=NULL; pglist = pglist->next, n_page++) { pg = (struct Page *)pglist->data; // draw the background and page into pgstrm pgstrm = g_string_new(""); g_string_printf(pgstrm, "q 1 0 0 -1 0 %.2f cm 1 J 1 j ", pg->height); n_obj_bgpix = -1; n_obj_prefix = -1; if (pg->bg->type == BG_SOLID) pdf_draw_solid_background(pg, pgstrm); else if (pg->bg->type == BG_PDF && annot && pdfinfo.pages[pg->bg->file_page_seq-1].contents!=NULL) { make_xref(&xref, xref.last+1, pdfbuf->len); n_obj_prefix = xref.last; tmpstr = make_pdfprefix(pdfinfo.pages+(pg->bg->file_page_seq-1), pg->width, pg->height); g_string_append_printf(pdfbuf, "%d 0 obj\n<< /Length %d >> stream\n%s\nendstream\nendobj\n", n_obj_prefix, tmpstr->len, tmpstr->str); g_string_free(tmpstr, TRUE); g_string_prepend(pgstrm, "Q Q Q "); } else if (pg->bg->type == BG_PIXMAP || pg->bg->type == BG_PDF) n_obj_bgpix = pdf_draw_bitmap_background(pg, pgstrm, &xref, pdfbuf); // draw the page contents use_hiliter = FALSE; pdf_draw_page(pg, pgstrm, &use_hiliter, &xref, &pdffonts); g_string_append_printf(pgstrm, "Q\n"); // deflate pgstrm and write it zpgstrm = do_deflate(pgstrm->str, pgstrm->len); g_string_free(pgstrm, TRUE); make_xref(&xref, xref.last+1, pdfbuf->len); g_string_append_printf(pdfbuf, "%d 0 obj\n<< /Length %d /Filter /FlateDecode>> stream\n", xref.last, zpgstrm->len); g_string_append_len(pdfbuf, zpgstrm->str, zpgstrm->len); g_string_free(zpgstrm, TRUE); g_string_append(pdfbuf, "endstream\nendobj\n"); // write the page object make_xref(&xref, n_obj_pages_offs+n_page, pdfbuf->len); g_string_append_printf(pdfbuf, "%d 0 obj\n<< /Type /Page /Parent %d 0 R /MediaBox [0 0 %.2f %.2f] ", n_obj_pages_offs+n_page, n_obj_catalog+1, pg->width, pg->height); if (n_obj_prefix>0) { obj = get_pdfobj(pdfbuf, &xref, pdfinfo.pages[pg->bg->file_page_seq-1].contents); if (obj->type != PDFTYPE_ARRAY) { free_pdfobj(obj); obj = dup_pdfobj(pdfinfo.pages[pg->bg->file_page_seq-1].contents); } g_string_append_printf(pdfbuf, "/Contents [%d 0 R ", n_obj_prefix); if (obj->type == PDFTYPE_REF) g_string_append_printf(pdfbuf, "%d %d R ", obj->intval, obj->num); if (obj->type == PDFTYPE_ARRAY) { for (i=0; i<obj->num; i++) { show_pdfobj(obj->elts[i], pdfbuf); g_string_append_c(pdfbuf, ' '); } } free_pdfobj(obj); g_string_append_printf(pdfbuf, "%d 0 R] ", xref.last); } else g_string_append_printf(pdfbuf, "/Contents %d 0 R ", xref.last); g_string_append(pdfbuf, "/Resources "); if (n_obj_prefix>0) obj = dup_pdfobj(pdfinfo.pages[pg->bg->file_page_seq-1].resources); else obj = NULL; if (obj!=NULL && obj->type!=PDFTYPE_DICT) { free_pdfobj(obj); obj=NULL; } if (obj==NULL) { obj = g_malloc(sizeof(struct PdfObj)); obj->type = PDFTYPE_DICT; obj->num = 0; obj->elts = NULL; obj->names = NULL; } add_dict_subentry(pdfbuf, &xref, obj, "/ProcSet", PDFTYPE_ARRAY, NULL, mk_pdfname("/PDF")); if (n_obj_bgpix>0) add_dict_subentry(pdfbuf, &xref, obj, "/ProcSet", PDFTYPE_ARRAY, NULL, mk_pdfname("/ImageC")); if (use_hiliter) add_dict_subentry(pdfbuf, &xref, obj, "/ExtGState", PDFTYPE_DICT, "/XoHi", mk_pdfref(n_obj_catalog+2)); if (n_obj_bgpix>0) add_dict_subentry(pdfbuf, &xref, obj, "/XObject", PDFTYPE_DICT, "/ImBg", mk_pdfref(n_obj_bgpix)); for (list=pdffonts; list!=NULL; list = list->next) { font = (struct PdfFont *)list->data; if (font->used_in_this_page) { add_dict_subentry(pdfbuf, &xref, obj, "/ProcSet", PDFTYPE_ARRAY, NULL, mk_pdfname("/Text")); tmpbuf = g_strdup_printf("/F%d", font->n_obj); add_dict_subentry(pdfbuf, &xref, obj, "/Font", PDFTYPE_DICT, tmpbuf, mk_pdfref(font->n_obj)); g_free(tmpbuf); } } show_pdfobj(obj, pdfbuf); free_pdfobj(obj); g_string_append(pdfbuf, " >> endobj\n"); } // after the pages, we insert fonts for (list = pdffonts; list!=NULL; list = list->next) { font = (struct PdfFont *)list->data; embed_pdffont(pdfbuf, &xref, font); g_free(font->filename); g_free(font->fontname); g_free(font); } g_list_free(pdffonts); // PDF trailer startxref = pdfbuf->len; if (annot) g_string_append_printf(pdfbuf, "xref\n%d %d\n", n_obj_catalog, xref.last-n_obj_catalog+1); else g_string_append_printf(pdfbuf, "xref\n0 %d\n0000000000 65535 f \n", xref.last+1); for (i=n_obj_catalog; i<=xref.last; i++) g_string_append_printf(pdfbuf, "%010d 00000 n \n", xref.data[i]); g_string_append_printf(pdfbuf, "trailer\n<< /Size %d /Root %d 0 R ", xref.last+1, n_obj_catalog); if (annot) { g_string_append_printf(pdfbuf, "/Prev %d ", pdfinfo.startxref); // keeping encryption info somehow doesn't work. // xournal can't annotate encrypted PDFs anyway.../* obj = get_dict_entry(pdfinfo.trailerdict, "/Encrypt"); if (obj!=NULL) { g_string_append_printf(pdfbuf, "/Encrypt "); show_pdfobj(obj, pdfbuf); } */ } g_string_append_printf(pdfbuf, ">>\nstartxref\n%d\n%%%%EOF\n", startxref); g_free(xref.data); if (annot) { free_pdfobj(pdfinfo.trailerdict); if (pdfinfo.pages!=NULL) for (i=0; i<pdfinfo.npages; i++) { free_pdfobj(pdfinfo.pages[i].resources); free_pdfobj(pdfinfo.pages[i].mediabox); free_pdfobj(pdfinfo.pages[i].contents); } } setlocale(LC_NUMERIC, ""); if (fwrite(pdfbuf->str, 1, pdfbuf->len, f) < pdfbuf->len) { fclose(f); g_string_free(pdfbuf, TRUE); return FALSE; } fclose(f); g_string_free(pdfbuf, TRUE); return TRUE;}/*********** Printing via libgnomeprint **********/// does the same job as update_canvas_bg(), but to a print contextvoid print_background(GnomePrintContext *gpc, struct Page *pg, gboolean *abort){ double x, y; GdkPixbuf *pix; BgPdfPage *pgpdf; if (pg->bg->type == BG_SOLID) { gnome_print_setopacity(gpc, 1.0); gnome_print_setrgbcolor(gpc, RGBA_RGB(pg->bg->color_rgba)); gnome_print_rect_filled(gpc, 0, 0, pg->width, -pg->height); if (!ui.print_ruling) return; if (pg->bg->ruling == RULING_NONE) return; gnome_print_setrgbcolor(gpc, RGBA_RGB(RULING_COLOR)); gnome_print_setlinewidth(gpc, RULING_THICKNESS); if (pg->bg->ruling == RULING_GRAPH) { for (x=RULING_GRAPHSPACING; x<pg->width-1; x+=RULING_GRAPHSPACING) gnome_print_line_stroked(gpc, x, 0, x, -pg->height); for (y=RULING_GRAPHSPACING; y<pg->height-1; y+=RULING_GRAPHSPACING) gnome_print_line_stroked(gpc, 0, -y, pg->width, -y); return; } for (y=RULING_TOPMARGIN; y<pg->height-1; y+=RULING_SPACING) gnome_print_line_stroked(gpc, 0, -y, pg->width, -y); if (pg->bg->ruling == RULING_LINED) { gnome_print_setrgbcolor(gpc, RGBA_RGB(RULING_MARGIN_COLOR)); gnome_print_line_stroked(gpc, RULING_LEFTMARGIN, 0, RULING_LEFTMARGIN, -pg->height); } return; } else if (pg->bg->type == BG_PIXMAP || pg->bg->type == BG_PDF) { 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; 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(); if (*abort) return; } } pix = pgpdf->pixbuf; } else pix = pg->bg->pixbuf; if (gdk_pixbuf_get_bits_per_sample(pix) != 8) return; if (gdk_pixbuf_get_colorspace(pix) != GDK_COLORSPACE_RGB) return; gnome_print_gsave(gpc); gnome_print_scale(gpc, pg->width, pg->height); gnome_print_translate(gpc, 0., -1.); if (gdk_pixbuf_get_n_channels(pix) == 3) gnome_print_rgbimage(gpc, gdk_pixbuf_get_pixels(pix), gdk_pixbuf_get_width(pix), gdk_pixbuf_get_height(pix), gdk_pixbuf_get_rowstride(pix)); else if (gdk_pixbuf_get_n_channels(pix) == 4) gnome_print_rgbaimage(gpc, gdk_pixbuf_get_pixels(pix), gdk_pixbuf_get_width(pix), gdk_pixbuf_get_height(pix), gdk_pixbuf_get_rowstride(pix)); gnome_print_grestore(gpc); return; }}void print_page(GnomePrintContext *gpc, struct Page *pg, int pageno, double pgwidth, double pgheight, gboolean *abort){ char tmp[10]; gdouble scale; guint old_rgba; double old_thickness; GList *layerlist, *itemlist; struct Layer *l; struct Item *item; int i; double *pt; PangoFontDescription *font_desc; PangoLayout *layout; if (pg==NULL) return; g_snprintf(tmp, 10, "Page %d", pageno); gnome_print_beginpage(gpc, (guchar *)tmp); gnome_print_gsave(gpc); scale = MIN(pgwidth/pg->width, pgheight/pg->height)*0.95; gnome_print_translate(gpc, (pgwidth - scale*pg->width)/2, (pgheight + scale*pg->height)/2); gnome_print_scale(gpc, scale, scale); gnome_print_setlinejoin(gpc, 1); // round gnome_print_setlinecap(gpc, 1); // round print_background(gpc, pg, abort); old_rgba = 0x12345678; // not any values we use, so we'll reset them old_thickness = 0.0; for (layerlist = pg->layers; layerlist!=NULL; layerlist = layerlist->next) { if (*abort) break; l = (struct Layer *)layerlist->data; for (itemlist = l->items; itemlist!=NULL; itemlist = itemlist->next) { if (*abort) break; item = (struct Item *)itemlist->data; if (item->type == ITEM_STROKE || item->type == ITEM_TEXT) { if ((item->brush.color_rgba & ~0xff) != (old_rgba & ~0xff)) gnome_print_setrgbcolor(gpc, RGBA_RGB(item->brush.color_rgba)); if ((item->brush.color_rgba & 0xff) != (old_rgba & 0xff)) gnome_print_setopacity(gpc, RGBA_ALPHA(item->brush.color_rgba)); old_rgba = item->brush.color_rgba; } if (item->type == ITEM_STROKE) { if (item->brush.thickness != old_thickness) gnome_print_setlinewidth(gpc, item->brush.thickness); old_thickness = item->brush.thickness; gnome_print_newpath(gpc); pt = item->path->coords; gnome_print_moveto(gpc, pt[0], -pt[1]); for (i=1, pt+=2; i<item->path->num_points; i++, pt+=2) gnome_print_lineto(gpc, pt[0], -pt[1]); gnome_print_stroke(gpc); } if (item->type == ITEM_TEXT) { layout = gnome_print_pango_create_layout(gpc); font_desc = pango_font_description_from_string(item->font_name); pango_font_description_set_absolute_size(font_desc, item->font_size*PANGO_SCALE); pango_layout_set_font_description(layout, font_desc); pango_font_description_free(font_desc); pango_layout_set_text(layout, item->text, -1); gnome_print_moveto(gpc, item->bbox.left, -item->bbox.top); gnome_print_pango_layout(gpc, layout); g_object_unref(layout); } } } gnome_print_grestore(gpc); gnome_print_showpage(gpc);}void cb_print_abort(GtkDialog *dialog, gint response, gboolean *abort){ *abort = TRUE;}void print_job_render(GnomePrintJob *gpj, int fromPage, int toPage){ GnomePrintConfig *config; GnomePrintContext *gpc; GtkWidget *wait_dialog; double pgwidth, pgheight; int i; gboolean abort; config = gnome_print_job_get_config(gpj); gnome_print_config_get_page_size(config, &pgwidth, &pgheight); g_object_unref(G_OBJECT(config)); gpc = gnome_print_job_get_context(gpj); abort = FALSE; wait_dialog = gtk_message_dialog_new(GTK_WINDOW(winMain), GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, GTK_BUTTONS_CANCEL, "Preparing print job"); gtk_widget_show(wait_dialog); g_signal_connect(wait_dialog, "response", G_CALLBACK (cb_print_abort), &abort); for (i = fromPage; i <= toPage; i++) {#if GTK_CHECK_VERSION(2,6,0) if (!gtk_check_version(2, 6, 0)) gtk_message_dialog_format_secondary_text( GTK_MESSAGE_DIALOG(wait_dialog), "Page %d", i+1); #endif while (gtk_events_pending()) gtk_main_iteration(); print_page(gpc, (struct Page *)g_list_nth_data(journal.pages, i), i+1, pgwidth, pgheight, &abort); if (abort) break; }#if GTK_CHECK_VERSION(2,6,0) if (!gtk_check_version(2, 6, 0)) gtk_message_dialog_format_secondary_text( GTK_MESSAGE_DIALOG(wait_dialog), "Finalizing...");#endif while (gtk_events_pending()) gtk_main_iteration(); gnome_print_context_close(gpc); g_object_unref(G_OBJECT(gpc)); gnome_print_job_close(gpj); if (!abort) gnome_print_job_print(gpj); g_object_unref(G_OBJECT(gpj)); gtk_widget_destroy(wait_dialog);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -