/* * R : A Computer Langage for Statistical Data Analysis * Copyright (C) 1998-2004 Lyndon Drake * and the 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, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "gdkrotated.h" #include void gdk_draw_text_rot(GdkDrawable *drawable, GdkFont *font, GdkGC *gc, int x, int y, int maxx, int maxy, const gchar *text, gint text_length, double angle) { GdkColor black, white; GdkPixmap *pixmap; GdkGC *rotgc; GdkImage *image; int lbearing, rbearing, width, ascent, descent, height; int dx, dy; int i, j, mini, minj, maxi, maxj; double sintheta, costheta; /* sanity check */ if((text == NULL) || (*text == '\0')) return; /* shortcut horizontal text */ if(angle == 0.0) { gdk_draw_text(drawable, font, gc, x, y, text, text_length); } else { /* text metrics */ gdk_text_extents(font, text, text_length, &lbearing, &rbearing, &width, &ascent, &descent); height = ascent + descent; /* draw text into pixmap */ pixmap = gdk_pixmap_new(drawable, width, height, 1); rotgc = gdk_gc_new(pixmap); gdk_gc_set_font(rotgc, font); white.pixel = gdk_rgb_xpixel_from_rgb(0xffffffff); black.pixel = gdk_rgb_xpixel_from_rgb(0); gdk_gc_set_foreground(rotgc, &white); gdk_draw_rectangle (pixmap, rotgc, 1, 0, 0, width, height); gdk_gc_set_foreground(rotgc, &black); gdk_draw_text(pixmap, font, rotgc, 0, ascent, text, text_length); image = gdk_image_get(pixmap, 0, 0, width, height); /* precalc cos/sin of angle */ /* the floor(x * 1000.0 + 0.5) / 1000.0 is a hack to round things off */ costheta = floor(cos(angle) * 1000.0 + 0.5) / 1000.0; sintheta = floor(sin(angle) * 1000.0 + 0.5) / 1000.0; /* calculate bounding box for i and j iteration */ mini = maxi = floor((double)(0 - ascent) * sintheta) + x; minj = maxj = floor((double)(0 - ascent) * costheta) + y; i = floor((double)width * costheta + (double)(height - ascent) * sintheta) + x; j = floor(- (double)width * sintheta + (double)(height - ascent) * costheta) + y; if(i < mini) mini = i; if(i > maxi) maxi = i; if(j < minj) minj = j; if(j > maxj) maxj = j; i = floor((double)(height - ascent) * sintheta) + x; j = floor((double)(height - ascent) * costheta) + y; if(i < mini) mini = i; if(i > maxi) maxi = i; if(j < minj) minj = j; if(j > maxj) maxj = j; i = floor((double)width * costheta + (double)(0 - ascent) * sintheta) + x; j = floor(- (double)width * sintheta + (double)(0 - ascent) * costheta) + y; if(i < mini) mini = i; if(i > maxi) maxi = i; if(j < minj) minj = j; if(j > maxj) maxj = j; maxi++; maxj++; if(mini < 0) mini = 0; if(maxi > maxx) maxi = maxx; if(minj < 0) minj = 0; if(maxj > maxy) maxj = maxy; /* copy pixels */ for(j = minj; j < maxj; j++) { for(i = mini; i < maxi; i++) { dx = floor((double)(i - x) * costheta - (double)(j - y) * sintheta); dy = floor((double)(i - x) * sintheta + (double)(j - y) * costheta) + ascent; if((dx >= 0) && (dx < width) && (dy >= 0) && (dy < height) && (gdk_image_get_pixel(image, dx, dy) == black.pixel)) { gdk_draw_point(drawable, gc, i, j); } } } /* clean up */ gdk_pixmap_unref(pixmap); gdk_gc_unref(rotgc); } }