home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-10-21 | 28.4 KB | 1,001 lines |
- ! else
- ! for(i=0; i<len; i++) {
- ! ichar=str[i]-32;
- !
- ! /* make sure it's a printing character ... */
- ! if((ichar>=0)&&(ichar<95))
- ! width+=rotfont->per_char[ichar].width;
- ! }
-
- ! return width;
- }
-
- - /* *** Return the height of a string *** */
-
- ! int XRotTextHeight(rotfont, str, len)
- ! XRotFontStruct *rotfont;
- ! char *str;
- ! int len;
- {
- ! int i, height=0, ichar;
- ! int maxasc=0;
- ! int maxdsc=0;
- ! int dum;
- ! XCharStruct ch;
-
- ! if(str==NULL) return 0;
-
- ! if(rotfont->dir==0) {
- ! XTextExtents(rotfont->xfontstruct, str, len, &dum,&dum,&dum,&ch);
- ! height = ch.ascent + ch.descent;
- ! }
- ! else
- ! for(i=0; i<len; i++)
- ! {
- ! ichar=str[i]-32;
- !
- ! /* make sure it's a printing character ... */
- ! /* then find the highest and most descending */
- ! if((ichar>=0)&&(ichar<95)) {
- ! maxasc=max2(maxasc,rotfont->per_char[ichar].ascent);
- ! maxdsc=max2(maxdsc,rotfont->per_char[ichar].descent);
- ! }
- ! /* and add the two together */
- ! height = maxasc+maxdsc;
- ! }
-
- ! return height;
- ! }
-
-
- ! /* ---------------------------------------------------------------------- */
-
-
- ! /* *** A front end to XRotPaintString : mimics XDrawString *** */
-
- ! void XRotDrawString(dpy, drawable, rotfont,gc, x, y, str, len)
- ! Display *dpy;
- ! Drawable drawable;
- ! XRotFontStruct *rotfont;
- ! GC gc;
- ! int x, y;
- ! char *str;
- ! int len;
- ! {
- ! XRotPaintString(dpy, drawable, rotfont, gc, x, y, str, len, 0);
- }
-
-
- /* ---------------------------------------------------------------------- */
- -
-
- - /* *** A front end to XRotPaintString : mimics XDrawImageString *** */
-
- ! void XRotDrawImageString(dpy, drawable, rotfont, gc, x, y, str, len)
- ! Display *dpy;
- ! Drawable drawable;
- ! XRotFontStruct *rotfont;
- ! GC gc;
- ! int x, y;
- ! char *str;
- ! int len;
- {
- ! XRotPaintString(dpy, drawable, rotfont, gc, x, y, str, len, 1);
- }
-
-
- /* ---------------------------------------------------------------------- */
- -
- -
- - /* *** Paint a simple string with a rotated font *** */
-
- - /* *** The user should use one of the two front ends above *** */
-
- ! void XRotPaintString(dpy, drawable, rotfont, gc, x, y, str, len, paintbg)
- ! Display *dpy;
- ! Drawable drawable;
- ! XRotFontStruct *rotfont;
- ! GC gc;
- ! int x, y;
- ! char *str;
- ! int len;
- ! int paintbg;
- ! {
- ! static GC my_gc=NULL;
- ! XGCValues values;
- ! int i, xp, yp, dir, ichar, width;
- ! #ifdef X11R3
- ! static Pixmap empty_stipple=(Pixmap)NULL;
- ! #endif
-
- ! dir=rotfont->dir;
-
- ! if(!my_gc) my_gc=XCreateGC(dpy, drawable, NULL, 0);
-
- ! XCopyGC(dpy, gc, GCFunction|GCForeground|GCBackground, my_gc);
-
- ! /* a horizontal string is easy ... */
- ! if(dir==0)
- ! { XSetFillStyle(dpy, my_gc, FillSolid);
- ! XSetFont(dpy, my_gc, rotfont->xfontstruct->fid);
- ! if(!paintbg) XDrawString(dpy, drawable, my_gc, x, y, str, len);
- ! else XDrawImageString(dpy, drawable, my_gc, x, y, str, len);
-
- ! return;
- ! }
-
- ! /* vertical or upside down ... */
-
- ! /* to draw an `image string' we need to fill the background ... */
- ! if(paintbg)
- ! {
- ! #ifdef X11R3
- ! /* Release 3 doesn't have XGetGCValues(), so this is a
- ! slightly slower fudge ... */
- ! {
- ! GC stipple_gc;
- ! int bestw, besth;
-
- ! if(!empty_stipple)
- ! { XQueryBestStipple(dpy, drawable, 1, 1, &bestw, &besth);
- ! empty_stipple=XCreatePixmap(dpy, drawable, bestw, besth, 1);
-
- ! stipple_gc=XCreateGC(dpy, empty_stipple, NULL, 0);
- ! XSetForeground(dpy, stipple_gc, 0);
-
- ! XFillRectangle(dpy, empty_stipple, stipple_gc, 0, 0, bestw+1, besth+1);
- ! XFreeGC(dpy, stipple_gc);
- ! }
-
- ! XSetStipple(dpy, my_gc, empty_stipple);
- ! XSetFillStyle(dpy, my_gc, FillOpaqueStippled);
- ! }
- ! #else
- ! /* get the foreground and background colors
- ! ( note that this is not a round trip -> little speed penalty ) */
- ! XGetGCValues(dpy, my_gc, GCForeground|GCBackground, &values);
-
- ! XSetForeground(dpy, my_gc, values.background);
- ! XSetFillStyle(dpy, my_gc, FillSolid);
- ! #endif
-
- ! width=XRotTextWidth(rotfont, str, strlen(str));
-
- ! if(dir==1)
- ! XFillRectangle(dpy, drawable, my_gc, x-rotfont->max_ascent+1, y-width,
- ! rotfont->height-1, width);
- ! else if(dir==2)
- ! XFillRectangle(dpy, drawable, my_gc, x-width, y-rotfont->max_descent+1,
- ! width, rotfont->height-1);
- ! else
- ! XFillRectangle(dpy, drawable, my_gc, x-rotfont->max_descent+1,
- ! y, rotfont->height-1, width);
-
- ! #ifndef X11R3
- ! XSetForeground(dpy, my_gc, values.foreground);
- ! #endif
- ! }
-
- ! XSetFillStyle(dpy, my_gc, FillStippled);
-
- ! /* loop through each character in string ... */
- ! for(i=0; i<len; i++)
- ! {
- ! ichar=str[i]-32;
-
- ! /* make sure it's a printing character ... */
- ! if((ichar>=0)&&(ichar<95))
- ! {
- ! /* suitable offset ... */
- ! if(dir==1)
- ! { xp=x-rotfont->per_char[ichar].ascent;
- ! yp=y-rotfont->per_char[ichar].rbearing; }
- ! else if(dir==2)
- ! { xp=x-rotfont->per_char[ichar].rbearing;
- ! yp=y-rotfont->per_char[ichar].descent+1; }
- ! else
- ! { xp=x-rotfont->per_char[ichar].descent+1;
- ! yp=y+rotfont->per_char[ichar].lbearing; }
- !
- ! /* draw the glyph ... */
- ! XSetStipple(dpy, my_gc, rotfont->per_char[ichar].glyph.bm);
-
- ! XSetTSOrigin(dpy, my_gc, xp, yp);
- !
- ! XFillRectangle(dpy, drawable, my_gc, xp, yp,
- ! rotfont->per_char[ichar].glyph.bit_w,
- ! rotfont->per_char[ichar].glyph.bit_h);
- !
- ! /* advance position ... */
- ! if(dir==1) y-=rotfont->per_char[ichar].width;
- ! else if(dir==2) x-=rotfont->per_char[ichar].width;
- ! else y+=rotfont->per_char[ichar].width;
- ! }
- ! }
- }
- !
- !
- /* ---------------------------------------------------------------------- */
-
-
- ! /* *** A front end to XRotPaintAlignedString : uses XRotDrawString *** */
-
- ! void XRotDrawAlignedString(dpy, drawable, rotfont, gc, x, y,
- ! text, align)
- ! Display *dpy;
- ! Drawable drawable;
- ! XRotFontStruct *rotfont;
- ! GC gc;
- ! int x, y;
- ! char *text;
- ! int align;
- {
- ! XRotPaintAlignedString(dpy, drawable, rotfont, gc, x, y, text, align, 0);
- }
-
-
- --- 383,1310 ----
- /* ---------------------------------------------------------------------- */
-
-
- ! /**************************************************************************/
- ! /* 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 || *text=='\0')
- ! return 0;
- !
- ! /* manipulate angle to 0<=angle<2*PI radians */
- ! while(angle<0.0)
- ! angle+=M_2PI;
- !
- ! while(angle>=M_2PI)
- ! angle-=M_2PI;
- !
- ! /* 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 NULL;
- !
- ! /* this gc has similar properties to the user's gc */
- ! my_gc=XCreateGC(dpy, drawable, (unsigned long) 0, 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, (unsigned long) 0, 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);
- !
- ! /* by default we draw the rotated bitmap, solid */
- ! bitmap_to_paint=item->bitmap;
-
- ! /* handle user stippling */
- ! #ifndef X11R3
- ! {
- ! GC depth_one_gc;
- ! XGCValues values;
- ! Pixmap new_bitmap, inverse;
- !
- ! /* try and get some GC properties */
- ! if(XGetGCValues(dpy, gc,
- ! GCStipple|GCFillStyle|GCForeground|GCBackground|
- ! GCTileStipXOrigin|GCTileStipYOrigin,
- ! &values)) {
- !
- ! /* only do this if stippling requested */
- ! if((values.fill_style==FillStippled ||
- ! values.fill_style==FillOpaqueStippled) && !bg) {
- !
- ! /* opaque stipple: draw rotated text in background colour */
- ! if(values.fill_style==FillOpaqueStippled) {
- ! XSetForeground(dpy, my_gc, values.background);
- ! XSetFillStyle(dpy, my_gc, FillStippled);
- ! XSetStipple(dpy, my_gc, item->bitmap);
- ! XSetTSOrigin(dpy, my_gc, xp, yp);
- ! XFillRectangle(dpy, drawable, my_gc, xp, yp,
- ! item->cols_out, item->rows_out);
- ! XSetForeground(dpy, my_gc, values.foreground);
- ! }
- !
- ! /* this will merge the rotated text and the user's stipple */
- ! new_bitmap=XCreatePixmap(dpy, drawable,
- ! item->cols_out, item->rows_out, 1);
- !
- ! /* create a GC */
- ! depth_one_gc=XCreateGC(dpy, new_bitmap, (unsigned long) 0, 0);
- ! XSetForeground(dpy, depth_one_gc, 1);
- ! XSetBackground(dpy, depth_one_gc, 0);
- !
- ! /* set the relative stipple origin */
- ! XSetTSOrigin(dpy, depth_one_gc,
- ! values.ts_x_origin-xp, values.ts_y_origin-yp);
- !
- ! /* fill the whole bitmap with the user's stipple */
- ! XSetStipple(dpy, depth_one_gc, values.stipple);
- ! XSetFillStyle(dpy, depth_one_gc, FillOpaqueStippled);
- ! XFillRectangle(dpy, new_bitmap, depth_one_gc,
- ! 0, 0, item->cols_out, item->rows_out);
- !
- ! /* set stipple origin back to normal */
- ! XSetTSOrigin(dpy, depth_one_gc, 0, 0);
- !
- ! /* this will contain an inverse copy of the rotated text */
- ! inverse=XCreatePixmap(dpy, drawable,
- ! item->cols_out, item->rows_out, 1);
- !
- ! /* invert text */
- ! XSetFillStyle(dpy, depth_one_gc, FillSolid);
- ! XSetFunction(dpy, depth_one_gc, GXcopyInverted);
- ! XCopyArea(dpy, item->bitmap, inverse, depth_one_gc,
- ! 0, 0, item->cols_out, item->rows_out, 0, 0);
- !
- ! /* now delete user's stipple everywhere EXCEPT on text */
- ! XSetForeground(dpy, depth_one_gc, 0);
- ! XSetBackground(dpy, depth_one_gc, 1);
- ! XSetStipple(dpy, depth_one_gc, inverse);
- ! XSetFillStyle(dpy, depth_one_gc, FillStippled);
- ! XSetFunction(dpy, depth_one_gc, GXcopy);
- ! XFillRectangle(dpy, new_bitmap, depth_one_gc,
- ! 0, 0, item->cols_out, item->rows_out);
- !
- ! /* free resources */
- ! XFreePixmap(dpy, inverse);
- ! XFreeGC(dpy, depth_one_gc);
- !
- ! /* this is the new bitmap */
- ! bitmap_to_paint=new_bitmap;
- ! }
- ! }
- ! }
- ! #endif /*X11R3*/
- !
- ! /* paint text using stipple technique */
- ! XSetFillStyle(dpy, my_gc, FillStippled);
- ! XSetStipple(dpy, my_gc, bitmap_to_paint);
- ! XSetTSOrigin(dpy, my_gc, xp, yp);
- ! XFillRectangle(dpy, drawable, my_gc, xp, yp,
- ! item->cols_out, item->rows_out);
- !
- ! /* free our resources */
- ! XFreeGC(dpy, my_gc);
- !
- ! /* stippled bitmap no longer needed */
- ! if(bitmap_to_paint!=item->bitmap)
- ! XFreePixmap(dpy, bitmap_to_paint);
- !
- ! #ifdef CACHE_XIMAGES
- ! XFreePixmap(dpy, item->bitmap);
- ! #endif /*CACHE_XIMAGES*/
- !
- ! /* if item isn't cached, destroy it completely */
- ! if(!item->cached)
- ! XRotFreeTextItem(dpy,item);
- !
- ! /* we got to the end OK! */
- ! return 0;
- }
-
-
- /* ---------------------------------------------------------------------- */
-
-
- ! /**************************************************************************/
- ! /* Draw a horizontal string in a quick fashion */
- ! /**************************************************************************/
- !
- ! static int XRotDrawHorizontalString(dpy, font, drawable, gc, x, y, text,
- ! align, bg)
- ! Display *dpy;
- ! XFontStruct *font;
- ! Drawable drawable;
- ! GC gc;
- ! int x, y;
- ! char *text;
- ! int align;
- ! int bg;
- {
- ! GC my_gc;
- ! int nl=1, i;
- ! int height;
- ! int xp, yp;
- ! char *str1, *str2, *str3;
- ! char *str2_a="\0", *str2_b="\n\0";
- ! int dir, asc, desc;
- ! XCharStruct overall;
-
- ! DEBUG_PRINT1("**Horizontal text.\n");
- !
- ! if (text == NULL || *text=='\0') {
- ! DEBUG_PRINT1("Empty string, ignoring\n");
- return 0;
- + }
-
- ! /* this gc has similar properties to the user's gc (including stipple) */
- ! my_gc=XCreateGC(dpy, drawable, (unsigned long) 0, 0);
- ! XCopyGC(dpy, gc,
- ! GCForeground|GCBackground|GCFunction|GCStipple|GCFillStyle|
- ! GCTileStipXOrigin|GCTileStipYOrigin|GCPlaneMask, my_gc);
- ! XSetFont(dpy, my_gc, font->fid);
- !
- ! /* count number of sections in string */
- ! if(align!=NONE)
- ! for(i=0; i<strlen(text)-1; i++)
- ! if(text[i]=='\n')
- ! nl++;
- !
- ! /* ignore newline characters if not doing alignment */
- ! if(align==NONE)
- ! str2=str2_a;
- ! else
- ! str2=str2_b;
- !
- ! /* overall font height */
- ! height=font->ascent+font->descent;
- !
- ! /* y position */
- ! if(align==TLEFT || align==TCENTRE || align==TRIGHT)
- ! yp=y+font->ascent;
- ! else if(align==MLEFT || align==MCENTRE || align==MRIGHT)
- ! yp=y-nl*height/2+font->ascent;
- ! else if(align==BLEFT || align==BCENTRE || align==BRIGHT)
- ! yp=y-nl*height+font->ascent;
- ! else
- ! yp=y;
- !
- ! str1=my_strdup(text);
- ! if(str1==NULL)
- ! return 1;
- !
- ! str3=my_strtok(str1, str2);
- !
- ! /* loop through each section in the string */
- ! do {
- ! XTextExtents(font, str3, strlen(str3), &dir, &asc, &desc,
- ! &overall);
-
- ! /* where to draw section in x ? */
- ! if(align==TLEFT || align==MLEFT || align==BLEFT || align==NONE)
- ! xp=x;
- ! else if(align==TCENTRE || align==MCENTRE || align==BCENTRE)
- ! xp=x-overall.rbearing/2;
- ! else
- ! xp=x-overall.rbearing;
- !
- ! /* draw string onto bitmap */
- ! if(!bg)
- ! XDrawString(dpy, drawable, my_gc, xp, yp, str3, strlen(str3));
- ! else
- ! XDrawImageString(dpy, drawable, my_gc, xp, yp, str3, strlen(str3));
- !
- ! /* move to next line */
- ! yp+=height;
- !
- ! str3=my_strtok((char *)NULL, str2);
- ! }
- ! while(str3!=NULL);
- !
- ! free(str1);
- ! XFreeGC(dpy, my_gc);
-
- ! return 0;
- }
-
-
- ! /* ---------------------------------------------------------------------- */
- !
- !
- ! /**************************************************************************/
- ! /* Query cache for a match with this font/text/angle/alignment */
- ! /* request, otherwise arrange for its creation */
- ! /**************************************************************************/
- !
- ! static RotatedTextItem *XRotRetrieveFromCache(dpy, font, angle, text, align)
- ! Display *dpy;
- ! XFontStruct *font;
- ! float angle;
- ! char *text;
- ! int align;
- {
- ! Font fid;
- ! char *font_name=NULL;
- ! unsigned long name_value;
- ! RotatedTextItem *item=NULL;
- ! RotatedTextItem *i1=first_text_item;
- !
- ! /* get font name, if it exists */
- ! if(XGetFontProperty(font, XA_FONT, &name_value)) {
- ! DEBUG_PRINT1("got font name OK\n");
- ! font_name=XGetAtomName(dpy, name_value);
- ! fid=0;
- ! }
- ! #ifdef CACHE_FID
- ! /* otherwise rely (unreliably?) on font ID */
- ! else {
- ! DEBUG_PRINT1("can't get fontname, caching FID\n");
- ! font_name=NULL;
- ! fid=font->fid;
- ! }
- ! #else
- ! /* not allowed to cache font ID's */
- ! else {
- ! DEBUG_PRINT1("can't get fontname, can't cache\n");
- ! font_name=NULL;
- ! fid=0;
- ! }
- ! #endif /*CACHE_FID*/
- !
- ! /* look for a match in cache */
-
- ! /* matching formula:
- ! identical text;
- ! identical fontname (if defined, font ID's if not);
- ! angles close enough (<0.00001 here, could be smaller);
- ! HORIZONTAL alignment matches, OR it's a one line string;
- ! magnifications the same */
-
- ! while(i1 && !item) {
- ! /* match everything EXCEPT fontname/ID */
- ! if(strcmp(text, i1->text)==0 &&
- ! fabs(angle-i1->angle)<0.00001 &&
- ! style.magnify==i1->magnify &&
- ! (i1->nl==1 ||
- ! ((align==0)?9:(align-1))%3==
- ! ((i1->align==0)?9:(i1->align-1))%3)) {
-
- ! /* now match fontname/ID */
- ! if(font_name!=NULL && i1->font_name!=NULL) {
- ! if(strcmp(font_name, i1->font_name)==0) {
- ! item=i1;
- ! DEBUG_PRINT1("Matched against font names\n");
- ! }
- ! else
- ! i1=i1->next;
- ! }
- ! #ifdef CACHE_FID
- ! else if(font_name==NULL && i1->font_name==NULL) {
- ! if(fid==i1->fid) {
- ! item=i1;
- ! DEBUG_PRINT1("Matched against FID's\n");
- ! }
- ! else
- ! i1=i1->next;
- ! }
- ! #endif /*CACHE_FID*/
- ! else
- ! i1=i1->next;
- ! }
- ! else
- ! i1=i1->next;
- ! }
- !
- ! if(item)
- ! DEBUG_PRINT1("**Found target in cache.\n");
- ! if(!item)
- ! DEBUG_PRINT1("**No match in cache.\n");
-
- + /* no match */
- + if(!item) {
- + /* create new item */
- + item=XRotCreateTextItem(dpy, font, angle, text, align);
- + if(!item)
- + return NULL;
-
- ! /* record what it shows */
- ! item->text=my_strdup(text);
-
- + /* fontname or ID */
- + if(font_name!=NULL) {
- + item->font_name=my_strdup(font_name);
- + item->fid=0;
- + }
- + else {
- + item->font_name=NULL;
- + item->fid=fid;
- + }
-
- ! item->angle=angle;
- ! item->align=align;
- ! item->magnify=style.magnify;
-
- ! /* cache it */
- ! XRotAddToLinkedList(dpy, item);
- ! }
- !
- ! if(font_name)
- ! XFree(font_name);
- !
- ! /* if XImage is cached, need to recreate the bitmap */
- !
- ! #ifdef CACHE_XIMAGES
- ! {
- ! GC depth_one_gc;
- !
- ! /* create bitmap to hold rotated text */
- ! item->bitmap=XCreatePixmap(dpy, DefaultRootWindow(dpy),
- ! item->cols_out, item->rows_out, 1);
- !
- ! /* depth one gc */
- ! depth_one_gc=XCreateGC(dpy, item->bitmap, (unsigned long) 0, 0);
- ! XSetBackground(dpy, depth_one_gc, 0);
- ! XSetForeground(dpy, depth_one_gc, 1);
- !
- ! /* make the text bitmap from XImage */
- ! XPutImage(dpy, item->bitmap, depth_one_gc, item->ximage, 0, 0, 0, 0,
- ! item->cols_out, item->rows_out);
- !
- ! XFreeGC(dpy, depth_one_gc);
- ! }
- ! #endif /*CACHE_XIMAGES*/
- !
- ! return item;
- }
-
-
- /* ---------------------------------------------------------------------- */
-
-
- ! /**************************************************************************/
- ! /* Create a rotated text item */
- ! /**************************************************************************/
- !
- ! static RotatedTextItem *XRotCreateTextItem(dpy, font, angle, text, align)
- ! Display *dpy;
- ! XFontStruct *font;
- ! float angle;
- ! char *text;
- ! int align;
- {
- ! RotatedTextItem *item=NULL;
- ! Pixmap canvas;
- ! GC font_gc;
- ! XImage *I_in;
- ! register int i, j;
- ! char *str1, *str2, *str3;
- ! char *str2_a="\0", *str2_b="\n\0";
- ! int height;
- ! int byte_w_in, byte_w_out;
- ! int xp, yp;
- ! float sin_angle, cos_angle;
- ! int it, jt;
- ! float di, dj;
- ! int ic=0;
- ! float xl, xr, xinc;
- ! int byte_out;
- ! int dir, asc, desc;
- ! XCharStruct overall;
- ! int old_cols_in=0, old_rows_in=0;
- !
- ! /* allocate memory */
- ! item=(RotatedTextItem *)malloc((unsigned)sizeof(RotatedTextItem));
- ! if(!item)
- ! return NULL;
- !
- ! /* count number of sections in string */
- ! item->nl=1;
- ! if(align!=NONE)
- ! for(i=0; i<strlen(text)-1; i++)
- ! if(text[i]=='\n')
- ! item->nl++;
- !
- ! /* ignore newline characters if not doing alignment */
- ! if(align==NONE)
- ! str2=str2_a;
- ! else
- ! str2=str2_b;
- !
- ! /* find width of longest section */
- ! str1=my_strdup(text);
- ! if(str1==NULL)
- ! return NULL;
- !
- ! str3=my_strtok(str1, str2);
- !
- ! XTextExtents(font, str3, strlen(str3), &dir, &asc, &desc,
- ! &overall);
- !
- ! item->max_width=overall.rbearing;
- !
- ! /* loop through each section */
- ! do {
- ! str3=my_strtok((char *)NULL, str2);
- !
- ! if(str3!=NULL) {
- ! XTextExtents(font, str3, strlen(str3), &dir, &asc, &desc,
- ! &overall);
- !
- ! if(overall.rbearing>item->max_width)
- ! item->max_width=overall.rbearing;
- ! }
- ! }
- ! while(str3!=NULL);
- !
- ! free(str1);
- !
- ! /* overall font height */
- ! height=font->ascent+font->descent;
- !
- ! /* dimensions horizontal text will have */
- ! item->cols_in=item->max_width;
- ! item->rows_in=item->nl*height;
- !
- ! /* bitmap for drawing on */
- ! canvas=XCreatePixmap(dpy, DefaultRootWindow(dpy),
- ! item->cols_in, item->rows_in, 1);
- !
- ! /* create a GC for the bitmap */
- ! font_gc=XCreateGC(dpy, canvas, (unsigned long) 0, 0);
- ! XSetBackground(dpy, font_gc, 0);
- ! XSetFont(dpy, font_gc, font->fid);
- !
- ! /* make sure the bitmap is blank */
- ! XSetForeground(dpy, font_gc, 0);
- ! XFillRectangle(dpy, canvas, font_gc, 0, 0,
- ! item->cols_in+1, item->rows_in+1);
- ! XSetForeground(dpy, font_gc, 1);
- !
- ! /* pre-calculate sin and cos */
- ! sin_angle=sin(angle);
- ! cos_angle=cos(angle);
- !
- ! /* text background will be drawn using XFillPolygon */
- ! item->corners_x=
- ! (float *)malloc((unsigned)(4*item->nl*sizeof(float)));
- ! if(!item->corners_x)
- ! return NULL;
- !
- ! item->corners_y=
- ! (float *)malloc((unsigned)(4*item->nl*sizeof(float)));
- ! if(!item->corners_y)
- ! return NULL;
- !
- ! /* draw text horizontally */
- !
- ! /* start at top of bitmap */
- ! yp=font->ascent;
- !
- ! str1=my_strdup(text);
- ! if(str1==NULL)
- ! return NULL;
- !
- ! str3=my_strtok(str1, str2);
- !
- ! /* loop through each section in the string */
- ! do {
- ! XTextExtents(font, str3, strlen(str3), &dir, &asc, &desc,
- ! &overall);
- !
- ! /* where to draw section in x ? */
- ! if(align==TLEFT || align==MLEFT || align==BLEFT || align==NONE)
- ! xp=0;
- ! else if(align==TCENTRE || align==MCENTRE || align==BCENTRE)
- ! xp=(item->max_width-overall.rbearing)/2;
- ! else
- ! xp=item->max_width-overall.rbearing;
- !
- ! /* draw string onto bitmap */
- ! XDrawString(dpy, canvas, font_gc, xp, yp, str3, strlen(str3));
- !
- ! /* keep a note of corner positions of this string */
- ! item->corners_x[ic]=((float)xp-(float)item->cols_in/2)*style.magnify;
- ! item->corners_y[ic]=((float)(yp-font->ascent)-(float)item->rows_in/2)
- ! *style.magnify;
- ! item->corners_x[ic+1]=item->corners_x[ic];
- ! item->corners_y[ic+1]=item->corners_y[ic]+(float)height*style.magnify;
- ! item->corners_x[item->nl*4-1-ic]=item->corners_x[ic]+
- ! (float)overall.rbearing*style.magnify;
- ! item->corners_y[item->nl*4-1-ic]=item->corners_y[ic];
- ! item->corners_x[item->nl*4-2-ic]=
- ! item->corners_x[item->nl*4-1-ic];
- ! item->corners_y[item->nl*4-2-ic]=item->corners_y[ic+1];
- !
- ! ic+=2;
- !
- ! /* move to next line */
- ! yp+=height;
- !
- ! str3=my_strtok((char *)NULL, str2);
- ! }
- ! while(str3!=NULL);
- !
- ! free(str1);
- !
- ! /* create image to hold horizontal text */
- ! I_in=MakeXImage(dpy, item->cols_in, item->rows_in);
- ! if(I_in==NULL)
- ! return NULL;
- !
- ! /* extract horizontal text */
- ! XGetSubImage(dpy, canvas, 0, 0, item->cols_in, item->rows_in,
- ! 1, XYPixmap, I_in, 0, 0);
- ! I_in->format=XYBitmap;
- !
- ! /* magnify horizontal text */
- ! if(style.magnify!=1.) {
- ! I_in=XRotMagnifyImage(dpy, I_in);
- !
- ! old_cols_in=item->cols_in;
- ! old_rows_in=item->rows_in;
- ! item->cols_in=(float)item->cols_in*style.magnify;
- ! item->rows_in=(float)item->rows_in*style.magnify;
- ! }
- !
- ! /* how big will rotated text be ? */
- ! item->cols_out=fabs((float)item->rows_in*sin_angle) +
- ! fabs((float)item->cols_in*cos_angle) +0.99999 +2;
- !
- ! item->rows_out=fabs((float)item->rows_in*cos_angle) +
- ! fabs((float)item->cols_in*sin_angle) +0.99999 +2;
- !
- ! if(item->cols_out%2==0)
- ! item->cols_out++;
- !
- ! if(item->rows_out%2==0)
- ! item->rows_out++;
- !
- ! /* create image to hold rotated text */
- ! item->ximage=MakeXImage(dpy, item->cols_out, item->rows_out);
- ! if(item->ximage==NULL)
- ! return NULL;
- !
- ! byte_w_in=(item->cols_in-1)/8+1;
- ! byte_w_out=(item->cols_out-1)/8+1;
- !
- ! /* we try to make this bit as fast as possible - which is why it looks
- ! a bit over-the-top */
- !
- ! /* vertical distance from centre */
- ! dj=0.5-(float)item->rows_out/2;
- !
- ! /* where abouts does text actually lie in rotated image? */
- ! /* check angle within 0.5 degrees (0.008 radians) */
- ! if(fabs((double)angle)<0.008 || fabs((double)angle-M_PI/2)<0.008 ||
- ! fabs((double)angle-M_PI)<0.008 || fabs((double)angle-3*M_PI/2)<0.008) {
- ! xl=0;
- ! xr=(float)item->cols_out;
- ! xinc=0;
- ! }
- ! else if(angle<M_PI) {
- ! xl=(float)item->cols_out/2+
- ! (dj-(float)item->rows_in/(2*cos_angle))/
- ! tan(angle)-2;
- ! xr=(float)item->cols_out/2+
- ! (dj+(float)item->rows_in/(2*cos_angle))/
- ! tan(angle)+2;
- ! xinc=1./tan(angle);
- ! }
- ! else {
- ! xl=(float)item->cols_out/2+
- ! (dj+(float)item->rows_in/(2*cos_angle))/
- ! tan(angle)-2;
- ! xr=(float)item->cols_out/2+
- ! (dj-(float)item->rows_in/(2*cos_angle))/
- ! tan(angle)+2;
- !
- ! xinc=1./tan(angle);
- ! }
- !
- ! /* loop through all relevent bits in rotated image */
- ! for(j=0; j<item->rows_out; j++) {
- !
- ! /* no point re-calculating these every pass */
- ! di=(float)((xl<0)?0:(int)xl)+0.5-(float)item->cols_out/2;
- ! byte_out=(item->rows_out-j-1)*byte_w_out;
- !
- ! /* loop through meaningful columns */
- ! for(i=((xl<0)?0:(int)xl);
- ! i<((xr>=item->cols_out)?item->cols_out:(int)xr); i++) {
- !
- ! /* rotate coordinates */
- ! it=(float)item->cols_in/2 + ( di*cos_angle + dj*sin_angle);
- ! jt=(float)item->rows_in/2 - (-di*sin_angle + dj*cos_angle);
- !
- ! /* set pixel if required */
- ! if(it>=0 && it<item->cols_in && jt>=0 && jt<item->rows_in)
- ! if((I_in->data[jt*byte_w_in+it/8] & 128>>(it%8))>0)
- ! item->ximage->data[byte_out+i/8]|=128>>i%8;
- !
- ! di+=1;
- ! }
- ! dj+=1;
- ! xl+=xinc;
- ! xr+=xinc;
- ! }
- ! XDestroyImage(I_in);
- !
-