Rev 44544 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
/** R : A Computer Language for Statistical Data Analysis* Copyright (C) 1995, 1996 Robert Gentleman and Ross Ihaka* Copyright (C) 1997--2008 R Development Core Team** 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 program 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, a copy is available at* http://www.r-project.org/Licenses/*//* Entry points usedcairo_arccairo_clipcairo_close_pathcairo_createcairo_destroycairo_fill_preservecairo_line_tocairo_move_tocairo_new_pathcairo_paintcairo_rectanglecairo_rel_move_tocairo_reset_clipcairo_restorecairo_rotatecairo_savecairo_set_dashcairo_set_line_capcairo_set_line_joincairo_set_line_widthcairo_set_miter_limitcairo_set_operatorcairo_set_source_rgbcairo_set_source_rgbacairo_statuscairo_strokecairo_surface_destroycairo_surface_statuscairo_xlib_surface_createcairo_xlib_surface_set_sizeg_object_unref (glib)pango_cairo_create_layoutpango_cairo_show_layoutpango_font_description_freepango_font_description_newpango_font_description_set_familypango_font_description_set_sizepango_font_description_set_stylepango_font_description_set_weightpango_layout_get_linepango_layout_line_get_pixel_extentspango_layout_set_font_descriptionpango_layout_set_text*/static void Cairo_Circle(double x, double y, double r,const pGEcontext gc, pDevDesc dd);static void Cairo_Clip(double x0, double x1, double y0, double y1,pDevDesc dd);static void Cairo_Line(double x1, double y1, double x2, double y2,const pGEcontext gc, pDevDesc dd);static void Cairo_MetricInfo(int c, const pGEcontext gc,double* ascent, double* descent,double* width, pDevDesc dd);static void Cairo_NewPage(const pGEcontext gc, pDevDesc dd);static void Cairo_Polygon(int n, double *x, double *y,const pGEcontext gc, pDevDesc dd);static void Cairo_Polyline(int n, double *x, double *y,const pGEcontext gc, pDevDesc dd);static void Cairo_Rect(double x0, double y0, double x1, double y1,const pGEcontext gc, pDevDesc dd);static double Cairo_StrWidth(const char *str, const pGEcontext gc,pDevDesc dd);static void Cairo_Text(double x, double y, const char *str,double rot, double hadj,const pGEcontext gc, pDevDesc dd);static void Cairo_update(pX11Desc xd){cairo_set_source_surface (xd->xcc, xd->cs, 0, 0);cairo_paint(xd->xcc);}static void CairoColor(unsigned int col, pX11Desc xd){unsigned int alpha = R_ALPHA(col);double red, blue, green;red = R_RED(col)/255.0;green = R_GREEN(col)/255.0;blue = R_BLUE(col)/255.0;/* NB: this uses display gamma 0.6 for historical reasons,to match the previous X11 device */red = pow(red, RedGamma);green = pow(green, GreenGamma);blue = pow(blue, BlueGamma);cairo_set_source_rgba(xd->cc, red, green, blue, alpha/255.0);}/* --> See "Notes on Line Textures" in GraphicsEngine.h** 27/5/98 Paul - change to allow lty and lwd to interact:* the line texture is now scaled by the line width so that,* for example, a wide (lwd=2) dotted line (lty=2) has bigger* dots which are more widely spaced. Previously, such a line* would have "dots" which were wide, but not long, nor widely* spaced.*/static void CairoLineType(const pGEcontext gc, pX11Desc xd){cairo_t *cc = xd->cc;cairo_line_cap_t lcap = CAIRO_LINE_CAP_SQUARE;cairo_line_join_t ljoin = CAIRO_LINE_JOIN_ROUND;switch(gc->lend){case GE_ROUND_CAP: lcap = CAIRO_LINE_CAP_ROUND; break;case GE_BUTT_CAP: lcap = CAIRO_LINE_CAP_BUTT; break;case GE_SQUARE_CAP: lcap = CAIRO_LINE_CAP_SQUARE; break;}switch(gc->ljoin){case GE_ROUND_JOIN: ljoin = CAIRO_LINE_JOIN_ROUND; break;case GE_MITRE_JOIN: ljoin = CAIRO_LINE_JOIN_MITER; break;case GE_BEVEL_JOIN: ljoin = CAIRO_LINE_JOIN_BEVEL; break;}cairo_set_line_width(cc, gc->lwd);cairo_set_line_cap(cc, lcap);cairo_set_line_join(cc, ljoin);cairo_set_miter_limit(cc, gc->lmitre);if (gc->lty == 0 || gc->lty == -1)cairo_set_dash(cc, 0, 0, 0);else {double ls[16]; /* max 16x4=64 bit */int l = 0, dt = gc->lty;while (dt > 0) {ls[l] = (double)(dt&15);dt >>= 4;l++;}cairo_set_dash(cc, ls, l, 0);}}static void Cairo_Clip(double x0, double x1, double y0, double y1,pDevDesc dd){pX11Desc xd = (pX11Desc) dd->deviceSpecific;if (x1 < x0) { double h = x1; x1 = x0; x0 = h; };if (y1 < y0) { double h = y1; y1 = y0; y0 = h; };cairo_reset_clip(xd->cc);cairo_new_path(xd->cc);/* Add 1 per X11_Clip */cairo_rectangle(xd->cc, x0, y0, x1 - x0 + 1, y1 - y0 + 1);cairo_clip(xd->cc);}static void Cairo_NewPage(const pGEcontext gc, pDevDesc dd){pX11Desc xd = (pX11Desc) dd->deviceSpecific;cairo_reset_clip(xd->cc);xd->fill = R_OPAQUE(gc->fill) ? gc->fill: xd->canvas;CairoColor(xd->fill, xd);cairo_new_path(xd->cc);cairo_paint(xd->cc);Cairo_update(xd);/* Apparently needed */XSync(display, 0);}static void Cairo_Rect(double x0, double y0, double x1, double y1,const pGEcontext gc, pDevDesc dd){pX11Desc xd = (pX11Desc) dd->deviceSpecific;cairo_new_path(xd->cc);cairo_rectangle(xd->cc, x0, y0, x1 - x0, y1 - y0);if (R_ALPHA(gc->fill) > 0) {cairo_set_antialias(xd->cc, CAIRO_ANTIALIAS_NONE);CairoColor(gc->fill, xd);cairo_fill_preserve(xd->cc);cairo_set_antialias(xd->cc, xd->antialias);}if (R_ALPHA(gc->col) > 0 && gc->lty != -1) {CairoColor(gc->col, xd);CairoLineType(gc, xd);cairo_stroke(xd->cc);}}static void Cairo_Circle(double x, double y, double r,const pGEcontext gc, pDevDesc dd){pX11Desc xd = (pX11Desc) dd->deviceSpecific;cairo_new_path(xd->cc);cairo_arc(xd->cc, x, y, r + 0.5 , 0.0, 2 * M_PI);if (R_ALPHA(gc->fill) > 0) {cairo_set_antialias(xd->cc, CAIRO_ANTIALIAS_NONE);CairoColor(gc->fill, xd);cairo_fill_preserve(xd->cc);cairo_set_antialias(xd->cc, xd->antialias);}if (R_ALPHA(gc->col) > 0 && gc->lty != -1) {CairoColor(gc->col, xd);CairoLineType(gc, xd);cairo_stroke(xd->cc);}}static void Cairo_Line(double x1, double y1, double x2, double y2,const pGEcontext gc, pDevDesc dd){pX11Desc xd = (pX11Desc) dd->deviceSpecific;if (R_ALPHA(gc->col) > 0) {CairoColor(gc->col, xd);CairoLineType(gc, xd);cairo_new_path(xd->cc);cairo_move_to(xd->cc, x1, y1);cairo_line_to(xd->cc, x2, y2);cairo_stroke(xd->cc);}}static void Cairo_Polyline(int n, double *x, double *y,const pGEcontext gc, pDevDesc dd){int i;pX11Desc xd = (pX11Desc) dd->deviceSpecific;if (R_ALPHA(gc->col) > 0) {CairoColor(gc->col, xd);CairoLineType(gc, xd);cairo_new_path(xd->cc);cairo_move_to(xd->cc, x[0], y[0]);for(i = 0; i < n; i++) cairo_line_to(xd->cc, x[i], y[i]);cairo_stroke(xd->cc);}}static void Cairo_Polygon(int n, double *x, double *y,const pGEcontext gc, pDevDesc dd){int i;pX11Desc xd = (pX11Desc) dd->deviceSpecific;cairo_new_path(xd->cc);cairo_move_to(xd->cc, x[0], y[0]);for(i = 0; i < n; i++) cairo_line_to(xd->cc, x[i], y[i]);cairo_close_path(xd->cc);if (R_ALPHA(gc->fill) > 0) {cairo_set_antialias(xd->cc, CAIRO_ANTIALIAS_NONE);CairoColor(gc->fill, xd);cairo_fill_preserve(xd->cc);cairo_set_antialias(xd->cc, xd->antialias);}if (R_ALPHA(gc->col) > 0 && gc->lty != -1) {CairoColor(gc->col, xd);CairoLineType(gc, xd);cairo_stroke(xd->cc);}}static PangoFontDescription *getFont(const pGEcontext gc){PangoFontDescription *fontdesc;gint size, face = gc->fontface;if (face < 1 || face > 5) face = 1;size = gc->cex * gc->ps + 0.5;fontdesc = pango_font_description_new();if (face == 5)pango_font_description_set_family(fontdesc, "symbol");else {char *fm = gc->fontfamily;if(streql(fm, "mono")) fm = "courier";else if(streql(fm, "serif")) fm = "times";else if(streql(fm, "sans")) fm = "helvetica";pango_font_description_set_family(fontdesc, fm[0] ? fm : "helvetica");if(face == 2 || face == 4)pango_font_description_set_weight(fontdesc, PANGO_WEIGHT_BOLD);if(face == 3 || face == 4)pango_font_description_set_style(fontdesc, PANGO_STYLE_OBLIQUE);}pango_font_description_set_size(fontdesc, PANGO_SCALE * size);return fontdesc;}static PangoLayout*layoutText(PangoFontDescription *desc, cairo_t *cc, const char *str){PangoLayout *layout;layout = pango_cairo_create_layout(cc);pango_layout_set_font_description(layout, desc);pango_layout_set_text(layout, str, -1);return layout;}static voidtext_extents(PangoFontDescription *desc, cairo_t *cc,const pGEcontext gc, const gchar *str,gint *lbearing, gint *rbearing,gint *width, gint *ascent, gint *descent, int ink){PangoLayout *layout;PangoRectangle rect, lrect;layout = layoutText(desc, cc, str);pango_layout_line_get_pixel_extents(pango_layout_get_line(layout, 0),&rect, &lrect);if(width) *width = lrect.width;if(ink) {if(ascent) *ascent = PANGO_ASCENT(rect);if(descent) *descent = PANGO_DESCENT(rect);if(lbearing) *lbearing = PANGO_LBEARING(rect);if(rbearing) *rbearing = PANGO_RBEARING(rect);} else {if(ascent) *ascent = PANGO_ASCENT(lrect);if(descent) *descent = PANGO_DESCENT(lrect);if(lbearing) *lbearing = PANGO_LBEARING(lrect);if(rbearing) *rbearing = PANGO_RBEARING(lrect);}g_object_unref(layout);}static void Cairo_MetricInfo(int c, const pGEcontext gc,double* ascent, double* descent,double* width, pDevDesc dd){pX11Desc xd = (pX11Desc) dd->deviceSpecific;char str[16];int Unicode = mbcslocale;PangoFontDescription *desc = getFont(gc);gint iascent, idescent, iwidth;if(c == 0) c = 77;if(c < 0) {c = -c; Unicode = 1;}if(Unicode) {Rf_ucstoutf8(str, (unsigned int) c);} else {str[0] = c; str[1] = 0;/* Here, we assume that c < 256 */}text_extents(desc, xd->cc, gc, str, NULL, NULL,&iwidth, &iascent, &idescent, 1);*ascent = iascent;*descent = idescent;*width = iwidth;#if 0printf("c = %d, '%s', face %d %f %f %f\n",c, str, gc->fontface, *width, *ascent, *descent);#endif}static double Cairo_StrWidth(const char *str, const pGEcontext gc, pDevDesc dd){pX11Desc xd = (pX11Desc) dd->deviceSpecific;gint width;PangoFontDescription *desc = getFont(gc);text_extents(desc, xd-> cc, gc, str, NULL, NULL, &width, NULL, NULL, 0);pango_font_description_free(desc);return (double) width;}static void Cairo_Text(double x, double y,const char *str, double rot, double hadj,const pGEcontext gc, pDevDesc dd){pX11Desc xd = (pX11Desc) dd->deviceSpecific;gint ascent, lbearing, width;PangoLayout *layout;if (R_ALPHA(gc->col) > 0) {PangoFontDescription *desc = getFont(gc);cairo_save(xd->cc);text_extents(desc, xd->cc, gc, str, &lbearing, NULL, &width,&ascent, NULL, 0);cairo_move_to(xd->cc, x, y);if (rot != 0.0) cairo_rotate(xd->cc, -rot/180.*M_PI);/* pango has a coord system at top left */cairo_rel_move_to(xd->cc, -lbearing - width*hadj, -ascent);CairoColor(gc->col, xd);layout = layoutText(desc, xd->cc, str);pango_cairo_show_layout(xd->cc, layout);cairo_restore(xd->cc);g_object_unref(layout);pango_font_description_free(desc);}}