📄 rotated.c
字号:
/* ********************************************************************** *//* xvertext 5.0, Copyright (c) 1993 Alan Richardson (mppa3@uk.ac.sussex.syma) * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, provided * that the above copyright notice appear in all copies and that both the * copyright notice and this permission notice appear in supporting * documentation. All work developed as a consequence of the use of * this program should duly acknowledge such use. No representations are * made about the suitability of this software for any purpose. It is * provided "as is" without express or implied warranty. *//* ********************************************************************** *//* BETTER: xvertext now does rotation at any angle!! * * BEWARE: function arguments have CHANGED since version 2.0!! *//* ********************************************************************** */#include <X11/Xlib.h>#include <X11/Xutil.h>#include <X11/Xatom.h>#include <stdio.h>#include <math.h>#include "rotated.h"/* ---------------------------------------------------------------------- *//* Make sure cache size is set */#ifndef CACHE_SIZE_LIMIT#define CACHE_SIZE_LIMIT 0#endif /*CACHE_SIZE_LIMIT */ /* Make sure a cache method is specified */#ifndef CACHE_XIMAGES#ifndef CACHE_BITMAPS#define CACHE_BITMAPS#endif /*CACHE_BITMAPS*/#endif /*CACHE_XIMAGES*//* ---------------------------------------------------------------------- *//* Debugging macros */#ifdef DEBUGstatic int debug=1;#elsestatic int debug=0;#endif /*DEBUG*/#define DEBUG_PRINT1(a) if (debug) printf (a)#define DEBUG_PRINT2(a, b) if (debug) printf (a, b)#define DEBUG_PRINT3(a, b, c) if (debug) printf (a, b, c)#define DEBUG_PRINT4(a, b, c, d) if (debug) printf (a, b, c, d)#define DEBUG_PRINT5(a, b, c, d, e) if (debug) printf (a, b, c, d, e)/* ---------------------------------------------------------------------- */#ifndef M_PI#define M_PI 3.14159265358979323846#endif/* ---------------------------------------------------------------------- *//* A structure holding everything needed for a rotated string */typedef struct rotated_text_item_template { Pixmap bitmap; XImage *ximage; char *text; char *font_name; Font fid; float angle; int align; float magnify; int cols_in; int rows_in; int cols_out; int rows_out; int nl; int max_width; float *corners_x; float *corners_y; long int size; int cached; struct rotated_text_item_template *next;} RotatedTextItem;RotatedTextItem *first_text_item=NULL;/* ---------------------------------------------------------------------- *//* A structure holding current magnification and bounding box padding */static struct style_template { float magnify; int bbx_pad;} style={ 1., 0 };/* ---------------------------------------------------------------------- */static char *my_strdup();static char *my_strtok();float XRotVersion();void XRotSetMagnification();void XRotSetBoundingBoxPad();int XRotDrawString();int XRotDrawImageString();int XRotDrawAlignedString();int XRotDrawAlignedImageString();XPoint *XRotTextExtents();static XImage *MakeXImage();static int XRotPaintAlignedString();static int XRotDrawHorizontalString();static RotatedTextItem *XRotRetrieveFromCache();static RotatedTextItem *XRotCreateTextItem();static void XRotAddToLinkedList();static void XRotFreeTextItem();static XImage *XRotMagnifyImage();/* ---------------------------------------------------------------------- *//**************************************************************************//* Routine to mimic `strdup()' (some machines don't have it) *//**************************************************************************/static char *my_strdup(str) char *str;{ char *s; if(str==NULL) return NULL; s=(char *)malloc((unsigned)(strlen(str)+1)); if(s!=NULL) strcpy(s, str); return s;}/* ---------------------------------------------------------------------- *//**************************************************************************//* Routine to replace `strtok' : this one returns a zero length string if *//* it encounters two consecutive delimiters *//**************************************************************************/static char *my_strtok(str1, str2) char *str1, *str2;{ char *ret; int i, j, stop; static int start, len; static char *stext; if(str2==NULL) return NULL; /* initialise if str1 not NULL */ if(str1!=NULL) { start=0; stext=str1; len=strlen(str1); } /* run out of tokens ? */ if(start>=len) return NULL; /* loop through characters */ for(i=start; i<len; i++) { /* loop through delimiters */ stop=0; for(j=0; j<strlen(str2); j++) if(stext[i]==str2[j]) stop=1; if(stop) break; } stext[i]='\0'; ret=stext+start; start=i+1; return ret;}/* ---------------------------------------------------------------------- *//**************************************************************************//* Return version/copyright information *//**************************************************************************/float XRotVersion(str, n) char *str; int n;{ if(str!=NULL) strncpy(str, XV_COPYRIGHT, n); return XV_VERSION;}/* ---------------------------------------------------------------------- *//**************************************************************************//* Set the font magnification factor for all subsequent operations *//**************************************************************************/void XRotSetMagnification(m) float m;{ if(m>0.) style.magnify=m;}/* ---------------------------------------------------------------------- *//**************************************************************************//* Set the padding used when calculating bounding boxes *//**************************************************************************/void XRotSetBoundingBoxPad(p) int p;{ if(p>=0) style.bbx_pad=p;}/* ---------------------------------------------------------------------- *//**************************************************************************//* Create an XImage structure and allocate memory for it *//**************************************************************************/static XImage *MakeXImage(dpy, w, h) Display *dpy; int w, h;{ XImage *I; char *data; /* reserve memory for image */ data=(char *)calloc((unsigned)(((w-1)/8+1)*h), 1); if(data==NULL) return NULL; /* create the XImage */ I=XCreateImage(dpy, DefaultVisual(dpy, DefaultScreen(dpy)), 1, XYBitmap, 0, data, w, h, 8, 0); if(I==NULL) return NULL; I->byte_order=I->bitmap_bit_order=MSBFirst; return I;}/* ---------------------------------------------------------------------- *//**************************************************************************//* A front end to XRotPaintAlignedString: *//* -no alignment, no background *//**************************************************************************/int XRotDrawString(dpy, font, angle, drawable, gc, x, y, str) Display *dpy; XFontStruct *font; float angle; Drawable drawable; GC gc; int x, y; char *str;{ return (XRotPaintAlignedString(dpy, font, angle, drawable, gc, x, y, str, NONE, 0));}/* ---------------------------------------------------------------------- *//**************************************************************************//* A front end to XRotPaintAlignedString: *//* -no alignment, paints background *//**************************************************************************/int XRotDrawImageString(dpy, font, angle, drawable, gc, x, y, str) Display *dpy; XFontStruct *font; float angle; Drawable drawable; GC gc; int x, y; char *str;{ return(XRotPaintAlignedString(dpy, font, angle, drawable, gc, x, y, str, NONE, 1));}/* ---------------------------------------------------------------------- *//**************************************************************************//* A front end to XRotPaintAlignedString: *//* -does alignment, no background *//**************************************************************************/int XRotDrawAlignedString(dpy, font, angle, drawable, gc, x, y, text, align) Display *dpy; XFontStruct *font; float angle; Drawable drawable; GC gc; int x, y; char *text; int align;{ return(XRotPaintAlignedString(dpy, font, angle, drawable, gc, x, y, text, align, 0));}/* ---------------------------------------------------------------------- *//**************************************************************************//* A front end to XRotPaintAlignedString: *//* -does alignment, paints background *//**************************************************************************/int XRotDrawAlignedImageString(dpy, font, angle, drawable, gc, x, y, text, align) Display *dpy; XFontStruct *font; float angle; Drawable drawable; GC gc; int x, y; char *text; int align;{ return(XRotPaintAlignedString(dpy, font, angle, drawable, gc, x, y, text, align, 1));}/* ---------------------------------------------------------------------- *//**************************************************************************//* Aligns and paints a rotated string *//**************************************************************************/static int XRotPaintAlignedString(dpy, font, angle, drawable, gc, x, y, text, align, bg) Display *dpy; XFontStruct *font; float angle; Drawable drawable; GC gc; int x, y; char *text; int align; int bg;{ int i; GC my_gc; int xp, yp; float hot_x, hot_y; float hot_xp, hot_yp; float sin_angle, cos_angle; RotatedTextItem *item; Pixmap bitmap_to_paint; /* return early for NULL/empty strings */ if(text==NULL) return 0; if(strlen(text)==0) return 0; /* manipulate angle to 0<=angle<360 degrees */ while(angle<0) angle+=360; while(angle>=360) angle-=360; angle*=M_PI/180; /* horizontal text made easy */ if(angle==0. && style.magnify==1.) return(XRotDrawHorizontalString(dpy, font, drawable, gc, x, y, text, align, bg)); /* get a rotated bitmap */ item=XRotRetrieveFromCache(dpy, font, angle, text, align); if(item==NULL) return 0; /* this gc has similar properties to the user's gc */ my_gc=XCreateGC(dpy, drawable, NULL, 0); XCopyGC(dpy, gc, GCForeground|GCBackground|GCFunction|GCPlaneMask, my_gc); /* alignment : which point (hot_x, hot_y) relative to bitmap centre coincides with user's specified point? */ /* y position */ if(align==TLEFT || align==TCENTRE || align==TRIGHT) hot_y=(float)item->rows_in/2*style.magnify; else if(align==MLEFT || align==MCENTRE || align==MRIGHT) hot_y=0; else if(align==BLEFT || align==BCENTRE || align==BRIGHT) hot_y=-(float)item->rows_in/2*style.magnify; else hot_y=-((float)item->rows_in/2-(float)font->descent)*style.magnify; /* x position */ if(align==TLEFT || align==MLEFT || align==BLEFT || align==NONE) hot_x=-(float)item->max_width/2*style.magnify; else if(align==TCENTRE || align==MCENTRE || align==BCENTRE) hot_x=0; else hot_x=(float)item->max_width/2*style.magnify; /* pre-calculate sin and cos */ sin_angle=sin(angle); cos_angle=cos(angle); /* rotate hot_x and hot_y around bitmap centre */ hot_xp= hot_x*cos_angle - hot_y*sin_angle; hot_yp= hot_x*sin_angle + hot_y*cos_angle; /* text background will be drawn using XFillPolygon */ if(bg) { GC depth_one_gc; XPoint *xpoints; Pixmap empty_stipple; /* reserve space for XPoints */ xpoints=(XPoint *)malloc((unsigned)(4*item->nl*sizeof(XPoint))); if(!xpoints) return 1; /* rotate corner positions */ for(i=0; i<4*item->nl; i++) { xpoints[i].x=(float)x + ( (item->corners_x[i]-hot_x)*cos_angle + (item->corners_y[i]+hot_y)*sin_angle); xpoints[i].y=(float)y + (-(item->corners_x[i]-hot_x)*sin_angle + (item->corners_y[i]+hot_y)*cos_angle); } /* we want to swap foreground and background colors here; XGetGCValues() is only available in R4+ */ empty_stipple=XCreatePixmap(dpy, drawable, 1, 1, 1); depth_one_gc=XCreateGC(dpy, empty_stipple, NULL, 0); XSetForeground(dpy, depth_one_gc, 0); XFillRectangle(dpy, empty_stipple, depth_one_gc, 0, 0, 2, 2); XSetStipple(dpy, my_gc, empty_stipple); XSetFillStyle(dpy, my_gc, FillOpaqueStippled); XFillPolygon(dpy, drawable, my_gc, xpoints, 4*item->nl, Nonconvex, CoordModeOrigin); /* free our resources */ free((char *)xpoints); XFreeGC(dpy, depth_one_gc); XFreePixmap(dpy, empty_stipple); } /* where should top left corner of bitmap go ? */ xp=(float)x-((float)item->cols_out/2 +hot_xp); yp=(float)y-((float)item->rows_out/2 -hot_yp);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -