📄 rotated.c
字号:
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? */ if(angle==0 || angle==M_PI/2 || angle==M_PI || angle==3*M_PI/2) { 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); if(style.magnify!=1.) { item->cols_in=old_cols_in; item->rows_in=old_rows_in; }#ifdef CACHE_BITMAPS /* create a bitmap to hold rotated text */ item->bitmap=XCreatePixmap(dpy, DefaultRootWindow(dpy), item->cols_out, item->rows_out, 1); /* make the text bitmap from XImage */ XPutImage(dpy, item->bitmap, font_gc, item->ximage, 0, 0, 0, 0, item->cols_out, item->rows_out); XDestroyImage(item->ximage);#endif /*CACHE_BITMAPS*/ XFreeGC(dpy, font_gc); XFreePixmap(dpy, canvas); return item;}/* ---------------------------------------------------------------------- *//**************************************************************************//* Adds a text item to the end of the cache, removing as many items *//* from the front as required to keep cache size below limit *//**************************************************************************/static void XRotAddToLinkedList(dpy, item) Display *dpy; RotatedTextItem *item;{ static long int current_size=0; static RotatedTextItem *last=NULL; RotatedTextItem *i1=first_text_item, *i2=NULL;#ifdef CACHE_BITMAPS /* I don't know how much memory a pixmap takes in the server - probably this + a bit more we can't account for */ item->size=((item->cols_out-1)/8+1)*item->rows_out;#else /* this is pretty much the size of a RotatedTextItem */ item->size=((item->cols_out-1)/8+1)*item->rows_out + sizeof(XImage) + strlen(item->text) + item->nl*8*sizeof(float) + sizeof(RotatedTextItem); if(item->font_name!=NULL) item->size+=strlen(item->font_name); else item->size+=sizeof(Font);#endif /*CACHE_BITMAPS */#ifdef DEBUG /* count number of items in cache, for debugging */ { int i=0; while(i1) { i++; i1=i1->next; } DEBUG_PRINT2("Cache has %d items.\n", i); i1=first_text_item; }#endif DEBUG_PRINT4("current cache size=%ld, new item=%ld, limit=%ld\n", current_size, item->size, CACHE_SIZE_LIMIT*1024); /* if this item is bigger than whole cache, forget it */ if(item->size>CACHE_SIZE_LIMIT*1024) { DEBUG_PRINT1("Too big to cache\n\n"); item->cached=0; return; } /* remove elements from cache as needed */ while(i1 && current_size+item->size>CACHE_SIZE_LIMIT*1024) { DEBUG_PRINT2("Removed %d bytes\n", i1->size); if(i1->font_name!=NULL) DEBUG_PRINT5(" (`%s'\n %s\n angle=%f align=%d)\n", i1->text, i1->font_name, i1->angle, i1->align);#ifdef CACHE_FID if(i1->font_name==NULL) DEBUG_PRINT5(" (`%s'\n FID=%ld\n angle=%f align=%d)\n", i1->text, i1->fid, i1->angle, i1->align);#endif /*CACHE_FID*/ current_size-=i1->size; i2=i1->next; /* free resources used by the unlucky item */ XRotFreeTextItem(dpy, i1); /* remove it from linked list */ first_text_item=i2; i1=i2; } /* add new item to end of linked list */ if(first_text_item==NULL) { item->next=NULL; first_text_item=item; last=item; } else { item->next=NULL; last->next=item; last=item; } /* new cache size */ current_size+=item->size; item->cached=1; DEBUG_PRINT1("Added item to cache.\n");}/* ---------------------------------------------------------------------- *//**************************************************************************//* Free the resources used by a text item *//**************************************************************************/static void XRotFreeTextItem(dpy, item) Display *dpy; RotatedTextItem *item;{ free(item->text); if(item->font_name!=NULL) free(item->font_name); free((char *)item->corners_x); free((char *)item->corners_y);#ifdef CACHE_BITMAPS XFreePixmap(dpy, item->bitmap);#else XDestroyImage(item->ximage);#endif /* CACHE_BITMAPS */ free((char *)item);}/* ---------------------------------------------------------------------- *//**************************************************************************//* Magnify an XImage using bilinear interpolation *//**************************************************************************/static XImage *XRotMagnifyImage(dpy, ximage) Display *dpy; XImage *ximage;{ int i, j; float x, y; float u,t; XImage *I_out; int cols_in, rows_in; int cols_out, rows_out; register int i2, j2; float z1, z2, z3, z4; int byte_width_in, byte_width_out; float mag_inv; /* size of input image */ cols_in=ximage->width; rows_in=ximage->height; /* size of final image */ cols_out=(float)cols_in*style.magnify; rows_out=(float)rows_in*style.magnify; /* this will hold final image */ I_out=MakeXImage(dpy, cols_out, rows_out); if(I_out==NULL) return NULL; /* width in bytes of input, output images */ byte_width_in=(cols_in-1)/8+1; byte_width_out=(cols_out-1)/8+1; /* for speed */ mag_inv=1./style.magnify; y=0.; /* loop over magnified image */ for(j2=0; j2<rows_out; j2++) { x=0; j=y; for(i2=0; i2<cols_out; i2++) { i=x; /* bilinear interpolation - where are we on bitmap ? */ /* right edge */ if(i==cols_in-1 && j!=rows_in-1) { t=0; u=y-(float)j; z1=(ximage->data[j*byte_width_in+i/8] & 128>>(i%8))>0; z2=z1; z3=(ximage->data[(j+1)*byte_width_in+i/8] & 128>>(i%8))>0; z4=z3; } /* top edge */ else if(i!=cols_in-1 && j==rows_in-1) { t=x-(float)i; u=0; z1=(ximage->data[j*byte_width_in+i/8] & 128>>(i%8))>0; z2=(ximage->data[j*byte_width_in+(i+1)/8] & 128>>((i+1)%8))>0; z3=z2; z4=z1; } /* top right corner */ else if(i==cols_in-1 && j==rows_in-1) { u=0; t=0; z1=(ximage->data[j*byte_width_in+i/8] & 128>>(i%8))>0; z2=z1; z3=z1; z4=z1; } /* somewhere `safe' */ else { t=x-(float)i; u=y-(float)j; z1=(ximage->data[j*byte_width_in+i/8] & 128>>(i%8))>0; z2=(ximage->data[j*byte_width_in+(i+1)/8] & 128>>((i+1)%8))>0; z3=(ximage->data[(j+1)*byte_width_in+(i+1)/8] & 128>>((i+1)%8))>0; z4=(ximage->data[(j+1)*byte_width_in+i/8] & 128>>(i%8))>0; } /* if interpolated value is greater than 0.5, set bit */ if(((1-t)*(1-u)*z1 + t*(1-u)*z2 + t*u*z3 + (1-t)*u*z4)>0.5) I_out->data[j2*byte_width_out+i2/8]|=128>>i2%8; x+=mag_inv; } y+=mag_inv; } /* destroy original */ XDestroyImage(ximage); /* return big image */ return I_out;}/* ---------------------------------------------------------------------- *//**************************************************************************//* Calculate the bounding box some text will have when painted *//**************************************************************************/XPoint *XRotTextExtents(dpy, font, angle, x, y, text, align) Display *dpy; XFontStruct *font; float angle; int x, y; char *text; int align;{ register int i; char *str1, *str2, *str3; char *str2_a="\0", *str2_b="\n\0"; int height; float sin_angle, cos_angle; int nl, max_width; int cols_in, rows_in; float hot_x, hot_y; XPoint *xp_in, *xp_out; int dir, asc, desc; XCharStruct overall; /* manipulate angle to 0<=angle<360 degrees */ while(angle<0) angle+=360; while(angle>360) angle-=360; angle*=M_PI/180; /* count number of sections in string */ nl=1; 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; /* 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); 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>max_width) max_width=overall.rbearing; } } while(str3!=NULL); free(str1); /* overall font height */ height=font->ascent+font->descent; /* dimensions horizontal text will have */ cols_in=max_width; rows_in=nl*height; /* pre-calculate sin and cos */ sin_angle=sin(angle); cos_angle=cos(angle); /* y position */ if(align==TLEFT || align==TCENTRE || align==TRIGHT) hot_y=(float)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)rows_in/2*style.magnify; else hot_y=-((float)rows_in/2-(float)font->descent)*style.magnify; /* x position */ if(align==TLEFT || align==MLEFT || align==BLEFT || align==NONE) hot_x=-(float)max_width/2*style.magnify; else if(align==TCENTRE || align==MCENTRE || align==BCENTRE) hot_x=0; else hot_x=(float)max_width/2*style.magnify; /* reserve space for XPoints */ xp_in=(XPoint *)malloc((unsigned)(5*sizeof(XPoint))); if(!xp_in) return NULL; xp_out=(XPoint *)malloc((unsigned)(5*sizeof(XPoint))); if(!xp_out) return NULL; /* bounding box when horizontal, relative to bitmap centre */ xp_in[0].x=-(float)cols_in*style.magnify/2-style.bbx_pad; xp_in[0].y= (float)rows_in*style.magnify/2+style.bbx_pad; xp_in[1].x= (float)cols_in*style.magnify/2+style.bbx_pad; xp_in[1].y= (float)rows_in*style.magnify/2+style.bbx_pad; xp_in[2].x= (float)cols_in*style.magnify/2+style.bbx_pad; xp_in[2].y=-(float)rows_in*style.magnify/2-style.bbx_pad; xp_in[3].x=-(float)cols_in*style.magnify/2-style.bbx_pad; xp_in[3].y=-(float)rows_in*style.magnify/2-style.bbx_pad; xp_in[4].x=xp_in[0].x; xp_in[4].y=xp_in[0].y; /* rotate and translate bounding box */ for(i=0; i<5; i++) { xp_out[i].x=(float)x + ( ((float)xp_in[i].x-hot_x)*cos_angle + ((float)xp_in[i].y+hot_y)*sin_angle); xp_out[i].y=(float)y + (-((float)xp_in[i].x-hot_x)*sin_angle + ((float)xp_in[i].y+hot_y)*cos_angle); } free((char *)xp_in); return xp_out;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -