/* gtkplotgnome - gnome-print driver * Copyright 1999-2001 Adrian E. Feiguin */ #ifdef WITH_GNOME_PRINT #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "gtkplotgnome.h" static void gtk_plot_gnome_class_init (GtkPlotGnomeClass *klass); static void gtk_plot_gnome_init (GtkPlotGnome *ps); static void gtk_plot_gnome_finalize (GtkObject *object); static void gtk_plot_gnome_set_size (GtkPlotGnome *ps, gint units, gdouble width, gdouble height); /*********************************************************************/ /* Postscript specific functions */ static gboolean init (GtkPlotPC *pc); static void setviewport (GtkPlotPC *pc, gdouble w, gdouble h); static void leave (GtkPlotPC *pc); static void gsave (GtkPlotPC *pc); static void grestore (GtkPlotPC *pc); static void clip (GtkPlotPC *pc, const GdkRectangle *area); static void clipmask (GtkPlotPC *pc, gdouble x, gdouble y, const GdkBitmap *mask); static void drawlines (GtkPlotPC *pc, GtkPlotPoint *points, gint numpoints); static void drawpoint (GtkPlotPC *pc, gdouble x, gdouble y); static void drawline (GtkPlotPC *pc, gdouble x0, gdouble y0, gdouble xf, gdouble yf); static void drawpolygon (GtkPlotPC *pc, gboolean filled, GtkPlotPoint *points, gint numpoints); static void drawrectangle (GtkPlotPC *pc, gboolean filled, gdouble x, gdouble y, gdouble width, gdouble height); static void drawcircle (GtkPlotPC *pc, gboolean filled, gdouble x, gdouble y, gdouble size); static void drawellipse (GtkPlotPC *pc, gboolean filled, gdouble x, gdouble y, gdouble width, gdouble height); static void setcolor (GtkPlotPC *pc, const GdkColor *color); static void setlineattr (GtkPlotPC *pc, gfloat line_width, GdkLineStyle line_style, GdkCapStyle cap_style, GdkJoinStyle join_style); static void drawstring (GtkPlotPC *pc, gint x, gint y, gint angle, const GdkColor *fg, const GdkColor *bg, gboolean transparent, gint border, gint border_space, gint border_width, gint shadow_width, const gchar *font, gint height, GtkJustification just, const gchar *text); static void setfont (GtkPlotPC *pc, GtkPSFont *psfont, gint height); static void setdash (GtkPlotPC *pc, gdouble offset, gdouble *values, gint num_values); static void drawpixmap (GtkPlotPC *pc, GdkPixmap *pixmap, GdkBitmap *mask, gint xsrc, gint ysrc, gint xdest, gint ydest, gint width, gint height, gdouble sx, gdouble sy); /*********************************************************************/ static GtkPlotPCClass *parent_class = NULL; GtkType gtk_plot_gnome_get_type (void) { static GtkType pc_type = 0; if (!pc_type) { GtkTypeInfo pc_info = { "GtkPlotGnome", sizeof (GtkPlotGnome), sizeof (GtkPlotGnomeClass), (GtkClassInitFunc) gtk_plot_gnome_class_init, (GtkObjectInitFunc) gtk_plot_gnome_init, /* reserved 1*/ NULL, /* reserved 2 */ NULL, (GtkClassInitFunc) NULL, }; pc_type = gtk_type_unique (GTK_TYPE_PLOT_PC, &pc_info); } return pc_type; } static void gtk_plot_gnome_init (GtkPlotGnome *ps) { ps->scalex = 1.0; ps->scaley = 1.0; ps->gsaved = FALSE; } static void gtk_plot_gnome_class_init (GtkPlotGnomeClass *klass) { GtkObjectClass *object_class; GtkPlotPCClass *pc_class; parent_class = gtk_type_class (gtk_plot_pc_get_type ()); object_class = (GtkObjectClass *) klass; pc_class = (GtkPlotPCClass *) klass; pc_class->init = init; pc_class->leave = leave; pc_class->set_viewport = setviewport; pc_class->gsave = gsave; pc_class->grestore = grestore; pc_class->clip = clip; pc_class->clip_mask = clipmask; pc_class->set_color = setcolor; pc_class->set_dash = setdash; pc_class->set_lineattr = setlineattr; pc_class->draw_point = drawpoint; pc_class->draw_line = drawline; pc_class->draw_lines = drawlines; pc_class->draw_rectangle = drawrectangle; pc_class->draw_polygon = drawpolygon; pc_class->draw_circle = drawcircle; pc_class->draw_ellipse = drawellipse; pc_class->set_font = setfont; pc_class->draw_string = drawstring; pc_class->draw_pixmap = drawpixmap; object_class->finalize = gtk_plot_gnome_finalize; } static void gtk_plot_gnome_finalize(GtkObject *object) { GtkPlotGnome *ps; ps = GTK_PLOT_GNOME(object); gnome_print_context_close(ps->ctx); } GtkObject * gtk_plot_gnome_new (GnomePrinter *printer, gint orientation, gint page_size) { GtkObject *object; GtkPlotGnome *ps; object = gtk_type_new(gtk_plot_gnome_get_type()); ps = GTK_PLOT_GNOME(object); gtk_plot_gnome_construct(ps, printer, orientation, page_size); return (object); } void gtk_plot_gnome_construct (GtkPlotGnome *ps, GnomePrinter *printer, gint orientation, gint page_size) { gint width, height; GnomePaper *paper; gchar *paper_name[] = { "US-Letter", "Legal", "a4", "Executive" }; ps->orientation = orientation; ps->page_size = page_size; switch (page_size){ case GTK_PLOT_LEGAL: width = GTK_PLOT_LEGAL_W; height = GTK_PLOT_LEGAL_H; break; case GTK_PLOT_A4: width = GTK_PLOT_A4_W; height = GTK_PLOT_A4_H; break; case GTK_PLOT_EXECUTIVE: width = GTK_PLOT_EXECUTIVE_W; height = GTK_PLOT_EXECUTIVE_H; break; case GTK_PLOT_LETTER: default: width = GTK_PLOT_LETTER_W; height = GTK_PLOT_LETTER_H; } gtk_plot_gnome_set_size(ps, GTK_PLOT_PSPOINTS, width, height); ps->ctx = gnome_print_context_new_with_paper_size(printer, paper_name[page_size]); } /* GtkObject * gtk_plot_gnome_new_with_size (GnomePrinter *printer, gint orientation, gint units, gdouble width, gdouble height) { GtkObject *object; GtkPlotGnome *ps; object = gtk_type_new(gtk_plot_gnome_get_type()); ps = GTK_PLOT_GNOME(object); gtk_plot_gnome_construct_with_size (ps, printer, orientation, units, width, height); return object; } void gtk_plot_gnome_construct_with_size (GtkPlotGnome *ps, GnomePrinter *printer, gint orientation, gint units, gdouble width, gdouble height) { gtk_plot_gnome_construct(ps, printer, orientation, GTK_PLOT_CUSTOM); gtk_plot_gnome_set_size(ps, units, width, height); } */ GtkObject * gtk_plot_gnome_preview_new (GnomeCanvas *canvas, gint orientation, gint page_size) { GtkObject *object; GtkPlotGnome *ps; object = gtk_type_new(gtk_plot_gnome_get_type()); ps = GTK_PLOT_GNOME(object); gtk_plot_gnome_preview_construct(ps, canvas, orientation, page_size); return (object); } void gtk_plot_gnome_preview_construct (GtkPlotGnome *ps, GnomeCanvas *canvas, gint orientation, gint page_size) { gint width, height; GnomePaper *paper; gchar *paper_name[] = { "US-Letter", "Legal", "a4", "Executive" }; ps->orientation = orientation; ps->page_size = page_size; switch (page_size){ case GTK_PLOT_LEGAL: width = GTK_PLOT_LEGAL_W; height = GTK_PLOT_LEGAL_H; break; case GTK_PLOT_A4: width = GTK_PLOT_A4_W; height = GTK_PLOT_A4_H; break; case GTK_PLOT_EXECUTIVE: width = GTK_PLOT_EXECUTIVE_W; height = GTK_PLOT_EXECUTIVE_H; break; case GTK_PLOT_LETTER: default: width = GTK_PLOT_LETTER_W; height = GTK_PLOT_LETTER_H; } gtk_plot_gnome_set_size(ps, GTK_PLOT_PSPOINTS, width, height); ps->ctx = gnome_print_preview_new(canvas, paper_name[page_size]); } static void gtk_plot_gnome_set_size (GtkPlotGnome *ps, gint units, gdouble width, gdouble height) { ps->units = units; ps->width = width; ps->height = height; switch(units){ case GTK_PLOT_MM: ps->page_width = (gdouble)width * 2.835; ps->page_height = (gdouble)height * 2.835; break; case GTK_PLOT_CM: ps->page_width = width * 28.35; ps->page_height = height * 28.35; break; case GTK_PLOT_INCHES: ps->page_width = width * 72; ps->page_height = height * 72; break; case GTK_PLOT_PSPOINTS: default: ps->page_width = width; ps->page_height = height; } gtk_plot_pc_set_viewport(GTK_PLOT_PC(ps), ps->page_width, ps->page_height); } void gtk_plot_gnome_set_scale (GtkPlotGnome *ps, gdouble sx, gdouble sy) { ps->scalex = sx; ps->scaley = sy; } static void setviewport (GtkPlotPC *pc, gdouble w, gdouble h) { } static void setlineattr (GtkPlotPC *pc, gfloat line_width, GdkLineStyle line_style, GdkCapStyle cap_style, GdkJoinStyle join_style) { gint art_cap, art_join; GnomePrintContext *ctx = GTK_PLOT_GNOME(pc)->ctx; switch (join_style) { case GDK_JOIN_MITER: art_join = ART_PATH_STROKE_JOIN_MITER; break; case GDK_JOIN_ROUND: art_join = ART_PATH_STROKE_JOIN_ROUND; break; case GDK_JOIN_BEVEL: art_join = ART_PATH_STROKE_JOIN_BEVEL; break; default: art_join = ART_PATH_STROKE_JOIN_MITER; break; } switch (cap_style) { case GDK_CAP_BUTT: case GDK_CAP_NOT_LAST: art_cap = ART_PATH_STROKE_CAP_BUTT; break; case GDK_CAP_ROUND: art_cap = ART_PATH_STROKE_CAP_ROUND; break; case GDK_CAP_PROJECTING: art_cap = ART_PATH_STROKE_CAP_SQUARE; break; default: art_cap = ART_PATH_STROKE_CAP_BUTT; /* shut up the compiler */ break; } gnome_print_setlinewidth(ctx, line_width); gnome_print_setlinecap(ctx, art_cap); gnome_print_setlinejoin(ctx, art_join); } static void setdash(GtkPlotPC *pc, gdouble offset, gdouble *values, gint num_values) { GnomePrintContext *ctx = GTK_PLOT_GNOME(pc)->ctx; gnome_print_setdash(ctx, num_values, values, 0); } static void leave(GtkPlotPC *pc) { GnomePrintContext *ctx = GTK_PLOT_GNOME(pc)->ctx; gnome_print_showpage(ctx); } static gboolean init(GtkPlotPC *pc) { time_t now; GnomePrintContext *ctx; GtkPlotGnome *ps; now = time(NULL); ps = GTK_PLOT_GNOME(pc); ctx = ps->ctx; gnome_print_beginpage(ctx, "GtkPlotGnome output"); ps->ctx = ctx; if(ps->orientation == GTK_PLOT_PORTRAIT){ gnome_print_translate(ctx, 0, ps->page_height); gnome_print_scale(ctx, ps->scalex, -ps->scaley); } if(ps->orientation == GTK_PLOT_LANDSCAPE){ gnome_print_scale(ctx, ps->scalex, -ps->scaley); gnome_print_rotate(ctx, -90); } return TRUE; } static void setcolor(GtkPlotPC *pc, const GdkColor *color) { GnomePrintContext *ctx = GTK_PLOT_GNOME(pc)->ctx; gnome_print_setrgbcolor(ctx, (gdouble) color->red / 65535.0, (gdouble) color->green / 65535.0, (gdouble) color->blue / 65535.0); } static void drawpoint(GtkPlotPC *pc, gdouble x, gdouble y) { GnomePrintContext *ctx = GTK_PLOT_GNOME(pc)->ctx; gnome_print_newpath(ctx); gnome_print_moveto(ctx, x, y); gnome_print_lineto(ctx, x, y); gnome_print_stroke(ctx); } static void drawlines(GtkPlotPC *pc, GtkPlotPoint *points, gint numpoints) { gint i; GnomePrintContext *ctx = GTK_PLOT_GNOME(pc)->ctx; gnome_print_newpath(ctx); gnome_print_moveto(ctx, points[0].x, points[0].y); for(i = 1; i < numpoints; i++) gnome_print_lineto(ctx, points[i].x, points[i].y); gnome_print_stroke(ctx); /* for(i = 0; i < numpoints - 1; i++){ gnome_print_newpath(ctx); gnome_print_moveto(ctx, points[i].x, points[i].y); gnome_print_lineto(ctx, points[i+1].x, points[i+1].y); gnome_print_stroke(ctx); } */ } static void drawpolygon(GtkPlotPC *pc, gboolean filled, GtkPlotPoint *points, gint numpoints) { gint i; GnomePrintContext *ctx = GTK_PLOT_GNOME(pc)->ctx; gnome_print_newpath(ctx); gnome_print_moveto(ctx, points[0].x, points[0].y); for(i = 1; i < numpoints; i++) gnome_print_lineto(ctx, points[i].x, points[i].y); if(filled) gnome_print_fill(ctx); else gnome_print_closepath(ctx); gnome_print_stroke(ctx); } static void drawline(GtkPlotPC *pc, gdouble x0, gdouble y0, gdouble xf, gdouble yf) { GnomePrintContext *ctx = GTK_PLOT_GNOME(pc)->ctx; gnome_print_newpath(ctx); gnome_print_moveto(ctx, x0, y0); gnome_print_lineto(ctx, xf, yf); gnome_print_stroke(ctx); } static void drawrectangle(GtkPlotPC *pc, gboolean filled, gdouble x, gdouble y, gdouble width, gdouble height) { GtkPlotPoint point[4]; point[0].x = x; point[0].y = y; point[1].x = x + width; point[1].y = y; point[2].x = x + width; point[2].y = y + height; point[3].x = x; point[3].y = y + height; drawpolygon(pc, filled, point, 4); } static void drawcircle(GtkPlotPC *pc, gboolean filled, gdouble x, gdouble y, gdouble size) { GtkPlotPoint *points; gint i, npoints = 126; points = g_new0(GtkPlotPoint, npoints); for (i = 0; i < npoints; i++) { double th; th = (2 * 3.141592654 * i) / npoints; points[i].x = x + size / 2. * cos (th); points[i].y = y + size / 2.* sin (th); } drawpolygon(pc, filled, points, npoints); g_free(points); } static void drawellipse(GtkPlotPC *pc, gboolean filled, gdouble x, gdouble y, gdouble width, gdouble height) { GtkPlotPoint *points; gint i, npoints = 126; points = g_new0(GtkPlotPoint, npoints); for (i = 0; i < npoints; i++) { double th; th = (2 * 3.141592654 * i) / npoints; points[i].x = x + width / 2. + width / 2. * cos (th); points[i].y = y + height / 2. + height / 2. * sin (th); } drawpolygon(pc, filled, points, npoints); g_free(points); } static void drawstring (GtkPlotPC *pc, gint x, gint y, gint angle, const GdkColor *fg, const GdkColor *bg, gboolean transparent, gint border, gint border_space, gint border_width, gint shadow_width, const gchar *font, gint font_height, GtkJustification justification, const gchar *text) { GnomePrintContext *ctx; gchar *currfont; const gchar *c; GtkPSFont *psfont, *base_psfont, *latin_psfont = NULL; gint curcnt = 0, offset = 0; gint numf; gdouble scale; gboolean italic, bold; gboolean special = FALSE; GList *family; gint twidth, theight, tdescent, tascent; gint tx, ty, width, height; gint i; gchar *curstr, *lastchar = NULL, bkspchar[2], *aux, *xaux; gchar num[4]; GnomeFont *gfont = NULL; if (text == NULL || strlen(text) == 0) return; ctx = GTK_PLOT_GNOME(pc)->ctx; gtk_psfont_get_families(&family, &numf); base_psfont = psfont = gtk_psfont_get_font(font); italic = psfont->italic; bold = psfont->bold; currfont = psfont->family; gfont = gnome_font_new_closest(psfont->family, bold ? GNOME_FONT_BOLD : 0, italic, font_height); gnome_print_setfont(ctx, gfont); gtk_plot_text_get_area(text, angle, justification, font, font_height, &tx, &ty, &width, &height); tx += x; ty += y; if(!transparent){ setcolor(pc, bg); gtk_plot_pc_draw_rectangle(pc, TRUE, tx - border_space, ty - border_space, width + 2*border_space, height + 2*border_space); } /* border */ setcolor(pc, fg); setdash(pc, 0, NULL, 0); setlineattr(pc, border_width, 0, 0, 0); switch(border){ case GTK_PLOT_BORDER_SHADOW: drawrectangle(pc, TRUE, tx - border_space + shadow_width, ty + height + border_space, width + 2 * border_space, shadow_width); drawrectangle(pc, TRUE, tx + width + border_space, ty - border_space + shadow_width, shadow_width, height + 2 * border_space); case GTK_PLOT_BORDER_LINE: drawrectangle(pc, FALSE, tx - border_space, ty - border_space, width + 2*border_space, height + 2*border_space); case GTK_PLOT_BORDER_NONE: default: break; } gtk_plot_text_get_size(text, angle, font, font_height, &twidth, &theight, &tascent, &tdescent); if(angle == 90 || angle == 270) angle = 360 - angle; gnome_print_gsave(ctx); gnome_print_translate(ctx, x, y); gnome_print_rotate(ctx, angle); gnome_print_moveto(ctx, 0, 0); gnome_print_scale(ctx, 1, -1); if (psfont->i18n_latinfamily) special = TRUE; c = text; while(c && *c != '\0' && *c != '\n') { if(*c == '\\'){ c++; switch(*c){ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '9': case '8': case'g': case 'B': case 'b': case 'x': case 'N': case 's': case 'S': case 'i': case '-': case '+': case '^': special = TRUE; break; default: break; } } else { c++; } } x = y = 0; if(special){ switch (justification) { case GTK_JUSTIFY_LEFT: break; case GTK_JUSTIFY_RIGHT: if(angle == 0 || angle == 180){ gnome_print_moveto(ctx, -twidth, 0); x -= twidth; } else { gnome_print_moveto(ctx, -theight, 0); x -= theight; } break; case GTK_JUSTIFY_CENTER: default: if(angle == 0 || angle == 180){ gnome_print_moveto(ctx, -twidth / 2., 0); x -= twidth / 2.; } else { gnome_print_moveto(ctx, -theight / 2., 0); x -= theight / 2.; } break; } } else { switch (justification) { case GTK_JUSTIFY_LEFT: break; case GTK_JUSTIFY_RIGHT: twidth = gnome_font_get_width_string(gfont, text); gnome_print_moveto(ctx, -twidth, 0); x -= twidth; break; case GTK_JUSTIFY_CENTER: default: twidth = gnome_font_get_width_string(gfont, text); gnome_print_moveto(ctx, -twidth/2., 0); x -= twidth/2.; break; } gnome_print_show(ctx, text); gnome_print_grestore(ctx); return; } i = strlen(text) + 2; curstr = g_malloc0(sizeof(GdkWChar) * i); aux = (gchar *)text; scale = font_height; curcnt = 0; while(aux && *aux != '\0' && *aux != '\n') { if(*aux == '\\'){ aux++; switch(*aux){ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '9': curstr[curcnt] = 0; curcnt = 0; gnome_print_show(ctx, curstr); x += gnome_font_get_width_string(gfont, curstr); gnome_print_moveto(ctx, x, y); gfont = gnome_font_new_closest((gchar *)g_list_nth_data(family, *aux-'0'), bold ? GNOME_FONT_BOLD : 0, italic, scale); gnome_print_setfont(ctx, gfont); aux++; break; case '8':case 'g': curstr[curcnt] = 0; gnome_print_show(ctx, curstr); x += gnome_font_get_width_string(gfont, curstr); gnome_print_moveto(ctx, x, y); curcnt = 0; gfont = gnome_font_new("Symbol", scale); gnome_print_setfont(ctx, gfont); aux++; break; case 'B': curstr[curcnt] = 0; gnome_print_show(ctx, curstr); x += gnome_font_get_width_string(gfont, curstr); gnome_print_moveto(ctx, x, y); curcnt = 0; bold = TRUE; gfont = gnome_font_new_closest(psfont->family, GNOME_FONT_BOLD, italic, scale); gnome_print_setfont(ctx, gfont); aux++; break; case 'x': /* xaux = aux + 1; for (i=0; i<3; i++){ if (xaux[i] >= '0' && xaux[i] <= '9') num[i] = xaux[i]; else break; } if (i < 3){ aux++; break; } num[3] = '\0'; i = atoi(num); g_snprintf(num, 4, "%o", i % (64 * 8)); curstr[curcnt++] = '\\'; i = 0; while (num[i]) { curstr[curcnt++] = num[i++]; } aux += 4; */ break; case 'i': curstr[curcnt] = 0; gnome_print_show(ctx, curstr); x += gnome_font_get_width_string(gfont, curstr); gnome_print_moveto(ctx, x, y); curcnt = 0; italic = TRUE; gfont = gnome_font_new_closest(psfont->family, bold ? GNOME_FONT_BOLD : 0, TRUE, scale); gnome_print_setfont(ctx, gfont); aux++; break; case 's':case '_': curstr[curcnt] = 0; gnome_print_show(ctx, curstr); x += gnome_font_get_width_string(gfont, curstr); curcnt = 0; scale = 0.6 * font_height; offset -= (gint)scale / 2; gnome_print_moveto(ctx, x, y -(gint)scale / 2); gfont = gnome_font_new_closest(psfont->family, bold ? GNOME_FONT_BOLD : 0, italic, scale); gnome_print_setfont(ctx, gfont); aux++; break; case 'S':case '^': curstr[curcnt] = 0; gnome_print_show(ctx, curstr); x += gnome_font_get_width_string(gfont, curstr); curcnt = 0; scale = 0.6 * font_height; offset += 0.5*font_height; gnome_print_moveto(ctx, x, y + 0.5 * font_height); gfont = gnome_font_new_closest(psfont->family, bold ? GNOME_FONT_BOLD : 0, italic, scale); gnome_print_setfont(ctx, gfont); aux++; break; case 'N': curstr[curcnt] = 0; gnome_print_show(ctx, curstr); x += gnome_font_get_width_string(gfont, curstr); curcnt = 0; psfont = base_psfont; italic = psfont->italic; bold = psfont->bold; scale = font_height; gfont = gnome_font_new_closest(base_psfont->family, bold ? GNOME_FONT_BOLD : 0, italic, scale); gnome_print_setfont(ctx, gfont); gnome_print_moveto(ctx, x, y); offset = 0; aux++; break; case 'b': curstr[curcnt] = '\0'; gnome_print_show(ctx, curstr); x += gnome_font_get_width_string(gfont, curstr); curcnt = 0; bkspchar[1] = '\0'; if (lastchar) { bkspchar[0] = *lastchar; lastchar--; } else { bkspchar[0] = 'X'; lastchar = NULL; } x -= gnome_font_get_width_string(gfont, bkspchar); gnome_print_moveto(ctx, x, y); aux++; break; case '-': curstr[curcnt] = 0; gnome_print_show(ctx, curstr); x += gnome_font_get_width_string(gfont, curstr); gnome_print_moveto(ctx, x, y); curcnt = 0; scale -= 3; if (scale < 6) { scale = 6; } aux++; break; case '+': curstr[curcnt] = 0; gnome_print_show(ctx, curstr); x += gnome_font_get_width_string(gfont, curstr); gnome_print_moveto(ctx, x, y); curcnt = 0; scale += 3; aux++; break; default: if(aux && *aux != '\0' && *aux != '\n'){ curstr[curcnt++] = *aux; aux++; } break; } } else { if(aux && *aux != '\0' && *aux != '\n'){ curstr[curcnt++] = *aux; lastchar = aux; aux++; } } } curstr[curcnt] = 0; gnome_print_show(ctx, curstr); gnome_print_grestore(ctx); g_free(curstr); } static void setfont(GtkPlotPC *pc, GtkPSFont *psfont, gint height) { GnomePrintContext *ctx = GTK_PLOT_GNOME(pc)->ctx; GnomeFont *font; font = gnome_font_new(psfont->psname, height); if(!font) font = gnome_font_new("Courier", height); gnome_print_setfont(ctx, font); gtk_object_unref(GTK_OBJECT(font)); } static void gsave(GtkPlotPC *pc) { GtkPlotGnome *ps; GnomePrintContext *ctx; ps = GTK_PLOT_GNOME(pc); ctx = ps->ctx; gnome_print_gsave(ctx); ps->gsaved = TRUE; } static void grestore(GtkPlotPC *pc) { GtkPlotGnome *ps; GnomePrintContext *ctx; ps = GTK_PLOT_GNOME(pc); ctx = ps->ctx; if(!ps->gsaved) return; gnome_print_grestore(ctx); ps->gsaved = FALSE; } static void clipmask(GtkPlotPC *pc, gdouble x, gdouble y, const GdkBitmap *mask) { GnomePrintContext *ctx = GTK_PLOT_GNOME(pc)->ctx; gint width, height; gint px, py; gint npoints = 0; gint i; GtkPlotVector *points; GdkImage *image; if(!mask){ grestore(pc); return; } gdk_window_get_size((GdkWindow *)mask, &width, &height); image = gdk_image_get((GdkWindow *)mask, 0, 0, width, height); points = (GtkPlotVector *)g_malloc(width*height*sizeof(GtkPlotVector)); for(px = 0; px < width; px++){ for(py = 0; py < height; py++){ if(gdk_image_get_pixel(image, px, py)){ points[npoints].x = px; points[npoints].y = py; npoints++; break; } } } for(py = points[npoints-1].y; py < height; py++){ for(px = width - 1; px >= 0; px--){ if(gdk_image_get_pixel(image, px, py)){ points[npoints].x = px; points[npoints].y = py; npoints++; break; } } } for(px = points[npoints-1].x; px >= 0; px--){ for(py = height - 1; py >= 0; py--){ if(gdk_image_get_pixel(image, px, py)){ points[npoints].x = px; points[npoints].y = py; npoints++; break; } } } for(py = points[npoints-1].y; py >= 0; py--){ for(px = 0; px < width; px++){ if(gdk_image_get_pixel(image, px, py)){ points[npoints].x = px; points[npoints].y = py; npoints++; break; } } } gnome_print_gsave(ctx); gnome_print_newpath(ctx); gnome_print_moveto(ctx, points[0].x, points[0].y); for(i = 1; i < npoints; i++) gnome_print_lineto(ctx, points[i].x, points[i].y); gnome_print_closepath(ctx); gnome_print_clip(ctx); g_free(points); gdk_image_destroy(image); } static void clip(GtkPlotPC *pc, const GdkRectangle *clip) { GnomePrintContext *ctx = GTK_PLOT_GNOME(pc)->ctx; if(!clip){ gnome_print_grestore(ctx); return; } gnome_print_gsave(ctx); gnome_print_newpath(ctx); gnome_print_moveto(ctx, clip->x, clip->y); gnome_print_lineto(ctx, clip->x + clip->width, clip->y); gnome_print_lineto(ctx, clip->x + clip->width, clip->y + clip->height); gnome_print_lineto(ctx, clip->x, clip->y + clip->height); gnome_print_closepath(ctx); gnome_print_clip(ctx); } static void drawpixmap (GtkPlotPC *pc, GdkPixmap *pixmap, GdkBitmap *mask, gint xsrc, gint ysrc, gint xdest, gint ydest, gint width, gint height, gdouble scale_x, gdouble scale_y) { GnomePrintContext *ctx = GTK_PLOT_GNOME(pc)->ctx; GdkColormap *colormap; GdkColorContext *cc; GdkVisual *visual; guchar *rgb_image, *line; GdkImage *image; GdkImage *mask_image = NULL; gint x, y; if(!pixmap) return; colormap = gdk_colormap_get_system (); visual = gdk_visual_get_system (); cc = gdk_color_context_new(visual, colormap); image = gdk_image_get(pixmap, xsrc, ysrc, width, height); if(mask) mask_image = gdk_image_get(mask, xsrc, ysrc, width, height); gnome_print_gsave(ctx); gnome_print_translate(ctx, xdest, ydest); gnome_print_scale(ctx, width * scale_x, height * scale_y); rgb_image = g_new0(guchar, width * height * 3); line = rgb_image; for(y = height - 1; y >= 0; y--){ for(x = 0; x < width; x++){ GdkColor color; color.pixel = gdk_image_get_pixel(image, x, y); gdk_color_context_query_color(cc, &color); line[x * 3] = color.red/256; line[x * 3 + 1] = color.green/256; line[x * 3 + 2] = color.blue/256; if(mask_image){ gulong pixel; pixel = gdk_image_get_pixel(mask_image, x, y); if(pixel != 0){ line[x * 3] = 255; line[x * 3 + 1] = 255; line[x * 3 + 2] = 255; } } } line += width * 3; } gnome_print_rgbimage(ctx, rgb_image, width, height, width * 3); gnome_print_grestore(ctx); gdk_image_destroy(image); if(mask_image) gdk_image_destroy(mask_image); g_free(rgb_image); gdk_color_context_free(cc); } #endif /* WITH_GNOME_PRINT */