diff options
Diffstat (limited to 'gtk/gtk_print.c')
-rw-r--r-- | gtk/gtk_print.c | 525 |
1 files changed, 255 insertions, 270 deletions
diff --git a/gtk/gtk_print.c b/gtk/gtk_print.c index 0685d2f9e..dfd5a85c3 100644 --- a/gtk/gtk_print.c +++ b/gtk/gtk_print.c @@ -45,121 +45,210 @@ #include "utils/log.h" #include "utils/utils.h" -static bool nsgtk_print_plot_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style); -bool nsgtk_print_plot_line(int x0, int y0, int x1, int y1, const plot_style_t *style); -static bool nsgtk_print_plot_polygon(const int *p, unsigned int n, colour fill); -static bool nsgtk_print_plot_path(const float *p, unsigned int n, colour fill, - float width, colour c, const float transform[6]); -static bool nsgtk_print_plot_clip(int clip_x0, int clip_y0, - int clip_x1, int clip_y1); -static bool nsgtk_print_plot_text(int x, int y, const struct css_style *style, - const char *text, size_t length, colour bg, colour c); -static bool nsgtk_print_plot_disc(int x, int y, int radius, colour c, - bool filled); -static bool nsgtk_print_plot_arc(int x, int y, int radius, int angle1, - int angle2, colour c); -static bool nsgtk_print_plot_bitmap(int x, int y, int width, int height, - struct bitmap *bitmap, colour bg, - bitmap_flags_t flags); - -static void nsgtk_print_set_solid(void); /**< Set for drawing solid lines */ -static void nsgtk_print_set_dotted(void); /**< Set for drawing dotted lines */ -static void nsgtk_print_set_dashed(void); /**< Set for drawing dashed lines */ +/* Globals */ +cairo_t *gtk_print_current_cr; +static struct print_settings* settings; +struct content *content_to_print; +static GdkRectangle cliprect; + +static inline void nsgtk_print_set_colour(colour c) +{ + int r, g, b; + GdkColor colour; + + r = c & 0xff; + g = (c & 0xff00) >> 8; + b = (c & 0xff0000) >> 16; + + colour.red = r | (r << 8); + colour.green = g | (g << 8); + colour.blue = b | (b << 8); + colour.pixel = (r << 16) | (g << 8) | b; + + gdk_color_alloc(gdk_colormap_get_system(), &colour); + + cairo_set_source_rgba(gtk_print_current_cr, r / 255.0, + g / 255.0, b / 255.0, 1.0); +} + +static bool nsgtk_print_plot_pixbuf(int x, int y, int width, int height, + GdkPixbuf *pixbuf, colour bg) +{ + /* XXX: This currently ignores the background colour supplied. + * Does this matter? + */ + + if (width == 0 || height == 0) + return true; + + if (gdk_pixbuf_get_width(pixbuf) == width && + gdk_pixbuf_get_height(pixbuf) == height) { + gdk_cairo_set_source_pixbuf(gtk_print_current_cr, pixbuf, x, y); + cairo_paint(gtk_print_current_cr); + } else { + GdkPixbuf *scaled; + scaled = gdk_pixbuf_scale_simple(pixbuf, + width, height, + /* plotting for the printer doesn't have + * to be fast so we can use always the + * interp_style that gives better quality + */ + GDK_INTERP_BILINEAR); + if (!scaled) + return false; + + gdk_cairo_set_source_pixbuf(gtk_print_current_cr, scaled, x, y); + cairo_paint(gtk_print_current_cr); + g_object_unref(scaled); + } + + return true; +} -static void nsgtk_print_set_colour(colour c); static bool gtk_print_font_paint(const struct css_style *style, const char *string, size_t length, - int x, int y, colour c); + int x, int y, colour c) +{ + PangoFontDescription *desc; + PangoLayout *layout; + gint size; + PangoLayoutLine *line; + if (length == 0) + return true; -static bool gtk_print_begin(struct print_settings* settings); -static bool gtk_print_next_page(void); -static void gtk_print_end(void); + desc = nsfont_style_to_description(style); + size = (gint) ((double) pango_font_description_get_size(desc) * + settings->scale); -/* Globals */ -cairo_t *gtk_print_current_cr; -static struct print_settings* settings; -struct content *content_to_print; -static GdkRectangle cliprect; + if (pango_font_description_get_size_is_absolute(desc)) + pango_font_description_set_absolute_size(desc, size); + else + pango_font_description_set_size(desc, size); -static const struct plotter_table nsgtk_print_plotters = { - .rectangle = nsgtk_print_plot_rectangle, - .line = nsgtk_print_plot_line, - .polygon = nsgtk_print_plot_polygon, - .clip = nsgtk_print_plot_clip, - .text = nsgtk_print_plot_text, - .disc = nsgtk_print_plot_disc, - .arc = nsgtk_print_plot_arc, - .bitmap = nsgtk_print_plot_bitmap, - .path = nsgtk_print_plot_path, - .option_knockout = false, -}; + layout = pango_cairo_create_layout(gtk_print_current_cr); -static const struct printer gtk_printer = { - &nsgtk_print_plotters, - gtk_print_begin, - gtk_print_next_page, - gtk_print_end -}; + pango_layout_set_font_description(layout, desc); + pango_layout_set_text(layout, string, length); + + line = pango_layout_get_line(layout, 0); + + cairo_move_to(gtk_print_current_cr, x, y); + nsgtk_print_set_colour(c); + pango_cairo_show_layout_line(gtk_print_current_cr, line); + + g_object_unref(layout); + pango_font_description_free(desc); -bool nsgtk_print_plot_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style) + return true; +} + + +/** Set cairo context to solid plot operation. */ +static inline void nsgtk_print_set_solid(void) { - LOG(("x0: %i ;\t y0: %i ;\t x1: %i ;\t y1: %i", x0,y0,x1,y1)); + double dashes = 0; + cairo_set_dash(gtk_print_current_cr, &dashes, 0, 0); +} - if (style->fill_type != PLOT_OP_TYPE_NONE) { +/** Set cairo context to dotted plot operation. */ +static inline void nsgtk_print_set_dotted(void) +{ + double cdashes[] = { 1.0, 2.0 }; + cairo_set_dash(gtk_print_current_cr, cdashes, 1, 0); +} - nsgtk_print_set_colour(style->fill_colour); - nsgtk_print_set_solid(); +/** Set cairo context to dashed plot operation. */ +static inline void nsgtk_print_set_dashed(void) +{ + double cdashes[] = { 8.0, 2.0 }; + cairo_set_dash(gtk_print_current_cr, cdashes, 1, 0); +} + +/** Set clipping area for subsequent plot operations. */ +static bool nsgtk_print_plot_clip(int clip_x0, int clip_y0, int clip_x1, int clip_y1) +{ + LOG(("Clipping. x0: %i ;\t y0: %i ;\t x1: %i ;\t y1: %i", + clip_x0,clip_y0,clip_x1,clip_y1)); - /* Normalize boundaries of the area - to prevent overflows. - * See comment in pdf_plot_fill. */ - x0 = min(max(x0, 0), settings->page_width); - y0 = min(max(y0, 0), settings->page_height); - x1 = min(max(x1, 0), settings->page_width); - y1 = min(max(y1, 0), settings->page_height); + /* Normalize cllipping area - to prevent overflows. + * See comment in pdf_plot_fill. */ + clip_x0 = min(max(clip_x0, 0), settings->page_width); + clip_y0 = min(max(clip_y0, 0), settings->page_height); + clip_x1 = min(max(clip_x1, 0), settings->page_width); + clip_y1 = min(max(clip_y1, 0), settings->page_height); + + cairo_reset_clip(gtk_print_current_cr); + cairo_rectangle(gtk_print_current_cr, clip_x0, clip_y0, + clip_x1 - clip_x0, clip_y1 - clip_y0); + cairo_clip(gtk_print_current_cr); + + cliprect.x = clip_x0; + cliprect.y = clip_y0; + cliprect.width = clip_x1 - clip_x0; + cliprect.height = clip_y1 - clip_y0; + + return true; +} + +static bool nsgtk_print_plot_arc(int x, int y, int radius, int angle1, int angle2, const plot_style_t *style) +{ + nsgtk_print_set_colour(style->fill_colour); + nsgtk_print_set_solid(); + + cairo_set_line_width(gtk_print_current_cr, 1); + cairo_arc(gtk_print_current_cr, x, y, radius, + (angle1 + 90) * (M_PI / 180), + (angle2 + 90) * (M_PI / 180)); + cairo_stroke(gtk_print_current_cr); + return true; +} + +static bool nsgtk_print_plot_disc(int x, int y, int radius, const plot_style_t *style) +{ + if (style->fill_type != PLOT_OP_TYPE_NONE) { + nsgtk_print_set_colour(style->fill_colour); + nsgtk_print_set_solid(); cairo_set_line_width(gtk_print_current_cr, 0); - cairo_rectangle(gtk_print_current_cr, x0, y0, x1 - x0, y1 - y0); + cairo_arc(gtk_print_current_cr, x, y, radius, 0, M_PI * 2); cairo_fill(gtk_print_current_cr); cairo_stroke(gtk_print_current_cr); } - if (style->stroke_type != PLOT_OP_TYPE_NONE) { - nsgtk_print_set_colour(style->stroke_colour); + if (style->stroke_type != PLOT_OP_TYPE_NONE) { + nsgtk_print_set_colour(style->stroke_colour); - switch (style->stroke_type) { - case PLOT_OP_TYPE_SOLID: /**< Solid colour */ - default: - nsgtk_print_set_solid(); - break; + switch (style->stroke_type) { + case PLOT_OP_TYPE_SOLID: /**< Solid colour */ + default: + nsgtk_print_set_solid(); + break; - case PLOT_OP_TYPE_DOT: /**< Doted plot */ - nsgtk_print_set_dotted(); - break; + case PLOT_OP_TYPE_DOT: /**< Doted plot */ + nsgtk_print_set_dotted(); + break; - case PLOT_OP_TYPE_DASH: /**< dashed plot */ - nsgtk_print_set_dashed(); - break; - } + case PLOT_OP_TYPE_DASH: /**< dashed plot */ + nsgtk_print_set_dashed(); + break; + } - if (style->stroke_width == 0) - cairo_set_line_width(gtk_print_current_cr, 1); - else - cairo_set_line_width(gtk_print_current_cr, style->stroke_width); + if (style->stroke_width == 0) + cairo_set_line_width(gtk_print_current_cr, 1); + else + cairo_set_line_width(gtk_print_current_cr, style->stroke_width); + + cairo_arc(gtk_print_current_cr, x, y, radius, 0, M_PI * 2); - cairo_rectangle(gtk_print_current_cr, x0, y0, x1 - x0, y1 - y0); cairo_stroke(gtk_print_current_cr); } - return true; } - - - -bool nsgtk_print_plot_line(int x0, int y0, int x1, int y1, const plot_style_t *style) +static bool nsgtk_print_plot_line(int x0, int y0, int x1, int y1, const plot_style_t *style) { nsgtk_print_set_colour(style->stroke_colour); @@ -190,141 +279,95 @@ bool nsgtk_print_plot_line(int x0, int y0, int x1, int y1, const plot_style_t *s return true; } - -bool nsgtk_print_plot_polygon(const int *p, unsigned int n, colour fill) +static bool nsgtk_print_plot_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style) { - unsigned int i; + LOG(("x0: %i ;\t y0: %i ;\t x1: %i ;\t y1: %i", x0,y0,x1,y1)); - LOG(("Plotting polygon.")); + if (style->fill_type != PLOT_OP_TYPE_NONE) { - nsgtk_print_set_colour(fill); - nsgtk_print_set_solid(); + nsgtk_print_set_colour(style->fill_colour); + nsgtk_print_set_solid(); - cairo_set_line_width(gtk_print_current_cr, 0); - cairo_move_to(gtk_print_current_cr, p[0], p[1]); - - LOG(("Starting line at: %i\t%i",p[0],p[1])); + /* Normalize boundaries of the area - to prevent overflows. + * See comment in pdf_plot_fill. */ + x0 = min(max(x0, 0), settings->page_width); + y0 = min(max(y0, 0), settings->page_height); + x1 = min(max(x1, 0), settings->page_width); + y1 = min(max(y1, 0), settings->page_height); - for (i = 1; i != n; i++) { - cairo_line_to(gtk_print_current_cr, p[i * 2], p[i * 2 + 1]); - LOG(("Drawing line to: %i\t%i",p[i * 2], p[i * 2 + 1])); + cairo_set_line_width(gtk_print_current_cr, 0); + cairo_rectangle(gtk_print_current_cr, x0, y0, x1 - x0, y1 - y0); + cairo_fill(gtk_print_current_cr); + cairo_stroke(gtk_print_current_cr); } - cairo_fill(gtk_print_current_cr); - cairo_stroke(gtk_print_current_cr); - - return true; -} + if (style->stroke_type != PLOT_OP_TYPE_NONE) { + nsgtk_print_set_colour(style->stroke_colour); + switch (style->stroke_type) { + case PLOT_OP_TYPE_SOLID: /**< Solid colour */ + default: + nsgtk_print_set_solid(); + break; + case PLOT_OP_TYPE_DOT: /**< Doted plot */ + nsgtk_print_set_dotted(); + break; + case PLOT_OP_TYPE_DASH: /**< dashed plot */ + nsgtk_print_set_dashed(); + break; + } -bool nsgtk_print_plot_clip(int clip_x0, int clip_y0, - int clip_x1, int clip_y1) -{ - LOG(("Clipping. x0: %i ;\t y0: %i ;\t x1: %i ;\t y1: %i", - clip_x0,clip_y0,clip_x1,clip_y1)); - - /* Normalize cllipping area - to prevent overflows. - * See comment in pdf_plot_fill. */ - clip_x0 = min(max(clip_x0, 0), settings->page_width); - clip_y0 = min(max(clip_y0, 0), settings->page_height); - clip_x1 = min(max(clip_x1, 0), settings->page_width); - clip_y1 = min(max(clip_y1, 0), settings->page_height); - - cairo_reset_clip(gtk_print_current_cr); - cairo_rectangle(gtk_print_current_cr, clip_x0, clip_y0, - clip_x1 - clip_x0, clip_y1 - clip_y0); - cairo_clip(gtk_print_current_cr); + if (style->stroke_width == 0) + cairo_set_line_width(gtk_print_current_cr, 1); + else + cairo_set_line_width(gtk_print_current_cr, style->stroke_width); - cliprect.x = clip_x0; - cliprect.y = clip_y0; - cliprect.width = clip_x1 - clip_x0; - cliprect.height = clip_y1 - clip_y0; + cairo_rectangle(gtk_print_current_cr, x0, y0, x1 - x0, y1 - y0); + cairo_stroke(gtk_print_current_cr); + } - return true; + return true; } - -bool nsgtk_print_plot_text(int x, int y, const struct css_style *style, - const char *text, size_t length, colour bg, colour c) +static bool nsgtk_print_plot_polygon(const int *p, unsigned int n, const plot_style_t *style) { - return gtk_print_font_paint(style, text, length, x, y, c); -} + unsigned int i; + LOG(("Plotting polygon.")); -bool nsgtk_print_plot_disc(int x, int y, int radius, colour c, bool filled) -{ - nsgtk_print_set_colour(c); + nsgtk_print_set_colour(style->fill_colour); nsgtk_print_set_solid(); + + cairo_set_line_width(gtk_print_current_cr, 0); + cairo_move_to(gtk_print_current_cr, p[0], p[1]); - if (filled) - cairo_set_line_width(gtk_print_current_cr, 0); - else - cairo_set_line_width(gtk_print_current_cr, 1); - - cairo_arc(gtk_print_current_cr, x, y, radius, 0, M_PI * 2); + LOG(("Starting line at: %i\t%i",p[0],p[1])); - if (filled) - cairo_fill(gtk_print_current_cr); + for (i = 1; i != n; i++) { + cairo_line_to(gtk_print_current_cr, p[i * 2], p[i * 2 + 1]); + LOG(("Drawing line to: %i\t%i",p[i * 2], p[i * 2 + 1])); + } + cairo_fill(gtk_print_current_cr); cairo_stroke(gtk_print_current_cr); return true; } -bool nsgtk_print_plot_arc(int x, int y, int radius, int angle1, int angle2, - colour c) -{ - nsgtk_print_set_colour(c); - nsgtk_print_set_solid(); - - cairo_set_line_width(gtk_print_current_cr, 1); - cairo_arc(gtk_print_current_cr, x, y, radius, - (angle1 + 90) * (M_PI / 180), - (angle2 + 90) * (M_PI / 180)); - cairo_stroke(gtk_print_current_cr); - - return true; -} -static bool nsgtk_print_plot_pixbuf(int x, int y, int width, int height, - GdkPixbuf *pixbuf, colour bg) +static bool nsgtk_print_plot_path(const float *p, unsigned int n, colour fill, + float width, colour c, const float transform[6]) { - /* XXX: This currently ignores the background colour supplied. - * Does this matter? - */ - - if (width == 0 || height == 0) - return true; - - if (gdk_pixbuf_get_width(pixbuf) == width && - gdk_pixbuf_get_height(pixbuf) == height) { - gdk_cairo_set_source_pixbuf(gtk_print_current_cr, pixbuf, x, y); - cairo_paint(gtk_print_current_cr); - } else { - GdkPixbuf *scaled; - scaled = gdk_pixbuf_scale_simple(pixbuf, - width, height, - /* plotting for the printer doesn't have - * to be fast so we can use always the - * interp_style that gives better quality - */ - GDK_INTERP_BILINEAR); - if (!scaled) - return false; - - gdk_cairo_set_source_pixbuf(gtk_print_current_cr, scaled, x, y); - cairo_paint(gtk_print_current_cr); - - g_object_unref(scaled); - } + /* Only the internal SVG renderer uses this plot call currently, + * and the GTK version uses librsvg. Thus, we ignore this complexity, + * and just return true obliviously. */ return true; } - -bool nsgtk_print_plot_bitmap(int x, int y, int width, int height, +static bool nsgtk_print_plot_bitmap(int x, int y, int width, int height, struct bitmap *bitmap, colour bg, bitmap_flags_t flags) { @@ -386,107 +429,48 @@ bool nsgtk_print_plot_bitmap(int x, int y, int width, int height, return true; } -bool nsgtk_print_plot_path(const float *p, unsigned int n, colour fill, - float width, colour c, const float transform[6]) -{ - /* Only the internal SVG renderer uses this plot call currently, - * and the GTK version uses librsvg. Thus, we ignore this complexity, - * and just return true obliviously. */ - - return true; -} - -void nsgtk_print_set_colour(colour c) -{ - int r, g, b; - GdkColor colour; - - r = c & 0xff; - g = (c & 0xff00) >> 8; - b = (c & 0xff0000) >> 16; - - colour.red = r | (r << 8); - colour.green = g | (g << 8); - colour.blue = b | (b << 8); - colour.pixel = (r << 16) | (g << 8) | b; - - gdk_color_alloc(gdk_colormap_get_system(), &colour); - - cairo_set_source_rgba(gtk_print_current_cr, r / 255.0, - g / 255.0, b / 255.0, 1.0); -} - -void nsgtk_print_set_solid(void) -{ - double dashes = 0; - - cairo_set_dash(gtk_print_current_cr, &dashes, 0, 0); -} - -void nsgtk_print_set_dotted(void) -{ - double cdashes = 1; - - cairo_set_dash(gtk_print_current_cr, &cdashes, 1, 0); -} - -void nsgtk_print_set_dashed(void) +static bool nsgtk_print_plot_text(int x, int y, const struct css_style *style, + const char *text, size_t length, colour bg, colour c) { - double cdashes = 3; - - cairo_set_dash(gtk_print_current_cr, &cdashes, 1, 0); + return gtk_print_font_paint(style, text, length, x, y, c); } -bool gtk_print_font_paint(const struct css_style *style, - const char *string, size_t length, - int x, int y, colour c) -{ - PangoFontDescription *desc; - PangoLayout *layout; - gint size; - PangoLayoutLine *line; - - if (length == 0) - return true; - - desc = nsfont_style_to_description(style); - size = (gint) ((double) pango_font_description_get_size(desc) * - settings->scale); - - if (pango_font_description_get_size_is_absolute(desc)) - pango_font_description_set_absolute_size(desc, size); - else - pango_font_description_set_size(desc, size); - - layout = pango_cairo_create_layout(gtk_print_current_cr); - - pango_layout_set_font_description(layout, desc); - pango_layout_set_text(layout, string, length); - - line = pango_layout_get_line(layout, 0); - - cairo_move_to(gtk_print_current_cr, x, y); - nsgtk_print_set_colour(c); - pango_cairo_show_layout_line(gtk_print_current_cr, line); - - g_object_unref(layout); - pango_font_description_free(desc); +/** GTK print plotter table */ +static const struct plotter_table nsgtk_print_plotters = { + .clip = nsgtk_print_plot_clip, + .arc = nsgtk_print_plot_arc, + .disc = nsgtk_print_plot_disc, + .line = nsgtk_print_plot_line, + .rectangle = nsgtk_print_plot_rectangle, + .polygon = nsgtk_print_plot_polygon, + .path = nsgtk_print_plot_path, + .bitmap = nsgtk_print_plot_bitmap, + .text = nsgtk_print_plot_text, + .option_knockout = false, +}; - return true; -} static bool gtk_print_begin(struct print_settings* settings) { return true; } + static bool gtk_print_next_page(void) { return true; } + static void gtk_print_end(void) { } +static const struct printer gtk_printer = { + &nsgtk_print_plotters, + gtk_print_begin, + gtk_print_next_page, + gtk_print_end +}; + /** * Handle the begin_print signal from the GtkPrintOperation * @@ -555,3 +539,4 @@ void gtk_print_signal_end_print(GtkPrintOperation *operation, print_cleanup(content_to_print, >k_printer, user_data); } + |