X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=src%2Fxo-print.c;h=029500ecba345d808c4ce4901227b185294dc32e;hb=69037d6ddbe7e90d13d8a7a088d8c209a926190e;hp=bb80653a926bdb7b57e9e7d20f39f5dc362cd56f;hpb=b471a5e1ffc9ad87400f079679fdf261875d513e;p=xournal.git
diff --git a/src/xo-print.c b/src/xo-print.c
index bb80653..029500e 100644
--- a/src/xo-print.c
+++ b/src/xo-print.c
@@ -1,3 +1,18 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
#ifdef HAVE_CONFIG_H
# include
#endif
@@ -728,7 +743,7 @@ int pdf_draw_bitmap_background(struct Page *pg, GString *str,
width = (int) (PDFTOPPM_PRINTING_DPI * pgwidth/72.0);
height = (int) (PDFTOPPM_PRINTING_DPI * pgheight/72.0);
pix = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, width, height);
- poppler_page_render_to_pixbuf(
+ wrapper_poppler_page_render_to_pixbuf(
pdfpage, 0, 0, width, height, PDFTOPPM_PRINTING_DPI/72.0, 0, pix);
g_object_unref(pdfpage);
}
@@ -761,7 +776,7 @@ int pdf_draw_bitmap_background(struct Page *pg, GString *str,
make_xref(xref, xref->last+1, pdfbuf->len);
g_string_append_printf(pdfbuf,
- "%d 0 obj\n<< /Length %d /Filter /FlateDecode /Type /Xobject "
+ "%d 0 obj\n<< /Length %zu /Filter /FlateDecode /Type /Xobject "
"/Subtype /Image /Width %d /Height %d /ColorSpace /DeviceRGB "
"/BitsPerComponent 8 >> stream\n",
xref->last, zpix->len, width, height);
@@ -772,6 +787,81 @@ int pdf_draw_bitmap_background(struct Page *pg, GString *str,
return xref->last;
}
+gboolean pdf_draw_image(PdfImage *image, struct XrefTable *xref, GString *pdfbuf)
+{
+ char *buf, *p1, *p2;
+ int height, width, stride, x, y, chan;
+ GString *zpix;
+
+ if (gdk_pixbuf_get_bits_per_sample(image->pixbuf) != 8 ||
+ gdk_pixbuf_get_colorspace(image->pixbuf) != GDK_COLORSPACE_RGB) {
+ return FALSE;
+ }
+
+ width = gdk_pixbuf_get_width(image->pixbuf);
+ height = gdk_pixbuf_get_height(image->pixbuf);
+ stride = gdk_pixbuf_get_rowstride(image->pixbuf);
+ chan = gdk_pixbuf_get_n_channels(image->pixbuf);
+ if (!((chan==3 && !image->has_alpha) || (chan==4 && image->has_alpha))) {
+ return FALSE;
+ }
+
+ p2 = buf = (char *)g_malloc(3*width*height);
+ for (y=0; ypixbuf)+stride*y;
+ for (x=0; xdata[image->n_obj] = 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 ",
+ image->n_obj, zpix->len, width, height);
+ if (image->has_alpha) {
+ g_string_append_printf(pdfbuf,
+ "/SMask %d 0 R ",
+ image->n_obj_smask);
+ }
+ g_string_append_printf(pdfbuf, " >> stream\n");
+
+ g_string_append_len(pdfbuf, zpix->str, zpix->len);
+ g_string_free(zpix, TRUE);
+ g_string_append(pdfbuf, "endstream\nendobj\n");
+
+ if (image->has_alpha) {
+ p2 = buf = (char *)g_malloc(width*height);
+ for (y=0; ypixbuf)+stride*y;
+ for (x=0; xdata[image->n_obj_smask] = pdfbuf->len;
+ g_string_append_printf(pdfbuf,
+ "%d 0 obj\n<< /Length %d /Filter /FlateDecode /Type /Xobject "
+ "/Subtype /Image /Width %d /Height %d /ColorSpace /DeviceGray "
+ "/BitsPerComponent 8 >> stream\n",
+ image->n_obj_smask, 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 TRUE;
+}
+
+
// manipulate Pdf fonts
struct PdfFont *new_pdffont(struct XrefTable *xref, GList **fonts,
@@ -840,8 +930,10 @@ void embed_pdffont(GString *pdfbuf, struct XrefTable *xref, struct PdfFont *font
gboolean fallback, is_binary;
guchar encoding[256];
gushort glyphs[256];
- int i, j, num, len1, len2;
- gsize len;
+ int i, j, num;
+ guint32 len1, len2;
+ guint32 tt_len;
+ gsize t1_len;
TrueTypeFont *ttfnt;
char *seg1, *seg2;
char *fontdata, *p;
@@ -862,14 +954,14 @@ void embed_pdffont(GString *pdfbuf, struct XrefTable *xref, struct PdfFont *font
}
font->num_glyphs_used = num-1;
if (OpenTTFont(font->filename, 0, &ttfnt) == SF_OK) {
- if (CreateTTFromTTGlyphs_tomemory(ttfnt, (guint8**)&fontdata, &len, glyphs, encoding, num,
+ if (CreateTTFromTTGlyphs_tomemory(ttfnt, (guint8**)&fontdata, &tt_len, glyphs, encoding, num,
0, NULL, TTCF_AutoName | TTCF_IncludeOS2) == SF_OK) {
make_xref(xref, xref->last+1, pdfbuf->len);
nobj_fontprog = xref->last;
g_string_append_printf(pdfbuf,
- "%d 0 obj\n<< /Length %d /Length1 %d >> stream\n",
- nobj_fontprog, (int)len, (int)len);
- g_string_append_len(pdfbuf, fontdata, len);
+ "%d 0 obj\n<< /Length %u /Length1 %u >> stream\n",
+ nobj_fontprog, tt_len, tt_len);
+ g_string_append_len(pdfbuf, fontdata, tt_len);
g_string_append(pdfbuf, "endstream\nendobj\n");
g_free(fontdata);
}
@@ -879,7 +971,7 @@ void embed_pdffont(GString *pdfbuf, struct XrefTable *xref, struct PdfFont *font
else fallback = TRUE;
} else {
// embed the font file: Type1 case
- if (g_file_get_contents(font->filename, &fontdata, &len, NULL) && len>=8) {
+ if (g_file_get_contents(font->filename, &fontdata, &t1_len, NULL) && t1_len>=8) {
if (fontdata[0]==(char)0x80 && fontdata[1]==(char)0x01) {
is_binary = TRUE;
len1 = pfb_get_length((unsigned char *)fontdata+2);
@@ -898,7 +990,7 @@ void embed_pdffont(GString *pdfbuf, struct XrefTable *xref, struct PdfFont *font
if (*p=='\n' || *p=='\r') p++;
if (*p=='\n' || *p=='\r') p++;
len1 = p-fontdata;
- p = g_strrstr_len(fontdata, len, T1_SEGMENT_3_END);
+ p = g_strrstr_len(fontdata, t1_len, T1_SEGMENT_3_END);
if (p==NULL) fallback = TRUE;
else {
// rewind 512 zeros
@@ -936,7 +1028,7 @@ void embed_pdffont(GString *pdfbuf, struct XrefTable *xref, struct PdfFont *font
make_xref(xref, xref->last+1, pdfbuf->len);
nobj_fontprog = xref->last;
g_string_append_printf(pdfbuf,
- "%d 0 obj\n<< /Length %d /Length1 %d /Length2 %d /Length3 0 >> stream\n",
+ "%d 0 obj\n<< /Length %u /Length1 %u /Length2 %u /Length3 0 >> stream\n",
nobj_fontprog, len1+len2, len1, len2);
g_string_append_len(pdfbuf, seg1, len1);
g_string_append_len(pdfbuf, seg2, len2);
@@ -1006,10 +1098,31 @@ void embed_pdffont(GString *pdfbuf, struct XrefTable *xref, struct PdfFont *font
g_string_append(pdfbuf, ">> endobj\n");
}
+// Pdf images
+
+struct PdfImage *new_pdfimage(struct XrefTable *xref, GList **images, GdkPixbuf *pixbuf)
+{
+ GList *list;
+ struct PdfImage *image;
+
+ image = g_malloc(sizeof(struct PdfImage));
+ *images = g_list_append(*images, image);
+ image->n_obj = xref->last+1;
+ make_xref(xref, xref->last+1, 0); // will give it a value later
+ image->has_alpha = gdk_pixbuf_get_has_alpha(pixbuf);
+ if (image->has_alpha) {
+ image->n_obj_smask = xref->last+1;
+ make_xref(xref, xref->last+1, 0); // will give it a value later
+ }
+ image->pixbuf = pixbuf;
+
+ return image;
+}
+
// draw a page's graphics
void pdf_draw_page(struct Page *pg, GString *str, gboolean *use_hiliter,
- struct XrefTable *xref, GList **pdffonts)
+ struct XrefTable *xref, GList **pdffonts, GList **pdfimages)
{
GList *layerlist, *itemlist, *tmplist;
struct Layer *l;
@@ -1034,6 +1147,7 @@ void pdf_draw_page(struct Page *pg, GString *str, gboolean *use_hiliter,
int font_id;
FT_Face ftface;
struct PdfFont *cur_font;
+ struct PdfImage *cur_image;
gboolean in_string;
old_rgba = old_text_rgba = 0x12345678; // not any values we use, so we'll reset them
@@ -1042,6 +1156,10 @@ void pdf_draw_page(struct Page *pg, GString *str, gboolean *use_hiliter,
cur_font = (struct PdfFont *)tmplist->data;
cur_font->used_in_this_page = FALSE;
}
+ for (tmplist = *pdfimages; tmplist!=NULL; tmplist = tmplist->next) {
+ cur_image = (struct PdfImage *)tmplist->data;
+ cur_image->used_in_this_page = FALSE;
+ }
for (layerlist = pg->layers; layerlist!=NULL; layerlist = layerlist->next) {
l = (struct Layer *)layerlist->data;
@@ -1161,6 +1279,14 @@ void pdf_draw_page(struct Page *pg, GString *str, gboolean *use_hiliter,
pango_layout_iter_free(iter);
g_object_unref(layout);
}
+ else if (item->type == ITEM_IMAGE) {
+ cur_image = new_pdfimage(xref, pdfimages, item->image);
+ cur_image->used_in_this_page = TRUE;
+ g_string_append_printf(str, "\nq 1 0 0 1 %.2f %.2f cm %.2f 0 0 %.2f 0 %.2f cm /Im%d Do Q ",
+ item->bbox.left, item->bbox.top, // translation
+ item->bbox.right-item->bbox.left, item->bbox.top-item->bbox.bottom, item->bbox.bottom-item->bbox.top, // scaling
+ cur_image->n_obj);
+ }
}
}
}
@@ -1187,17 +1313,19 @@ gboolean print_to_pdf(char *filename)
gboolean use_hiliter;
struct PdfInfo pdfinfo;
struct PdfObj *obj;
- GList *pdffonts, *list;
+ GList *pdffonts, *pdfimages, *list;
struct PdfFont *font;
+ struct PdfImage *image;
char *tmpbuf;
- f = fopen(filename, "w");
+ f = fopen(filename, "wb");
if (f == NULL) return FALSE;
setlocale(LC_NUMERIC, "C");
annot = FALSE;
xref.data = NULL;
uses_pdf = FALSE;
pdffonts = NULL;
+ pdfimages = NULL;
for (pglist = journal.pages; pglist!=NULL; pglist = pglist->next) {
pg = (struct Page *)pglist->data;
if (pg->bg->type == BG_PDF) uses_pdf = TRUE;
@@ -1258,7 +1386,7 @@ gboolean print_to_pdf(char *filename)
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",
+ "%d 0 obj\n<< /Length %zu >> 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 ");
@@ -1267,7 +1395,7 @@ gboolean print_to_pdf(char *filename)
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);
+ pdf_draw_page(pg, pgstrm, &use_hiliter, &xref, &pdffonts, &pdfimages);
g_string_append_printf(pgstrm, "Q\n");
// deflate pgstrm and write it
@@ -1276,7 +1404,7 @@ gboolean print_to_pdf(char *filename)
make_xref(&xref, xref.last+1, pdfbuf->len);
g_string_append_printf(pdfbuf,
- "%d 0 obj\n<< /Length %d /Filter /FlateDecode>> stream\n",
+ "%d 0 obj\n<< /Length %zu /Filter /FlateDecode>> stream\n",
xref.last, zpgstrm->len);
g_string_append_len(pdfbuf, zpgstrm->str, zpgstrm->len);
g_string_free(zpgstrm, TRUE);
@@ -1323,7 +1451,7 @@ gboolean print_to_pdf(char *filename)
}
add_dict_subentry(pdfbuf, &xref,
obj, "/ProcSet", PDFTYPE_ARRAY, NULL, mk_pdfname("/PDF"));
- if (n_obj_bgpix>0)
+ if (n_obj_bgpix>0 || pdfimages!=NULL)
add_dict_subentry(pdfbuf, &xref,
obj, "/ProcSet", PDFTYPE_ARRAY, NULL, mk_pdfname("/ImageC"));
if (use_hiliter)
@@ -1343,12 +1471,21 @@ gboolean print_to_pdf(char *filename)
g_free(tmpbuf);
}
}
+ for (list=pdfimages; list!=NULL; list = list->next) {
+ image = (struct PdfImage *)list->data;
+ if (image->used_in_this_page) {
+ tmpbuf = g_strdup_printf("/Im%d", image->n_obj);
+ add_dict_subentry(pdfbuf, &xref,
+ obj, "/XObject", PDFTYPE_DICT, tmpbuf, mk_pdfref(image->n_obj));
+ g_free(tmpbuf);
+ }
+ }
show_pdfobj(obj, pdfbuf);
free_pdfobj(obj);
g_string_append(pdfbuf, " >> endobj\n");
}
- // after the pages, we insert fonts
+ // after the pages, we insert fonts and images
for (list = pdffonts; list!=NULL; list = list->next) {
font = (struct PdfFont *)list->data;
embed_pdffont(pdfbuf, &xref, font);
@@ -1357,6 +1494,14 @@ gboolean print_to_pdf(char *filename)
g_free(font);
}
g_list_free(pdffonts);
+ for (list = pdfimages; list!=NULL; list = list->next) {
+ image = (struct PdfImage *)list->data;
+ if (!pdf_draw_image(image, &xref, pdfbuf)) {
+ return FALSE;
+ }
+ g_free(image);
+ }
+ g_list_free(pdfimages);
// PDF trailer
startxref = pdfbuf->len;
@@ -1548,6 +1693,16 @@ void print_job_render_page(GtkPrintOperation *print, GtkPrintContext *context, g
pango_cairo_show_layout(cr, layout);
g_object_unref(layout);
}
+ if (item->type == ITEM_IMAGE) {
+ double scalex = (item->bbox.right-item->bbox.left)/gdk_pixbuf_get_width(item->image);
+ double scaley = (item->bbox.bottom-item->bbox.top)/gdk_pixbuf_get_height(item->image);
+ cairo_scale(cr, scalex, scaley);
+ gdk_cairo_set_source_pixbuf(cr,item->image, item->bbox.left/scalex, item->bbox.top/scaley);
+ cairo_scale(cr, 1/scalex, 1/scaley);
+ cairo_paint(cr);
+ old_rgba = predef_colors_rgba[COLOR_BLACK];
+ cairo_set_source_rgb(cr, 0, 0, 0);
+ }
}
}
}