📄 rotated.c
字号:
/* 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, NULL, 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("**\nHorizontal text.\n"); /* this gc has similar properties to the user's gc (including stipple) */ my_gc=XCreateGC(dpy, drawable, NULL, 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("**\nFound target in cache.\n"); if(!item) DEBUG_PRINT1("**\nNo 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, NULL, 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, NULL, 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -