4 #ifndef _XVERTEXT_INCLUDED_
5 #define _XVERTEXT_INCLUDED_
28 #include <X11/Xutil.h>
29 #include <X11/Xatom.h>
44 #define XV_VERSION 5.0
45 #define XV_COPYRIGHT \
46 "xvertext routines Copyright (c) 1993 Alan Richardson"
74 #ifndef CACHE_SIZE_LIMIT
75 #define CACHE_SIZE_LIMIT 0
91 static int gRotatedDebug=1;
93 static int gRotatedDebug=0;
96 #define DEBUG_PRINT1(a) if (gRotatedDebug) printf (a)
97 #define DEBUG_PRINT2(a, b) if (gRotatedDebug) printf (a, b)
98 #define DEBUG_PRINT3(a, b, c) if (gRotatedDebug) printf (a, b, c)
99 #define DEBUG_PRINT4(a, b, c, d) if (gRotatedDebug) printf (a, b, c, d)
100 #define DEBUG_PRINT5(a, b, c, d, e) if (gRotatedDebug) printf (a, b, c, d, e)
105 #define M_PI 3.14159265358979323846
112 typedef struct RotatedTextItemTemplate_t {
136 struct RotatedTextItemTemplate_t *fNext;
139 static RotatedTextItem_t *gFirstTextItem=0;
145 static struct StyleTemplate_t {
154 static char *my_strdup(
char *);
155 static char *my_strtok(
char *,
char *);
157 float XRotVersion(
char*,
int);
158 void XRotSetMagnification(
float);
159 void XRotSetBoundingBoxPad(
int);
160 int XRotDrawString(Display*, XFontStruct*,
float,Drawable, GC,
int,
int,
char*);
161 int XRotDrawImageString(Display*, XFontStruct*,
float,Drawable, GC,
int,
int,
char*);
162 int XRotDrawAlignedString(Display*, XFontStruct*,
float,Drawable, GC,
int,
int,
char*,
int);
163 int XRotDrawAlignedImageString(Display*, XFontStruct*,
float,Drawable, GC,
int,
int,
char*,
int);
164 XPoint *XRotTextExtents(Display*, XFontStruct*,
float,
int,
int,
char*,
int);
166 static XImage *MakeXImage(Display *dpy,
int w,
int h);
167 static int XRotPaintAlignedString(Display *dpy, XFontStruct *font,
float angle, Drawable drawable, GC gc,
int x,
int y,
char *text,
int align,
int bg);
168 static int XRotDrawHorizontalString(Display *dpy, XFontStruct *font, Drawable drawable, GC gc,
int x,
int y,
char *text,
int align,
int bg);
169 static RotatedTextItem_t *XRotRetrieveFromCache(Display *dpy, XFontStruct *font,
float angle,
char *text,
int align);
170 static RotatedTextItem_t *XRotCreateTextItem(Display *dpy, XFontStruct *font,
float angle,
char *text,
int align);
171 static void XRotAddToLinkedList(Display *dpy, RotatedTextItem_t *item);
172 static void XRotFreeTextItem(Display *dpy, RotatedTextItem_t *item);
173 static XImage *XRotMagnifyImage(Display *dpy, XImage *ximage);
179 static char *my_strdup(
char *str)
185 s=(
char *)malloc((
unsigned)(strlen(str)+1));
186 if(s!=0) strcpy(s, str);
195 static char *my_strtok(
char *str1,
char *str2)
199 static int start, len;
202 if(str2==0)
return 0;
212 if(start>=len)
return 0;
215 for(i=start; i<len; i++) {
218 for(j=0; j<(int)strlen(str2); j++)
219 if(stext[i]==str2[j])
238 float XRotVersion(
char *str,
int n)
240 if(str!=0) strncpy(str, XV_COPYRIGHT, n);
248 void XRotSetMagnification(
float m)
250 if(m>0.) gRotStyle.fMagnify=m;
257 void XRotSetBoundingBoxPad(
int p)
259 if(p>=0) gRotStyle.fBbxPadl=p;
266 static XImage *MakeXImage(Display *dpy,
int w,
int h)
272 data=(
char *)calloc((
unsigned)(((w-1)/8+1)*h), 1);
273 if( data==0)
return 0;
276 image=XCreateImage(dpy, DefaultVisual(dpy, DefaultScreen(dpy)), 1, XYBitmap,
277 0, data, w, h, 8, 0);
283 image->byte_order=image->bitmap_bit_order=MSBFirst;
292 int XRotDrawString(Display *dpy, XFontStruct *font,
float angle,Drawable drawable, GC gc,
int x,
int y,
char *str)
294 return (XRotPaintAlignedString(dpy, font, angle, drawable, gc,
295 x, y, str, NONE, 0));
303 int XRotDrawImageString(Display *dpy,XFontStruct *font,
float angle, Drawable drawable,GC gc,
int x,
int y,
char *str)
305 return(XRotPaintAlignedString(dpy, font, angle, drawable, gc,
306 x, y, str, NONE, 1));
314 int XRotDrawAlignedString(Display *dpy, XFontStruct *font,
float angle, Drawable drawable, GC gc,
int x,
int y,
char *text,
int align)
316 return(XRotPaintAlignedString(dpy, font, angle, drawable, gc,
317 x, y, text, align, 0));
325 int XRotDrawAlignedImageString(Display *dpy, XFontStruct *font,
float angle, Drawable drawable, GC gc,
int x,
int y,
char *text,
328 return(XRotPaintAlignedString(dpy, font, angle, drawable, gc,
329 x, y, text, align, 1));
336 static int XRotPaintAlignedString(Display *dpy, XFontStruct *font,
float angle, Drawable drawable, GC gc,
int x,
int y,
char *text,
343 float hot_xp, hot_yp;
344 float sin_angle, cos_angle;
345 RotatedTextItem_t *item;
346 Pixmap bitmap_to_paint;
349 if(text==0)
return 0;
351 if(strlen(text)==0)
return 0;
354 while(angle<0) angle+=360;
356 while(angle>=360) angle-=360;
361 if(angle==0. && gRotStyle.fMagnify==1.)
362 return(XRotDrawHorizontalString(dpy, font, drawable, gc, x, y,
366 item=XRotRetrieveFromCache(dpy, font, angle, text, align);
367 if(item==0)
return 0;
370 my_gc=XCreateGC(dpy, drawable, 0, 0);
371 XCopyGC(dpy, gc, GCForeground|GCBackground|GCFunction|GCPlaneMask,
378 if(align==TLEFT || align==TCENTRE || align==TRIGHT)
379 hot_y=(float)item->fRowsIn/2*gRotStyle.fMagnify;
380 else if(align==MLEFT || align==MCENTRE || align==MRIGHT)
386 else if(align==BLEFT || align==BCENTRE || align==BRIGHT)
390 hot_y=-((float)item->fRowsIn/2-(
float)font->descent)*gRotStyle.fMagnify;
393 hot_y=-((float)item->fRowsIn/2-(
float)font->descent)*gRotStyle.fMagnify;
396 if(align==TLEFT || align==MLEFT || align==BLEFT || align==NONE)
397 hot_x=-(float)item->fMaxWidth/2*gRotStyle.fMagnify;
398 else if(align==TCENTRE || align==MCENTRE || align==BCENTRE)
401 hot_x=(float)item->fMaxWidth/2*gRotStyle.fMagnify;
404 sin_angle=TMath::Sin(angle);
405 cos_angle=TMath::Cos(angle);
408 hot_xp= hot_x*cos_angle - hot_y*sin_angle;
409 hot_yp= hot_x*sin_angle + hot_y*cos_angle;
415 Pixmap empty_stipple;
418 xpoints=(XPoint *)malloc((
unsigned)(4*item->fNl*
sizeof(XPoint)));
419 if(!xpoints)
return 1;
422 for(i=0; i<4*item->fNl; i++) {
423 xpoints[i].x=int((
float)x + ( (item->fCornersX[i]-hot_x)*cos_angle +
424 (item->fCornersY[i]+hot_y)*sin_angle));
425 xpoints[i].y=int((
float)y + (-(item->fCornersX[i]-hot_x)*sin_angle +
426 (item->fCornersY[i]+hot_y)*cos_angle));
432 empty_stipple=XCreatePixmap(dpy, drawable, 1, 1, 1);
434 depth_one_gc=XCreateGC(dpy, empty_stipple, 0, 0);
435 XSetForeground(dpy, depth_one_gc, 0);
436 XFillRectangle(dpy, empty_stipple, depth_one_gc, 0, 0, 2, 2);
438 XSetStipple(dpy, my_gc, empty_stipple);
439 XSetFillStyle(dpy, my_gc, FillOpaqueStippled);
441 XFillPolygon(dpy, drawable, my_gc, xpoints, 4*item->fNl, Nonconvex,
445 free((
char *)xpoints);
446 XFreeGC(dpy, depth_one_gc);
447 XFreePixmap(dpy, empty_stipple);
451 xp=int((
float)x-((
float)item->fColsOut/2 +hot_xp));
452 yp=int((
float)y-((
float)item->fRowsOut/2 -hot_yp));
455 bitmap_to_paint=item->fBitmap;
462 Pixmap new_bitmap, inverse;
465 if(XGetGCValues(dpy, gc,
466 GCStipple|GCFillStyle|GCForeground|GCBackground|
467 GCTileStipXOrigin|GCTileStipYOrigin,
471 if((values.fill_style==FillStippled ||
472 values.fill_style==FillOpaqueStippled) && !bg) {
475 if(values.fill_style==FillOpaqueStippled) {
476 XSetForeground(dpy, my_gc, values.background);
477 XSetFillStyle(dpy, my_gc, FillStippled);
478 XSetStipple(dpy, my_gc, item->fBitmap);
479 XSetTSOrigin(dpy, my_gc, xp, yp);
480 XFillRectangle(dpy, drawable, my_gc, xp, yp,
481 item->fColsOut, item->fRowsOut);
482 XSetForeground(dpy, my_gc, values.foreground);
486 new_bitmap=XCreatePixmap(dpy, drawable,
487 item->fColsOut, item->fRowsOut, 1);
490 depth_one_gc=XCreateGC(dpy, new_bitmap, 0, 0);
491 XSetForeground(dpy, depth_one_gc, 1);
492 XSetBackground(dpy, depth_one_gc, 0);
495 XSetTSOrigin(dpy, depth_one_gc,
496 values.ts_x_origin-xp, values.ts_y_origin-yp);
499 XSetStipple(dpy, depth_one_gc, values.stipple);
500 XSetFillStyle(dpy, depth_one_gc, FillOpaqueStippled);
501 XFillRectangle(dpy, new_bitmap, depth_one_gc,
502 0, 0, item->fColsOut, item->fRowsOut);
505 XSetTSOrigin(dpy, depth_one_gc, 0, 0);
508 inverse=XCreatePixmap(dpy, drawable,
509 item->fColsOut, item->fRowsOut, 1);
512 XSetFillStyle(dpy, depth_one_gc, FillSolid);
513 XSetFunction(dpy, depth_one_gc, GXcopyInverted);
514 XCopyArea(dpy, item->fBitmap, inverse, depth_one_gc,
515 0, 0, item->fColsOut, item->fRowsOut, 0, 0);
518 XSetForeground(dpy, depth_one_gc, 0);
519 XSetBackground(dpy, depth_one_gc, 1);
520 XSetStipple(dpy, depth_one_gc, inverse);
521 XSetFillStyle(dpy, depth_one_gc, FillStippled);
522 XSetFunction(dpy, depth_one_gc, GXcopy);
523 XFillRectangle(dpy, new_bitmap, depth_one_gc,
524 0, 0, item->fColsOut, item->fRowsOut);
527 XFreePixmap(dpy, inverse);
528 XFreeGC(dpy, depth_one_gc);
531 bitmap_to_paint=new_bitmap;
538 XSetFillStyle(dpy, my_gc, FillStippled);
539 XSetStipple(dpy, my_gc, bitmap_to_paint);
540 XSetTSOrigin(dpy, my_gc, xp, yp);
541 XFillRectangle(dpy, drawable, my_gc, xp, yp,
542 item->fColsOut, item->fRowsOut);
548 if(bitmap_to_paint!=item->fBitmap)
549 XFreePixmap(dpy, bitmap_to_paint);
552 XFreePixmap(dpy, item->fBitmap);
557 XRotFreeTextItem(dpy,item);
567 static int XRotDrawHorizontalString(Display *dpy, XFontStruct *font, Drawable drawable, GC gc,
int x,
int y,
char *text,
574 char *str1, *str2, *str3;
575 const char *str2_a=
"\0", *str2_b=
"\n\0";
579 DEBUG_PRINT1(
"**\nHorizontal text.\n");
582 my_gc=XCreateGC(dpy, drawable, 0, 0);
584 GCForeground|GCBackground|GCFunction|GCStipple|GCFillStyle|
585 GCTileStipXOrigin|GCTileStipYOrigin|GCPlaneMask, my_gc);
586 XSetFont(dpy, my_gc, font->fid);
590 for(i=0; i<(int)strlen(text)-1; i++)
601 height=font->ascent+font->descent;
604 if(align==TLEFT || align==TCENTRE || align==TRIGHT)
606 else if(align==MLEFT || align==MCENTRE || align==MRIGHT)
610 yp=y-nl*(height-font->descent)/2+font->ascent;
612 else if(align==BLEFT || align==BCENTRE || align==BRIGHT)
616 yp=y-nl*(height-font->descent)+font->ascent;
621 str1=my_strdup(text);
622 if(str1==0)
return 1;
624 str3=my_strtok(str1, str2);
629 XTextExtents(font, str3, strlen(str3), &dir, &asc, &desc,
633 if(align==TLEFT || align==MLEFT || align==BLEFT || align==NONE)
635 else if(align==TCENTRE || align==MCENTRE || align==BCENTRE)
636 xp=x-overall.rbearing/2;
638 xp=x-overall.rbearing;
642 XDrawString(dpy, drawable, my_gc, xp, yp, str3, strlen(str3));
644 XDrawImageString(dpy, drawable, my_gc, xp, yp, str3, strlen(str3));
649 str3=my_strtok((
char *)0, str2);
664 static RotatedTextItem_t *XRotRetrieveFromCache(Display *dpy, XFontStruct *font,
float angle,
char *text,
int align)
668 unsigned long name_value;
669 RotatedTextItem_t *item=0;
670 RotatedTextItem_t *i1=gFirstTextItem;
673 if(XGetFontProperty(font, XA_FONT, &name_value)) {
674 DEBUG_PRINT1(
"got font name OK\n");
675 font_name=XGetAtomName(dpy, name_value);
681 DEBUG_PRINT1(
"can't get fontname, caching FID\n");
688 DEBUG_PRINT1(
"can't get fontname, can't cache\n");
705 if(strcmp(text, i1->fText)==0 &&
706 TMath::Abs(angle-i1->fAngle)<0.00001 &&
707 gRotStyle.fMagnify==i1->fMagnify &&
709 ((align==0)?9:(align-1))%3==
710 ((i1->fAlign==0)?9:(i1->fAlign-1))%3)) {
713 if(font_name!=0 && i1->font_name!=0) {
714 if(strcmp(font_name, i1->font_name)==0) {
716 DEBUG_PRINT1(
"Matched against font names\n");
722 else if(font_name==0 && i1->font_name==0) {
725 DEBUG_PRINT1(
"Matched against FID's\n");
739 DEBUG_PRINT1(
"**\nFound target in cache.\n");
741 DEBUG_PRINT1(
"**\nNo match in cache.\n");
746 item=XRotCreateTextItem(dpy, font, angle, text, align);
751 item->fText=my_strdup(text);
755 item->font_name=my_strdup(font_name);
765 item->fMagnify=gRotStyle.fMagnify;
768 XRotAddToLinkedList(dpy, item);
781 item->fBitmap=XCreatePixmap(dpy, DefaultRootWindow(dpy),
782 item->fColsOut, item->fRowsOut, 1);
785 depth_one_gc=XCreateGC(dpy, item->fBitmap, 0, 0);
786 XSetBackground(dpy, depth_one_gc, 0);
787 XSetForeground(dpy, depth_one_gc, 1);
790 XPutImage(dpy, item->fBitmap, depth_one_gc, item->fXimage, 0, 0, 0, 0,
791 item->fColsOut, item->fRowsOut);
793 XFreeGC(dpy, depth_one_gc);
804 static RotatedTextItem_t *XRotCreateTextItem(Display *dpy, XFontStruct *font,
float angle,
char *text,
int align)
806 RotatedTextItem_t *item;
811 char *str1, *str2, *str3;
812 const char *str2_a=
"\0", *str2_b=
"\n\0";
814 int byte_w_in, byte_w_out;
816 float sin_angle, cos_angle;
824 int old_cols_in=0, old_rows_in=0;
827 item=(RotatedTextItem_t *)malloc((
unsigned)
sizeof(RotatedTextItem_t));
833 for(i=0; i<(int)strlen(text)-1; i++)
844 str1=my_strdup(text);
850 str3=my_strtok(str1, str2);
856 XTextExtents(font, str3, strlen(str3), &dir, &asc, &desc,
859 item->fMaxWidth=overall.rbearing;
863 str3=my_strtok((
char *)0, str2);
866 XTextExtents(font, str3, strlen(str3), &dir, &asc, &desc,
868 if(overall.rbearing>item->fMaxWidth)
869 item->fMaxWidth=overall.rbearing;
877 height=font->ascent+font->descent;
880 item->fColsIn=item->fMaxWidth;
881 item->fRowsIn=item->fNl*height;
884 canvas=XCreatePixmap(dpy, DefaultRootWindow(dpy),
885 item->fColsIn, item->fRowsIn, 1);
888 font_gc=XCreateGC(dpy, canvas, 0, 0);
889 XSetBackground(dpy, font_gc, 0);
890 XSetFont(dpy, font_gc, font->fid);
893 XSetForeground(dpy, font_gc, 0);
894 XFillRectangle(dpy, canvas, font_gc, 0, 0,
895 item->fColsIn+1, item->fRowsIn+1);
896 XSetForeground(dpy, font_gc, 1);
899 sin_angle=TMath::Sin(angle);
900 cos_angle=TMath::Cos(angle);
903 item->fCornersX = (
float *)malloc((
unsigned)(4*item->fNl*
sizeof(float)));
904 if(!item->fCornersX) {
909 item->fCornersY = (
float *)malloc((
unsigned)(4*item->fNl*
sizeof(float)));
910 if(!item->fCornersY) {
911 free(item->fCornersX);
921 str1=my_strdup(text);
923 free(item->fCornersX);
924 free(item->fCornersY);
929 str3=my_strtok(str1, str2);
931 free(item->fCornersX);
932 free(item->fCornersY);
939 XTextExtents(font, str3, strlen(str3), &dir, &asc, &desc,
943 if(align==TLEFT || align==MLEFT || align==BLEFT || align==NONE)
945 else if(align==TCENTRE || align==MCENTRE || align==BCENTRE)
946 xp=(item->fMaxWidth-overall.rbearing)/2;
948 xp=item->fMaxWidth-overall.rbearing;
951 XDrawString(dpy, canvas, font_gc, xp, yp, str3, strlen(str3));
954 item->fCornersX[ic]=((float)xp-(
float)item->fColsIn/2)*gRotStyle.fMagnify;
955 item->fCornersY[ic]=((
float)(yp-font->ascent)-(
float)item->fRowsIn/2)
957 item->fCornersX[ic+1]=item->fCornersX[ic];
958 item->fCornersY[ic+1]=item->fCornersY[ic]+(
float)height*gRotStyle.fMagnify;
959 item->fCornersX[item->fNl*4-1-ic]=item->fCornersX[ic]+
960 (float)overall.rbearing*gRotStyle.fMagnify;
961 item->fCornersY[item->fNl*4-1-ic]=item->fCornersY[ic];
962 item->fCornersX[item->fNl*4-2-ic]=
963 item->fCornersX[item->fNl*4-1-ic];
964 item->fCornersY[item->fNl*4-2-ic]=item->fCornersY[ic+1];
971 str3=my_strtok((
char *)0, str2);
978 imageIn=MakeXImage(dpy, item->fColsIn, item->fRowsIn);
980 free(item->fCornersX);
981 free(item->fCornersY);
987 XGetSubImage(dpy, canvas, 0, 0, item->fColsIn, item->fRowsIn,
988 1, XYPixmap, imageIn, 0, 0);
989 imageIn->format=XYBitmap;
992 if(gRotStyle.fMagnify!=1.) {
993 imageIn=XRotMagnifyImage(dpy, imageIn);
995 old_cols_in=item->fColsIn;
996 old_rows_in=item->fRowsIn;
997 item->fColsIn=int((
float)item->fColsIn*gRotStyle.fMagnify);
998 item->fRowsIn=int((
float)item->fRowsIn*gRotStyle.fMagnify);
1002 item->fColsOut=int(TMath::Abs((
float)item->fRowsIn*sin_angle) +
1003 TMath::Abs((
float)item->fColsIn*cos_angle) +0.99999 +2);
1005 item->fRowsOut=int(TMath::Abs((
float)item->fRowsIn*cos_angle) +
1006 TMath::Abs((
float)item->fColsIn*sin_angle) +0.99999 +2);
1008 if(item->fColsOut%2==0) item->fColsOut++;
1010 if(item->fRowsOut%2==0) item->fRowsOut++;
1013 item->fXimage=MakeXImage(dpy, item->fColsOut, item->fRowsOut);
1014 if(item->fXimage==0) {
1015 free(item->fCornersX);
1016 free(item->fCornersY);
1021 byte_w_in=(item->fColsIn-1)/8+1;
1022 byte_w_out=(item->fColsOut-1)/8+1;
1028 dj=0.5-(float)item->fRowsOut/2;
1031 if(angle==0 || angle==M_PI/2 ||
1032 angle==M_PI || angle==3*M_PI/2) {
1034 xr=(float)item->fColsOut;
1037 else if(angle<M_PI) {
1038 xl=(float)item->fColsOut/2+
1039 (dj-(
float)item->fRowsIn/(2*cos_angle))/
1040 TMath::Tan(angle)-2;
1041 xr=(float)item->fColsOut/2+
1042 (dj+(
float)item->fRowsIn/(2*cos_angle))/
1043 TMath::Tan(angle)+2;
1044 xinc=1./TMath::Tan(angle);
1047 xl=(float)item->fColsOut/2+
1048 (dj+(
float)item->fRowsIn/(2*cos_angle))/
1049 TMath::Tan(angle)-2;
1050 xr=(float)item->fColsOut/2+
1051 (dj-(
float)item->fRowsIn/(2*cos_angle))/
1052 TMath::Tan(angle)+2;
1054 xinc=1./TMath::Tan(angle);
1059 for(j=0; j<item->fRowsOut; j++) {
1062 di=(float)((xl<0)?0:(int)xl)+0.5-(float)item->fColsOut/2;
1063 byte_out=(item->fRowsOut-j-1)*byte_w_out;
1066 for(i=((xl<0)?0:(int)xl);
1067 i<((xr>=item->fColsOut)?item->fColsOut:(
int)xr); i++) {
1070 it=int((
float)item->fColsIn/2 + ( di*cos_angle + dj*sin_angle));
1071 jt=int((
float)item->fRowsIn/2 - (-di*sin_angle + dj*cos_angle));
1074 if(it>=0 && it<item->fColsIn && jt>=0 && jt<item->fRowsIn)
1075 if((imageIn->data[jt*byte_w_in+it/8] & 128>>(it%8))>0)
1076 item->fXimage->data[byte_out+i/8]|=128>>i%8;
1084 XDestroyImage(imageIn);
1087 if(gRotStyle.fMagnify!=1.) {
1088 item->fColsIn=old_cols_in;
1089 item->fRowsIn=old_rows_in;
1093 #ifdef CACHE_BITMAPS
1096 item->fBitmap=XCreatePixmap(dpy, DefaultRootWindow(dpy),
1097 item->fColsOut, item->fRowsOut, 1);
1100 XPutImage(dpy, item->fBitmap, font_gc, item->fXimage, 0, 0, 0, 0,
1101 item->fColsOut, item->fRowsOut);
1103 XDestroyImage(item->fXimage);
1107 XFreeGC(dpy, font_gc);
1108 XFreePixmap(dpy, canvas);
1118 static void XRotAddToLinkedList(Display *dpy, RotatedTextItem_t *item)
1120 static long int current_size=0;
1121 static RotatedTextItem_t *last=0;
1122 RotatedTextItem_t *i1=gFirstTextItem, *i2;
1124 #ifdef CACHE_BITMAPS
1129 item->fSize=((item->fColsOut-1)/8+1)*item->fRowsOut;
1135 item->fSize=((item->fColsOut-1)/8+1)*item->fRowsOut +
1136 sizeof(XImage) + strlen(item->text) +
1137 item->fNl*8*
sizeof(float) +
sizeof(RotatedTextItem_t);
1139 if(item->font_name!=0)
1140 item->fSize+=strlen(item->font_name);
1142 item->fSize+=
sizeof(Font);
1155 DEBUG_PRINT2(
"Cache has %d items.\n", i);
1160 DEBUG_PRINT4(
"current cache size=%ld, new item=%ld, limit=%d\n",
1161 current_size, item->fSize, CACHE_SIZE_LIMIT*1024);
1164 if(item->fSize>CACHE_SIZE_LIMIT*1024) {
1165 DEBUG_PRINT1(
"Too big to cache\n\n");
1171 while(i1 && current_size+item->fSize>CACHE_SIZE_LIMIT*1024) {
1173 DEBUG_PRINT2(
"Removed %ld bytes\n", i1->fSize);
1175 if(i1->font_name!=0)
1176 DEBUG_PRINT5(
" (`%s'\n %s\n angle=%f align=%d)\n",
1177 i1->fText, i1->font_name, i1->fAngle, i1->fAlign);
1180 if(i1->font_name==0)
1181 DEBUG_PRINT5(
" (`%s'\n FID=%ld\n angle=%f align=%d)\n",
1182 i1->fText, i1->fid, i1->angle, i1->align);
1185 current_size-=i1->fSize;
1190 XRotFreeTextItem(dpy, i1);
1198 if(gFirstTextItem==0) {
1200 gFirstTextItem=item;
1210 current_size+=item->fSize;
1214 DEBUG_PRINT1(
"Added item to cache.\n");
1221 static void XRotFreeTextItem(Display *dpy, RotatedTextItem_t *item)
1225 if(item->font_name!=0)
1226 free(item->font_name);
1228 free((
char *)item->fCornersX);
1229 free((
char *)item->fCornersY);
1231 #ifdef CACHE_BITMAPS
1232 XFreePixmap(dpy, item->fBitmap);
1234 XDestroyImage(item->fXimage);
1244 static XImage *XRotMagnifyImage(Display *dpy, XImage *ximage)
1250 int cols_in, rows_in;
1251 int cols_out, rows_out;
1253 float z1, z2, z3, z4;
1254 int byte_width_in, byte_width_out;
1258 cols_in=ximage->width;
1259 rows_in=ximage->height;
1262 cols_out=int((
float)cols_in*gRotStyle.fMagnify);
1263 rows_out=int((
float)rows_in*gRotStyle.fMagnify);
1266 imageOut=MakeXImage(dpy, cols_out, rows_out);
1271 byte_width_in=(cols_in-1)/8+1;
1272 byte_width_out=(cols_out-1)/8+1;
1275 mag_inv=1./gRotStyle.fMagnify;
1280 for(j2=0; j2<rows_out; j2++) {
1284 for(i2=0; i2<cols_out; i2++) {
1289 if(i==cols_in-1 && j!=rows_in-1) {
1293 z1=(ximage->data[j*byte_width_in+i/8] & 128>>(i%8))>0;
1295 z3=(ximage->data[(j+1)*byte_width_in+i/8] & 128>>(i%8))>0;
1299 else if(i!=cols_in-1 && j==rows_in-1) {
1303 z1=(ximage->data[j*byte_width_in+i/8] & 128>>(i%8))>0;
1304 z2=(ximage->data[j*byte_width_in+(i+1)/8] & 128>>((i+1)%8))>0;
1309 else if(i==cols_in-1 && j==rows_in-1) {
1313 z1=(ximage->data[j*byte_width_in+i/8] & 128>>(i%8))>0;
1323 z1=(ximage->data[j*byte_width_in+i/8] & 128>>(i%8))>0;
1324 z2=(ximage->data[j*byte_width_in+(i+1)/8] & 128>>((i+1)%8))>0;
1325 z3=(ximage->data[(j+1)*byte_width_in+(i+1)/8] &
1327 z4=(ximage->data[(j+1)*byte_width_in+i/8] & 128>>(i%8))>0;
1331 if(((1-t)*(1-u)*z1 + t*(1-u)*z2 + t*u*z3 + (1-t)*u*z4)>0.5)
1332 imageOut->data[j2*byte_width_out+i2/8]|=128>>i2%8;
1340 XDestroyImage(ximage);
1350 XPoint *XRotTextExtents(Display *, XFontStruct *font,
float angle,
int x,
int y,
char *text,
int align)
1353 char *str1, *str2, *str3;
1354 const char *str2_a=
"\0", *str2_b=
"\n\0";
1356 float sin_angle, cos_angle;
1358 int cols_in, rows_in;
1360 XPoint *xp_in, *xp_out;
1362 XCharStruct overall;
1365 while(angle<0) angle+=360;
1367 while(angle>360) angle-=360;
1374 for(i=0; i<(int)strlen(text)-1; i++)
1380 str2=(
char *)str2_a;
1382 str2=(
char *)str2_b;
1385 str1=my_strdup(text);
1386 if(str1==0)
return 0;
1388 str3=my_strtok(str1, str2);
1391 XTextExtents(font, str1, strlen(str1), &dir, &asc, &desc,
1394 XTextExtents(font, str3, strlen(str3), &dir, &asc, &desc,
1398 max_width=overall.rbearing;
1402 str3=my_strtok((
char *)0, str2);
1405 XTextExtents(font, str3, strlen(str3), &dir, &asc, &desc,
1408 if(overall.rbearing>max_width)
1409 max_width=overall.rbearing;
1417 height=font->ascent+font->descent;
1424 sin_angle=TMath::Sin(angle);
1425 cos_angle=TMath::Cos(angle);
1428 if(align==TLEFT || align==TCENTRE || align==TRIGHT)
1429 hot_y=(float)rows_in/2*gRotStyle.fMagnify;
1430 else if(align==MLEFT || align==MCENTRE || align==MRIGHT)
1432 else if(align==BLEFT || align==BCENTRE || align==BRIGHT)
1433 hot_y=-(float)rows_in/2*gRotStyle.fMagnify;
1435 hot_y=-((
float)rows_in/2-(float)font->descent)*gRotStyle.fMagnify;
1438 if(align==TLEFT || align==MLEFT || align==BLEFT || align==NONE)
1439 hot_x=-(float)max_width/2*gRotStyle.fMagnify;
1440 else if(align==TCENTRE || align==MCENTRE || align==BCENTRE)
1443 hot_x=(float)max_width/2*gRotStyle.fMagnify;
1446 xp_in=(XPoint *)malloc((
unsigned)(5*
sizeof(XPoint)));
1447 if(!xp_in)
return 0;
1449 xp_out=(XPoint *)malloc((
unsigned)(5*
sizeof(XPoint)));
1456 xp_in[0].x=(
short int)(-(
float)cols_in*gRotStyle.fMagnify/2-gRotStyle.fBbxPadl);
1457 xp_in[0].y=(
short int)( (
float)rows_in*gRotStyle.fMagnify/2+gRotStyle.fBbxPadl);
1458 xp_in[1].x=(
short int)( (
float)cols_in*gRotStyle.fMagnify/2+gRotStyle.fBbxPadl);
1459 xp_in[1].y=(
short int)( (
float)rows_in*gRotStyle.fMagnify/2+gRotStyle.fBbxPadl);
1460 xp_in[2].x=(
short int)( (
float)cols_in*gRotStyle.fMagnify/2+gRotStyle.fBbxPadl);
1461 xp_in[2].y=(
short int)(-(
float)rows_in*gRotStyle.fMagnify/2-gRotStyle.fBbxPadl);
1462 xp_in[3].x=(
short int)(-(
float)cols_in*gRotStyle.fMagnify/2-gRotStyle.fBbxPadl);
1463 xp_in[3].y=(
short int)(-(
float)rows_in*gRotStyle.fMagnify/2-gRotStyle.fBbxPadl);
1464 xp_in[4].x=xp_in[0].x;
1465 xp_in[4].y=xp_in[0].y;
1468 for(i=0; i<5; i++) {
1469 xp_out[i].x=(
short int)((
float)x + ( ((float)xp_in[i].x-hot_x)*cos_angle +
1470 ((float)xp_in[i].y+hot_y)*sin_angle));
1471 xp_out[i].y=(
short int)((
float)y + (-((float)xp_in[i].x-hot_x)*sin_angle +
1472 ((float)xp_in[i].y+hot_y)*cos_angle));
1475 free((
char *)xp_in);