home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / x / volume21 / xfig / patch02k < prev    next >
Encoding:
Text File  |  1993-10-21  |  31.5 KB  |  1,062 lines

  1. Newsgroups: comp.sources.x
  2. From: envbvs@epb12.lbl.gov (Brian V. Smith)
  3. Subject: v21i031:  xfig - Draw amd manipulate objects in an X-Window, Patch02k/16
  4. Message-ID: <1993Oct21.185915.7334@sparky.sterling.com>
  5. X-Md4-Signature: e20d6b93894665de4533d15ebcf42754
  6. Sender: chris@sparky.sterling.com (Chris Olson)
  7. Organization: Sterling Software
  8. Date: Thu, 21 Oct 1993 18:59:15 GMT
  9. Approved: chris@sterling.com
  10.  
  11. Submitted-by: envbvs@epb12.lbl.gov (Brian V. Smith)
  12. Posting-number: Volume 21, Issue 31
  13. Archive-name: xfig/patch02k
  14. Environment: patch, X11, xfig
  15. Patch-To: xfig: Volume 19, Issue 113-139
  16.  
  17. #! /bin/sh
  18. # This is a shell archive.  Remove anything before this line, then feed it
  19. # into a shell via "sh file" or similar.  To overwrite existing files,
  20. # type "sh file -c".
  21. # Contents:  xfig.10
  22. # Wrapped by chris@sparky on Thu Oct 21 13:40:07 1993
  23. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  24. echo If this archive is complete, you will see the following message:
  25. echo '          "shar: End of archive 11 (of 16)."'
  26. if test -f 'xfig.10' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'xfig.10'\"
  28. else
  29.   echo shar: Extracting \"'xfig.10'\" \(29056 characters\)
  30.   sed "s/^X//" >'xfig.10' <<'END_OF_FILE'
  31. X!  else
  32. X!   for(i=0; i<len; i++) {
  33. X!    ichar=str[i]-32;
  34. X!   
  35. X!    /* make sure it's a printing character ... */
  36. X!    if((ichar>=0)&&(ichar<95)) 
  37. X!     width+=rotfont->per_char[ichar].width;
  38. X!   }
  39. X  
  40. X!  return width;
  41. X  }
  42. X  
  43. X- /* *** Return the height of a string *** */
  44. X  
  45. X! int XRotTextHeight(rotfont, str, len)
  46. X!  XRotFontStruct *rotfont;
  47. X!  char *str;
  48. X!  int len;
  49. X  {
  50. X!  int i, height=0, ichar;
  51. X!  int maxasc=0;
  52. X!  int maxdsc=0;
  53. X!  int dum;
  54. X!  XCharStruct ch;
  55. X  
  56. X!  if(str==NULL) return 0;
  57. X  
  58. X!  if(rotfont->dir==0) {
  59. X!     XTextExtents(rotfont->xfontstruct, str, len, &dum,&dum,&dum,&ch);
  60. X!     height = ch.ascent + ch.descent;
  61. X!  }
  62. X!  else
  63. X!   for(i=0; i<len; i++)
  64. X!   {
  65. X!    ichar=str[i]-32;
  66. X!   
  67. X!    /* make sure it's a printing character ... */
  68. X!    /* then find the highest and most descending */
  69. X!    if((ichar>=0)&&(ichar<95)) {
  70. X!     maxasc=max2(maxasc,rotfont->per_char[ichar].ascent);
  71. X!     maxdsc=max2(maxdsc,rotfont->per_char[ichar].descent);
  72. X!    }
  73. X!    /* and add the two together */
  74. X!    height = maxasc+maxdsc;
  75. X!   }
  76. X  
  77. X!  return height;
  78. X! }
  79. X  
  80. X  
  81. X! /* ---------------------------------------------------------------------- */
  82. X  
  83. X  
  84. X! /* *** A front end to XRotPaintString : mimics XDrawString *** */
  85. X  
  86. X! void XRotDrawString(dpy,  drawable, rotfont,gc, x, y, str, len)
  87. X!  Display *dpy;
  88. X!  Drawable drawable;
  89. X!  XRotFontStruct *rotfont;
  90. X!  GC gc;
  91. X!  int x, y;
  92. X!  char *str;
  93. X!  int len;
  94. X! {
  95. X!  XRotPaintString(dpy, drawable, rotfont, gc, x, y, str, len, 0);
  96. X  }
  97. X  
  98. X  
  99. X  /* ---------------------------------------------------------------------- */
  100. X-  
  101. X  
  102. X- /* *** A front end to XRotPaintString : mimics XDrawImageString *** */
  103. X  
  104. X! void XRotDrawImageString(dpy,  drawable, rotfont, gc, x, y, str, len)
  105. X!  Display *dpy;
  106. X!  Drawable drawable;
  107. X!  XRotFontStruct *rotfont;
  108. X!  GC gc;
  109. X!  int x, y;
  110. X!  char *str;
  111. X!  int len;
  112. X  {
  113. X!  XRotPaintString(dpy, drawable, rotfont, gc, x, y, str, len, 1);
  114. X  }
  115. X  
  116. X  
  117. X  /* ---------------------------------------------------------------------- */
  118. X-               
  119. X-               
  120. X- /* *** Paint a simple string with a rotated font *** */
  121. X  
  122. X- /* *** The user should use one of the two front ends above *** */
  123. X  
  124. X! void XRotPaintString(dpy,  drawable, rotfont, gc, x, y, str, len, paintbg)
  125. X!  Display *dpy;
  126. X!  Drawable drawable;
  127. X!  XRotFontStruct *rotfont;
  128. X!  GC gc;
  129. X!  int x, y;
  130. X!  char *str;
  131. X!  int len;
  132. X!  int paintbg;
  133. X! {            
  134. X!  static GC my_gc=NULL;
  135. X!  XGCValues values;
  136. X!  int i, xp, yp, dir, ichar, width;
  137. X! #ifdef X11R3
  138. X!  static Pixmap empty_stipple=(Pixmap)NULL;
  139. X! #endif
  140. X  
  141. X!  dir=rotfont->dir;
  142. X  
  143. X!  if(!my_gc) my_gc=XCreateGC(dpy, drawable, NULL, 0);
  144. X  
  145. X!  XCopyGC(dpy, gc, GCFunction|GCForeground|GCBackground, my_gc);
  146. X  
  147. X!  /* a horizontal string is easy ... */
  148. X!  if(dir==0)
  149. X!   { XSetFillStyle(dpy, my_gc, FillSolid);
  150. X!     XSetFont(dpy, my_gc, rotfont->xfontstruct->fid);
  151. X!     if(!paintbg) XDrawString(dpy, drawable, my_gc, x, y, str, len);
  152. X!     else         XDrawImageString(dpy, drawable, my_gc, x, y, str, len);
  153. X  
  154. X!     return;
  155. X!   }
  156. X  
  157. X!  /* vertical or upside down ... */
  158. X  
  159. X!  /* to draw an `image string' we need to fill the background ... */
  160. X!  if(paintbg)
  161. X!   {
  162. X! #ifdef X11R3
  163. X!    /* Release 3 doesn't have XGetGCValues(), so this is a
  164. X!       slightly slower fudge ... */
  165. X!    {
  166. X!     GC stipple_gc;
  167. X!     int bestw, besth;
  168. X  
  169. X!     if(!empty_stipple)    
  170. X!      { XQueryBestStipple(dpy, drawable, 1, 1, &bestw, &besth);
  171. X!        empty_stipple=XCreatePixmap(dpy, drawable, bestw, besth, 1);
  172. X  
  173. X!        stipple_gc=XCreateGC(dpy, empty_stipple, NULL, 0);
  174. X!        XSetForeground(dpy, stipple_gc, 0);
  175. X  
  176. X!        XFillRectangle(dpy, empty_stipple, stipple_gc, 0, 0, bestw+1, besth+1);
  177. X!        XFreeGC(dpy, stipple_gc);
  178. X!      }
  179. X  
  180. X!      XSetStipple(dpy, my_gc, empty_stipple);
  181. X!      XSetFillStyle(dpy, my_gc, FillOpaqueStippled);
  182. X!    }    
  183. X! #else
  184. X!    /* get the foreground and background colors
  185. X!         ( note that this is not a round trip -> little speed penalty ) */
  186. X!    XGetGCValues(dpy, my_gc, GCForeground|GCBackground, &values);
  187. X  
  188. X!    XSetForeground(dpy, my_gc, values.background);
  189. X!    XSetFillStyle(dpy, my_gc, FillSolid);
  190. X! #endif
  191. X  
  192. X!    width=XRotTextWidth(rotfont, str, strlen(str));
  193. X  
  194. X!    if(dir==1)
  195. X!      XFillRectangle(dpy, drawable, my_gc, x-rotfont->max_ascent+1, y-width,
  196. X!                     rotfont->height-1, width);
  197. X!    else if(dir==2)
  198. X!      XFillRectangle(dpy, drawable, my_gc, x-width, y-rotfont->max_descent+1,
  199. X!                     width, rotfont->height-1);
  200. X!    else
  201. X!      XFillRectangle(dpy, drawable, my_gc, x-rotfont->max_descent+1,
  202. X!                     y, rotfont->height-1, width);
  203. X  
  204. X! #ifndef X11R3
  205. X!    XSetForeground(dpy, my_gc, values.foreground);
  206. X! #endif
  207. X!   }
  208. X  
  209. X!  XSetFillStyle(dpy, my_gc, FillStippled);
  210. X  
  211. X!  /* loop through each character in string ... */
  212. X!  for(i=0; i<len; i++)
  213. X!  {
  214. X!   ichar=str[i]-32;
  215. X  
  216. X!   /* make sure it's a printing character ... */
  217. X!   if((ichar>=0)&&(ichar<95))
  218. X!   {
  219. X!    /* suitable offset ... */
  220. X!    if(dir==1)
  221. X!      { xp=x-rotfont->per_char[ichar].ascent;
  222. X!        yp=y-rotfont->per_char[ichar].rbearing; }
  223. X!    else if(dir==2)
  224. X!      { xp=x-rotfont->per_char[ichar].rbearing;
  225. X!        yp=y-rotfont->per_char[ichar].descent+1; }
  226. X!    else
  227. X!      { xp=x-rotfont->per_char[ichar].descent+1;  
  228. X!        yp=y+rotfont->per_char[ichar].lbearing; }
  229. X!                    
  230. X!    /* draw the glyph ... */
  231. X!    XSetStipple(dpy, my_gc, rotfont->per_char[ichar].glyph.bm);
  232. X  
  233. X!    XSetTSOrigin(dpy, my_gc, xp, yp);
  234. X!    
  235. X!    XFillRectangle(dpy, drawable, my_gc, xp, yp,
  236. X!                   rotfont->per_char[ichar].glyph.bit_w,
  237. X!                   rotfont->per_char[ichar].glyph.bit_h);
  238. X!     
  239. X!    /* advance position ... */
  240. X!    if(dir==1)      y-=rotfont->per_char[ichar].width;
  241. X!    else if(dir==2) x-=rotfont->per_char[ichar].width;
  242. X!    else            y+=rotfont->per_char[ichar].width;
  243. X!   }
  244. X!  }
  245. X  }
  246. X!   
  247. X!     
  248. X  /* ---------------------------------------------------------------------- */
  249. X  
  250. X  
  251. X! /* *** A front end to XRotPaintAlignedString : uses XRotDrawString *** */
  252. X  
  253. X! void XRotDrawAlignedString(dpy, drawable, rotfont, gc, x, y,
  254. X!                                   text, align)
  255. X!  Display *dpy;                    
  256. X!  Drawable drawable;
  257. X!  XRotFontStruct *rotfont;
  258. X!  GC gc;
  259. X!  int x, y;
  260. X!  char *text;
  261. X!  int align;
  262. X  {
  263. X!  XRotPaintAlignedString(dpy, drawable, rotfont, gc, x, y, text, align, 0);
  264. X  }
  265. X  
  266. X  
  267. X--- 383,1310 ----
  268. X  /* ---------------------------------------------------------------------- */
  269. X  
  270. X  
  271. X! /**************************************************************************/
  272. X! /*  Aligns and paints a rotated string                                    */
  273. X! /**************************************************************************/
  274. X  
  275. X! static int XRotPaintAlignedString(dpy, font, angle, drawable, gc, x, y, text,
  276. X!                   align, bg)
  277. X!     Display *dpy;
  278. X!     XFontStruct *font;
  279. X!     float angle;
  280. X!     Drawable drawable;
  281. X!     GC gc;
  282. X!     int x, y;
  283. X!     char *text;
  284. X!     int align;
  285. X!     int bg;
  286. X  {
  287. X!     int i;
  288. X!     GC my_gc;
  289. X!     int xp, yp;
  290. X!     float hot_x, hot_y;
  291. X!     float hot_xp, hot_yp;
  292. X!     float sin_angle, cos_angle;
  293. X!     RotatedTextItem *item;
  294. X!     Pixmap bitmap_to_paint;
  295. X!     
  296. X!     /* return early for NULL/empty strings */
  297. X!     if(text==NULL || *text=='\0')
  298. X!         return 0;
  299. X!     
  300. X!     /* manipulate angle to 0<=angle<2*PI radians */
  301. X!     while(angle<0.0)
  302. X!         angle+=M_2PI;
  303. X!     
  304. X!     while(angle>=M_2PI)
  305. X!         angle-=M_2PI;
  306. X!     
  307. X!     /* horizontal text made easy */
  308. X!     if(angle==0. && style.magnify==1.) 
  309. X!     return(XRotDrawHorizontalString(dpy, font, drawable, gc, x, y,
  310. X!                     text, align, bg));
  311. X!     
  312. X!     /* get a rotated bitmap */
  313. X!     item=XRotRetrieveFromCache(dpy, font, angle, text, align);
  314. X!     if(item==NULL)
  315. X!     return NULL;
  316. X!     
  317. X!     /* this gc has similar properties to the user's gc */
  318. X!     my_gc=XCreateGC(dpy, drawable, (unsigned long) 0, 0);
  319. X!     XCopyGC(dpy, gc, GCForeground|GCBackground|GCFunction|GCPlaneMask,
  320. X!         my_gc);
  321. X  
  322. X!     /* alignment : which point (hot_x, hot_y) relative to bitmap centre
  323. X!        coincides with user's specified point? */
  324. X!     
  325. X!     /* y position */
  326. X!     if(align==TLEFT || align==TCENTRE || align==TRIGHT)
  327. X!         hot_y=(float)item->rows_in/2*style.magnify;
  328. X!     else if(align==MLEFT || align==MCENTRE || align==MRIGHT)
  329. X!     hot_y=0;
  330. X!     else if(align==BLEFT || align==BCENTRE || align==BRIGHT)
  331. X!     hot_y= -(float)item->rows_in/2*style.magnify;
  332. X!     else
  333. X!     hot_y= -((float)item->rows_in/2-(float)font->descent)*style.magnify;
  334. X!     
  335. X!     /* x position */
  336. X!     if(align==TLEFT || align==MLEFT || align==BLEFT || align==NONE)
  337. X!     hot_x= -(float)item->max_width/2*style.magnify;
  338. X!     else if(align==TCENTRE || align==MCENTRE || align==BCENTRE)
  339. X!     hot_x=0;
  340. X!     else
  341. X!         hot_x=(float)item->max_width/2*style.magnify;
  342. X!     
  343. X!     /* pre-calculate sin and cos */
  344. X!     sin_angle=sin(angle);
  345. X!     cos_angle=cos(angle);
  346. X!     
  347. X!     /* rotate hot_x and hot_y around bitmap centre */
  348. X!     hot_xp= hot_x*cos_angle - hot_y*sin_angle;
  349. X!     hot_yp= hot_x*sin_angle + hot_y*cos_angle;
  350. X!     
  351. X!     /* text background will be drawn using XFillPolygon */
  352. X!     if(bg) {
  353. X!     GC depth_one_gc;
  354. X!     XPoint *xpoints;
  355. X!     Pixmap empty_stipple;
  356. X!     
  357. X!     /* reserve space for XPoints */
  358. X!     xpoints=(XPoint *)malloc((unsigned)(4*item->nl*sizeof(XPoint)));
  359. X!     if(!xpoints)
  360. X!         return 1;
  361. X!     
  362. X!     /* rotate corner positions */
  363. X!     for(i=0; i<4*item->nl; i++) {
  364. X!         xpoints[i].x=(float)x + ( (item->corners_x[i]-hot_x)*cos_angle + 
  365. X!                       (item->corners_y[i]+hot_y)*sin_angle);
  366. X!         xpoints[i].y=(float)y + (-(item->corners_x[i]-hot_x)*sin_angle + 
  367. X!                       (item->corners_y[i]+hot_y)*cos_angle);
  368. X!     }
  369. X!     
  370. X!     /* we want to swap foreground and background colors here;
  371. X!        XGetGCValues() is only available in R4+ */
  372. X!     
  373. X!     empty_stipple=XCreatePixmap(dpy, drawable, 1, 1, 1);
  374. X!     
  375. X!     depth_one_gc=XCreateGC(dpy, empty_stipple, (unsigned long) 0, 0);
  376. X!     XSetForeground(dpy, depth_one_gc, 0);
  377. X!     XFillRectangle(dpy, empty_stipple, depth_one_gc, 0, 0, 2, 2);
  378. X  
  379. X!     XSetStipple(dpy, my_gc, empty_stipple);
  380. X!     XSetFillStyle(dpy, my_gc, FillOpaqueStippled);
  381. X!     
  382. X!     XFillPolygon(dpy, drawable, my_gc, xpoints, 4*item->nl, Nonconvex,
  383. X!              CoordModeOrigin);
  384. X!     
  385. X!     /* free our resources */
  386. X!     free((char *)xpoints);
  387. X!     XFreeGC(dpy, depth_one_gc);
  388. X!     XFreePixmap(dpy, empty_stipple);
  389. X!     }
  390. X!     
  391. X!     /* where should top left corner of bitmap go ? */
  392. X!     xp=(float)x-((float)item->cols_out/2 +hot_xp);
  393. X!     yp=(float)y-((float)item->rows_out/2 -hot_yp);
  394. X!     
  395. X!     /* by default we draw the rotated bitmap, solid */
  396. X!     bitmap_to_paint=item->bitmap;
  397. X  
  398. X!     /* handle user stippling */
  399. X! #ifndef X11R3
  400. X!     {
  401. X!     GC depth_one_gc;
  402. X!     XGCValues values;
  403. X!     Pixmap new_bitmap, inverse;
  404. X!     
  405. X!     /* try and get some GC properties */
  406. X!     if(XGetGCValues(dpy, gc, 
  407. X!             GCStipple|GCFillStyle|GCForeground|GCBackground|
  408. X!             GCTileStipXOrigin|GCTileStipYOrigin,
  409. X!             &values)) {
  410. X! 
  411. X!         /* only do this if stippling requested */
  412. X!         if((values.fill_style==FillStippled ||
  413. X!         values.fill_style==FillOpaqueStippled) && !bg) {
  414. X! 
  415. X!         /* opaque stipple: draw rotated text in background colour */
  416. X!         if(values.fill_style==FillOpaqueStippled) {
  417. X!             XSetForeground(dpy, my_gc, values.background);
  418. X!             XSetFillStyle(dpy, my_gc, FillStippled);
  419. X!             XSetStipple(dpy, my_gc, item->bitmap);
  420. X!             XSetTSOrigin(dpy, my_gc, xp, yp);
  421. X!             XFillRectangle(dpy, drawable, my_gc, xp, yp,
  422. X!                    item->cols_out, item->rows_out);
  423. X!             XSetForeground(dpy, my_gc, values.foreground);
  424. X!         }
  425. X! 
  426. X!         /* this will merge the rotated text and the user's stipple */
  427. X!         new_bitmap=XCreatePixmap(dpy, drawable,
  428. X!                      item->cols_out, item->rows_out, 1);
  429. X! 
  430. X!         /* create a GC */
  431. X!         depth_one_gc=XCreateGC(dpy, new_bitmap, (unsigned long) 0, 0);
  432. X!         XSetForeground(dpy, depth_one_gc, 1);
  433. X!         XSetBackground(dpy, depth_one_gc, 0);
  434. X! 
  435. X!         /* set the relative stipple origin */
  436. X!         XSetTSOrigin(dpy, depth_one_gc, 
  437. X!                  values.ts_x_origin-xp, values.ts_y_origin-yp);
  438. X! 
  439. X!         /* fill the whole bitmap with the user's stipple */
  440. X!         XSetStipple(dpy, depth_one_gc, values.stipple);
  441. X!         XSetFillStyle(dpy, depth_one_gc, FillOpaqueStippled);
  442. X!         XFillRectangle(dpy, new_bitmap, depth_one_gc,
  443. X!                    0, 0, item->cols_out, item->rows_out);
  444. X! 
  445. X!         /* set stipple origin back to normal */
  446. X!         XSetTSOrigin(dpy, depth_one_gc, 0, 0);
  447. X! 
  448. X!         /* this will contain an inverse copy of the rotated text */
  449. X!         inverse=XCreatePixmap(dpy, drawable,
  450. X!                       item->cols_out, item->rows_out, 1);
  451. X! 
  452. X!         /* invert text */
  453. X!         XSetFillStyle(dpy, depth_one_gc, FillSolid);
  454. X!         XSetFunction(dpy, depth_one_gc, GXcopyInverted);
  455. X!         XCopyArea(dpy, item->bitmap, inverse, depth_one_gc,
  456. X!               0, 0, item->cols_out, item->rows_out, 0, 0);
  457. X! 
  458. X!         /* now delete user's stipple everywhere EXCEPT on text */
  459. X!                 XSetForeground(dpy, depth_one_gc, 0);
  460. X!                 XSetBackground(dpy, depth_one_gc, 1);
  461. X!         XSetStipple(dpy, depth_one_gc, inverse);
  462. X!         XSetFillStyle(dpy, depth_one_gc, FillStippled);
  463. X!         XSetFunction(dpy, depth_one_gc, GXcopy);
  464. X!         XFillRectangle(dpy, new_bitmap, depth_one_gc,
  465. X!                                0, 0, item->cols_out, item->rows_out);
  466. X! 
  467. X!         /* free resources */
  468. X!         XFreePixmap(dpy, inverse);
  469. X!         XFreeGC(dpy, depth_one_gc);
  470. X! 
  471. X!         /* this is the new bitmap */
  472. X!         bitmap_to_paint=new_bitmap;
  473. X!         }
  474. X!     }
  475. X!     }
  476. X! #endif /*X11R3*/
  477. X! 
  478. X!     /* paint text using stipple technique */
  479. X!     XSetFillStyle(dpy, my_gc, FillStippled);
  480. X!     XSetStipple(dpy, my_gc, bitmap_to_paint);
  481. X!     XSetTSOrigin(dpy, my_gc, xp, yp);
  482. X!     XFillRectangle(dpy, drawable, my_gc, xp, yp, 
  483. X!            item->cols_out, item->rows_out);
  484. X!     
  485. X!     /* free our resources */
  486. X!     XFreeGC(dpy, my_gc);
  487. X! 
  488. X!     /* stippled bitmap no longer needed */
  489. X!     if(bitmap_to_paint!=item->bitmap)
  490. X!     XFreePixmap(dpy, bitmap_to_paint);
  491. X! 
  492. X! #ifdef CACHE_XIMAGES
  493. X!     XFreePixmap(dpy, item->bitmap);
  494. X! #endif /*CACHE_XIMAGES*/
  495. X! 
  496. X!     /* if item isn't cached, destroy it completely */
  497. X!     if(!item->cached) 
  498. X!     XRotFreeTextItem(dpy,item);
  499. X! 
  500. X!     /* we got to the end OK! */
  501. X!     return 0;
  502. X  }
  503. X  
  504. X  
  505. X  /* ---------------------------------------------------------------------- */
  506. X  
  507. X  
  508. X! /**************************************************************************/
  509. X! /*  Draw a horizontal string in a quick fashion                           */
  510. X! /**************************************************************************/
  511. X! 
  512. X! static int XRotDrawHorizontalString(dpy, font, drawable, gc, x, y, text, 
  513. X!                      align, bg)
  514. X!     Display *dpy;
  515. X!     XFontStruct *font;
  516. X!     Drawable drawable;
  517. X!     GC gc;
  518. X!     int x, y;
  519. X!     char *text;
  520. X!     int align;
  521. X!     int bg;
  522. X  {
  523. X!     GC my_gc;
  524. X!     int nl=1, i;
  525. X!     int height;
  526. X!     int xp, yp;
  527. X!     char *str1, *str2, *str3;
  528. X!     char *str2_a="\0", *str2_b="\n\0";
  529. X!     int dir, asc, desc;
  530. X!     XCharStruct overall;
  531. X  
  532. X!     DEBUG_PRINT1("**Horizontal text.\n");
  533. X! 
  534. X!     if (text == NULL || *text=='\0') {
  535. X!     DEBUG_PRINT1("Empty string, ignoring\n");
  536. X      return 0;
  537. X+     }
  538. X  
  539. X!     /* this gc has similar properties to the user's gc (including stipple) */
  540. X!     my_gc=XCreateGC(dpy, drawable, (unsigned long) 0, 0);
  541. X!     XCopyGC(dpy, gc,
  542. X!         GCForeground|GCBackground|GCFunction|GCStipple|GCFillStyle|
  543. X!         GCTileStipXOrigin|GCTileStipYOrigin|GCPlaneMask, my_gc);
  544. X!     XSetFont(dpy, my_gc, font->fid);
  545. X!     
  546. X!     /* count number of sections in string */
  547. X!     if(align!=NONE)
  548. X!     for(i=0; i<strlen(text)-1; i++)
  549. X!         if(text[i]=='\n')
  550. X!         nl++;
  551. X!     
  552. X!     /* ignore newline characters if not doing alignment */
  553. X!     if(align==NONE)
  554. X!     str2=str2_a;
  555. X!     else
  556. X!     str2=str2_b;
  557. X!     
  558. X!     /* overall font height */
  559. X!     height=font->ascent+font->descent;
  560. X!     
  561. X!     /* y position */
  562. X!     if(align==TLEFT || align==TCENTRE || align==TRIGHT)
  563. X!     yp=y+font->ascent;
  564. X!     else if(align==MLEFT || align==MCENTRE || align==MRIGHT)
  565. X!     yp=y-nl*height/2+font->ascent;
  566. X!     else if(align==BLEFT || align==BCENTRE || align==BRIGHT)
  567. X!     yp=y-nl*height+font->ascent;
  568. X!     else
  569. X!     yp=y;
  570. X!     
  571. X!     str1=my_strdup(text);
  572. X!     if(str1==NULL)
  573. X!     return 1;
  574. X!     
  575. X!     str3=my_strtok(str1, str2);
  576. X!     
  577. X!     /* loop through each section in the string */
  578. X!     do {
  579. X!         XTextExtents(font, str3, strlen(str3), &dir, &asc, &desc,
  580. X!                      &overall);
  581. X  
  582. X!     /* where to draw section in x ? */
  583. X!     if(align==TLEFT || align==MLEFT || align==BLEFT || align==NONE)
  584. X!         xp=x;
  585. X!     else if(align==TCENTRE || align==MCENTRE || align==BCENTRE)
  586. X!         xp=x-overall.rbearing/2;
  587. X!     else
  588. X!         xp=x-overall.rbearing;
  589. X!     
  590. X!     /* draw string onto bitmap */
  591. X!     if(!bg)
  592. X!         XDrawString(dpy, drawable, my_gc, xp, yp, str3, strlen(str3));
  593. X!     else
  594. X!         XDrawImageString(dpy, drawable, my_gc, xp, yp, str3, strlen(str3));
  595. X!     
  596. X!     /* move to next line */
  597. X!     yp+=height;
  598. X!     
  599. X!     str3=my_strtok((char *)NULL, str2);
  600. X!     }
  601. X!     while(str3!=NULL);
  602. X!     
  603. X!     free(str1);
  604. X!     XFreeGC(dpy, my_gc);
  605. X  
  606. X!     return 0;
  607. X  }
  608. X  
  609. X  
  610. X! /* ---------------------------------------------------------------------- */
  611. X! 
  612. X! 
  613. X! /**************************************************************************/
  614. X! /*   Query cache for a match with this font/text/angle/alignment          */
  615. X! /*       request, otherwise arrange for its creation                      */
  616. X! /**************************************************************************/
  617. X! 
  618. X! static RotatedTextItem *XRotRetrieveFromCache(dpy, font, angle, text, align)
  619. X!     Display *dpy;
  620. X!     XFontStruct *font;
  621. X!     float angle;
  622. X!     char *text;
  623. X!     int align;
  624. X  {
  625. X!     Font fid;
  626. X!     char *font_name=NULL;
  627. X!     unsigned long name_value;
  628. X!     RotatedTextItem *item=NULL;
  629. X!     RotatedTextItem *i1=first_text_item;
  630. X!     
  631. X!     /* get font name, if it exists */
  632. X!     if(XGetFontProperty(font, XA_FONT, &name_value)) {
  633. X!     DEBUG_PRINT1("got font name OK\n");
  634. X!     font_name=XGetAtomName(dpy, name_value);
  635. X!     fid=0;
  636. X!     }
  637. X! #ifdef CACHE_FID
  638. X!     /* otherwise rely (unreliably?) on font ID */
  639. X!     else {
  640. X!     DEBUG_PRINT1("can't get fontname, caching FID\n");
  641. X!     font_name=NULL;
  642. X!     fid=font->fid;
  643. X!     }
  644. X! #else
  645. X!     /* not allowed to cache font ID's */
  646. X!     else {
  647. X!     DEBUG_PRINT1("can't get fontname, can't cache\n");
  648. X!     font_name=NULL;
  649. X!     fid=0;
  650. X!     }
  651. X! #endif /*CACHE_FID*/
  652. X!     
  653. X!     /* look for a match in cache */
  654. X  
  655. X!     /* matching formula:
  656. X!        identical text;
  657. X!        identical fontname (if defined, font ID's if not);
  658. X!        angles close enough (<0.00001 here, could be smaller);
  659. X!        HORIZONTAL alignment matches, OR it's a one line string;
  660. X!        magnifications the same */
  661. X  
  662. X!     while(i1 && !item) {
  663. X!     /* match everything EXCEPT fontname/ID */
  664. X!     if(strcmp(text, i1->text)==0 &&
  665. X!        fabs(angle-i1->angle)<0.00001 &&
  666. X!        style.magnify==i1->magnify &&
  667. X!        (i1->nl==1 ||
  668. X!         ((align==0)?9:(align-1))%3==
  669. X!           ((i1->align==0)?9:(i1->align-1))%3)) {
  670. X  
  671. X!         /* now match fontname/ID */
  672. X!         if(font_name!=NULL && i1->font_name!=NULL) {
  673. X!         if(strcmp(font_name, i1->font_name)==0) {
  674. X!             item=i1;
  675. X!             DEBUG_PRINT1("Matched against font names\n");
  676. X!         }
  677. X!         else
  678. X!             i1=i1->next;
  679. X!         }
  680. X! #ifdef CACHE_FID
  681. X!         else if(font_name==NULL && i1->font_name==NULL) {
  682. X!         if(fid==i1->fid) {
  683. X!             item=i1;
  684. X!             DEBUG_PRINT1("Matched against FID's\n");
  685. X!                 }
  686. X!         else
  687. X!                     i1=i1->next;
  688. X!         }
  689. X! #endif /*CACHE_FID*/
  690. X!         else
  691. X!         i1=i1->next;
  692. X!     }
  693. X!     else
  694. X!         i1=i1->next;
  695. X!     }
  696. X!     
  697. X!     if(item)
  698. X!     DEBUG_PRINT1("**Found target in cache.\n");
  699. X!     if(!item)
  700. X!     DEBUG_PRINT1("**No match in cache.\n");
  701. X  
  702. X+     /* no match */
  703. X+     if(!item) {
  704. X+     /* create new item */
  705. X+     item=XRotCreateTextItem(dpy, font, angle, text, align);
  706. X+     if(!item)
  707. X+         return NULL;
  708. X  
  709. X!     /* record what it shows */
  710. X!     item->text=my_strdup(text);
  711. X  
  712. X+     /* fontname or ID */
  713. X+     if(font_name!=NULL) {
  714. X+         item->font_name=my_strdup(font_name);
  715. X+         item->fid=0;
  716. X+     }
  717. X+     else {
  718. X+         item->font_name=NULL;
  719. X+         item->fid=fid;
  720. X+     }
  721. X  
  722. X!     item->angle=angle;
  723. X!     item->align=align;
  724. X!     item->magnify=style.magnify;
  725. X  
  726. X!     /* cache it */
  727. X!     XRotAddToLinkedList(dpy, item);
  728. X!     }
  729. X! 
  730. X!     if(font_name)
  731. X!     XFree(font_name);
  732. X! 
  733. X!     /* if XImage is cached, need to recreate the bitmap */
  734. X! 
  735. X! #ifdef CACHE_XIMAGES
  736. X!     {
  737. X!     GC depth_one_gc;
  738. X! 
  739. X!     /* create bitmap to hold rotated text */
  740. X!     item->bitmap=XCreatePixmap(dpy, DefaultRootWindow(dpy),
  741. X!                    item->cols_out, item->rows_out, 1);
  742. X!     
  743. X!     /* depth one gc */
  744. X!     depth_one_gc=XCreateGC(dpy, item->bitmap, (unsigned long) 0, 0);
  745. X!     XSetBackground(dpy, depth_one_gc, 0);
  746. X!     XSetForeground(dpy, depth_one_gc, 1);
  747. X! 
  748. X!     /* make the text bitmap from XImage */
  749. X!     XPutImage(dpy, item->bitmap, depth_one_gc, item->ximage, 0, 0, 0, 0,
  750. X!           item->cols_out, item->rows_out);
  751. X! 
  752. X!     XFreeGC(dpy, depth_one_gc);
  753. X!     }
  754. X! #endif /*CACHE_XIMAGES*/
  755. X!     
  756. X!     return item;
  757. X  }
  758. X  
  759. X  
  760. X  /* ---------------------------------------------------------------------- */
  761. X  
  762. X  
  763. X! /**************************************************************************/
  764. X! /*  Create a rotated text item                                            */
  765. X! /**************************************************************************/
  766. X! 
  767. X! static RotatedTextItem *XRotCreateTextItem(dpy, font, angle, text, align)
  768. X!     Display *dpy;
  769. X!     XFontStruct *font;
  770. X!     float angle;
  771. X!     char *text;
  772. X!     int align;
  773. X  {
  774. X!     RotatedTextItem *item=NULL;
  775. X!     Pixmap canvas;
  776. X!     GC font_gc;
  777. X!     XImage *I_in;
  778. X!     register int i, j;
  779. X!     char *str1, *str2, *str3;
  780. X!     char *str2_a="\0", *str2_b="\n\0";
  781. X!     int height;
  782. X!     int byte_w_in, byte_w_out;
  783. X!     int xp, yp;
  784. X!     float sin_angle, cos_angle;
  785. X!     int it, jt;
  786. X!     float di, dj;
  787. X!     int ic=0;
  788. X!     float xl, xr, xinc;
  789. X!     int byte_out;
  790. X!     int dir, asc, desc;
  791. X!     XCharStruct overall;
  792. X!     int old_cols_in=0, old_rows_in=0;
  793. X!     
  794. X!     /* allocate memory */
  795. X!     item=(RotatedTextItem *)malloc((unsigned)sizeof(RotatedTextItem));
  796. X!     if(!item)
  797. X!     return NULL;
  798. X!     
  799. X!     /* count number of sections in string */
  800. X!     item->nl=1;
  801. X!     if(align!=NONE)
  802. X!     for(i=0; i<strlen(text)-1; i++)
  803. X!         if(text[i]=='\n')
  804. X!         item->nl++;
  805. X!     
  806. X!     /* ignore newline characters if not doing alignment */
  807. X!     if(align==NONE)
  808. X!     str2=str2_a;
  809. X!     else
  810. X!     str2=str2_b;
  811. X!     
  812. X!     /* find width of longest section */
  813. X!     str1=my_strdup(text);
  814. X!     if(str1==NULL)
  815. X!     return NULL;
  816. X!     
  817. X!     str3=my_strtok(str1, str2);
  818. X! 
  819. X!     XTextExtents(font, str3, strlen(str3), &dir, &asc, &desc,
  820. X!          &overall);
  821. X!     
  822. X!     item->max_width=overall.rbearing;
  823. X!     
  824. X!     /* loop through each section */
  825. X!     do {
  826. X!     str3=my_strtok((char *)NULL, str2);
  827. X! 
  828. X!     if(str3!=NULL) {
  829. X!         XTextExtents(font, str3, strlen(str3), &dir, &asc, &desc,
  830. X!              &overall);
  831. X! 
  832. X!         if(overall.rbearing>item->max_width)
  833. X!         item->max_width=overall.rbearing;
  834. X!     }
  835. X!     }
  836. X!     while(str3!=NULL);
  837. X!     
  838. X!     free(str1);
  839. X!     
  840. X!     /* overall font height */
  841. X!     height=font->ascent+font->descent;
  842. X!     
  843. X!     /* dimensions horizontal text will have */
  844. X!     item->cols_in=item->max_width;
  845. X!     item->rows_in=item->nl*height;
  846. X!     
  847. X!     /* bitmap for drawing on */
  848. X!     canvas=XCreatePixmap(dpy, DefaultRootWindow(dpy),
  849. X!              item->cols_in, item->rows_in, 1);
  850. X!     
  851. X!     /* create a GC for the bitmap */
  852. X!     font_gc=XCreateGC(dpy, canvas, (unsigned long) 0, 0);
  853. X!     XSetBackground(dpy, font_gc, 0);
  854. X!     XSetFont(dpy, font_gc, font->fid);
  855. X!     
  856. X!     /* make sure the bitmap is blank */
  857. X!     XSetForeground(dpy, font_gc, 0);
  858. X!     XFillRectangle(dpy, canvas, font_gc, 0, 0, 
  859. X!            item->cols_in+1, item->rows_in+1);
  860. X!     XSetForeground(dpy, font_gc, 1);
  861. X!     
  862. X!     /* pre-calculate sin and cos */
  863. X!     sin_angle=sin(angle);
  864. X!     cos_angle=cos(angle);
  865. X!     
  866. X!     /* text background will be drawn using XFillPolygon */
  867. X!     item->corners_x=
  868. X!     (float *)malloc((unsigned)(4*item->nl*sizeof(float)));
  869. X!     if(!item->corners_x)
  870. X!     return NULL;
  871. X!     
  872. X!     item->corners_y=
  873. X!     (float *)malloc((unsigned)(4*item->nl*sizeof(float)));
  874. X!     if(!item->corners_y)
  875. X!     return NULL;
  876. X!     
  877. X!     /* draw text horizontally */
  878. X!     
  879. X!     /* start at top of bitmap */
  880. X!     yp=font->ascent;
  881. X!     
  882. X!     str1=my_strdup(text);
  883. X!     if(str1==NULL)
  884. X!     return NULL;
  885. X!     
  886. X!     str3=my_strtok(str1, str2);
  887. X!     
  888. X!     /* loop through each section in the string */
  889. X!     do {
  890. X!     XTextExtents(font, str3, strlen(str3), &dir, &asc, &desc,
  891. X!         &overall);
  892. X! 
  893. X!     /* where to draw section in x ? */
  894. X!     if(align==TLEFT || align==MLEFT || align==BLEFT || align==NONE)
  895. X!         xp=0;
  896. X!     else if(align==TCENTRE || align==MCENTRE || align==BCENTRE)
  897. X!         xp=(item->max_width-overall.rbearing)/2;
  898. X!     else
  899. X!             xp=item->max_width-overall.rbearing;
  900. X! 
  901. X!     /* draw string onto bitmap */
  902. X!     XDrawString(dpy, canvas, font_gc, xp, yp, str3, strlen(str3));
  903. X!     
  904. X!     /* keep a note of corner positions of this string */
  905. X!     item->corners_x[ic]=((float)xp-(float)item->cols_in/2)*style.magnify;
  906. X!     item->corners_y[ic]=((float)(yp-font->ascent)-(float)item->rows_in/2)
  907. X!         *style.magnify;
  908. X!     item->corners_x[ic+1]=item->corners_x[ic];
  909. X!     item->corners_y[ic+1]=item->corners_y[ic]+(float)height*style.magnify;
  910. X!     item->corners_x[item->nl*4-1-ic]=item->corners_x[ic]+
  911. X!         (float)overall.rbearing*style.magnify;
  912. X!     item->corners_y[item->nl*4-1-ic]=item->corners_y[ic];
  913. X!     item->corners_x[item->nl*4-2-ic]=
  914. X!         item->corners_x[item->nl*4-1-ic];
  915. X!     item->corners_y[item->nl*4-2-ic]=item->corners_y[ic+1];
  916. X!     
  917. X!     ic+=2;
  918. X!     
  919. X!     /* move to next line */
  920. X!     yp+=height;
  921. X!     
  922. X!     str3=my_strtok((char *)NULL, str2);
  923. X!     }
  924. X!     while(str3!=NULL);
  925. X!     
  926. X!     free(str1);
  927. X!     
  928. X!     /* create image to hold horizontal text */
  929. X!     I_in=MakeXImage(dpy, item->cols_in, item->rows_in);
  930. X!     if(I_in==NULL)
  931. X!     return NULL;
  932. X!     
  933. X!     /* extract horizontal text */
  934. X!     XGetSubImage(dpy, canvas, 0, 0, item->cols_in, item->rows_in,
  935. X!          1, XYPixmap, I_in, 0, 0);
  936. X!     I_in->format=XYBitmap;
  937. X!     
  938. X!     /* magnify horizontal text */
  939. X!     if(style.magnify!=1.) {
  940. X!     I_in=XRotMagnifyImage(dpy, I_in);
  941. X! 
  942. X!     old_cols_in=item->cols_in;
  943. X!     old_rows_in=item->rows_in;
  944. X!     item->cols_in=(float)item->cols_in*style.magnify;
  945. X!     item->rows_in=(float)item->rows_in*style.magnify;
  946. X!     }
  947. X! 
  948. X!     /* how big will rotated text be ? */
  949. X!     item->cols_out=fabs((float)item->rows_in*sin_angle) +
  950. X!     fabs((float)item->cols_in*cos_angle) +0.99999 +2;
  951. X! 
  952. X!     item->rows_out=fabs((float)item->rows_in*cos_angle) +
  953. X!     fabs((float)item->cols_in*sin_angle) +0.99999 +2;
  954. X! 
  955. X!     if(item->cols_out%2==0)
  956. X!     item->cols_out++;
  957. X!     
  958. X!     if(item->rows_out%2==0)
  959. X!     item->rows_out++;
  960. X!     
  961. X!     /* create image to hold rotated text */
  962. X!     item->ximage=MakeXImage(dpy, item->cols_out, item->rows_out);
  963. X!     if(item->ximage==NULL)
  964. X!     return NULL;
  965. X!     
  966. X!     byte_w_in=(item->cols_in-1)/8+1;
  967. X!     byte_w_out=(item->cols_out-1)/8+1;
  968. X!     
  969. X!     /* we try to make this bit as fast as possible - which is why it looks
  970. X!        a bit over-the-top */
  971. X!     
  972. X!     /* vertical distance from centre */
  973. X!     dj=0.5-(float)item->rows_out/2;
  974. X! 
  975. X!     /* where abouts does text actually lie in rotated image? */
  976. X!     /* check angle within 0.5 degrees (0.008 radians) */
  977. X!     if(fabs((double)angle)<0.008 || fabs((double)angle-M_PI/2)<0.008 || 
  978. X!        fabs((double)angle-M_PI)<0.008 || fabs((double)angle-3*M_PI/2)<0.008) {
  979. X!     xl=0;
  980. X!     xr=(float)item->cols_out;
  981. X!     xinc=0;
  982. X!     }
  983. X!     else if(angle<M_PI) {
  984. X!     xl=(float)item->cols_out/2+
  985. X!         (dj-(float)item->rows_in/(2*cos_angle))/
  986. X!         tan(angle)-2;
  987. X!     xr=(float)item->cols_out/2+
  988. X!         (dj+(float)item->rows_in/(2*cos_angle))/
  989. X!         tan(angle)+2;
  990. X!     xinc=1./tan(angle);
  991. X!     }
  992. X!     else {
  993. X!     xl=(float)item->cols_out/2+
  994. X!         (dj+(float)item->rows_in/(2*cos_angle))/
  995. X!         tan(angle)-2;
  996. X!     xr=(float)item->cols_out/2+
  997. X!         (dj-(float)item->rows_in/(2*cos_angle))/
  998. X!         tan(angle)+2;
  999. X!     
  1000. X!     xinc=1./tan(angle);
  1001. X!     }
  1002. X! 
  1003. X!     /* loop through all relevent bits in rotated image */
  1004. X!     for(j=0; j<item->rows_out; j++) {
  1005. X!     
  1006. X!     /* no point re-calculating these every pass */
  1007. X!     di=(float)((xl<0)?0:(int)xl)+0.5-(float)item->cols_out/2;
  1008. X!     byte_out=(item->rows_out-j-1)*byte_w_out;
  1009. X!     
  1010. X!     /* loop through meaningful columns */
  1011. X!     for(i=((xl<0)?0:(int)xl); 
  1012. X!         i<((xr>=item->cols_out)?item->cols_out:(int)xr); i++) {
  1013. X!         
  1014. X!         /* rotate coordinates */
  1015. X!         it=(float)item->cols_in/2 + ( di*cos_angle + dj*sin_angle);
  1016. X!         jt=(float)item->rows_in/2 - (-di*sin_angle + dj*cos_angle);
  1017. X!         
  1018. X!             /* set pixel if required */
  1019. X!             if(it>=0 && it<item->cols_in && jt>=0 && jt<item->rows_in)
  1020. X!                 if((I_in->data[jt*byte_w_in+it/8] & 128>>(it%8))>0)
  1021. X!                     item->ximage->data[byte_out+i/8]|=128>>i%8;
  1022. X!         
  1023. X!         di+=1;
  1024. X!     }
  1025. X!     dj+=1;
  1026. X!     xl+=xinc;
  1027. X!     xr+=xinc;
  1028. X!     }
  1029. X!     XDestroyImage(I_in);
  1030. X!     
  1031. END_OF_FILE
  1032.   if test 29056 -ne `wc -c <'xfig.10'`; then
  1033.     echo shar: \"'xfig.10'\" unpacked with wrong size!
  1034.   fi
  1035.   # end of 'xfig.10'
  1036. fi
  1037. echo shar: End of archive 11 \(of 16\).
  1038. cp /dev/null ark11isdone
  1039. MISSING=""
  1040. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do
  1041.     if test ! -f ark${I}isdone ; then
  1042.     MISSING="${MISSING} ${I}"
  1043.     fi
  1044. done
  1045. if test "${MISSING}" = "" ; then
  1046.     echo You have unpacked all 16 archives.
  1047.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1048.     echo Creating merged patch file xfig.p2
  1049.     cat xfig.[01][0-9] > xfig.p2
  1050.     rm -f xfig.[01][0-9]
  1051. else
  1052.     echo You still must unpack the following archives:
  1053.     echo "        " ${MISSING}
  1054. fi
  1055. exit 0
  1056. exit 0 # Just in case...
  1057. -- 
  1058.   // chris@Sterling.COM           | Send comp.sources.x submissions to:
  1059. \X/  Amiga - The only way to fly! |    sources-x@sterling.com
  1060.  "It's intuitively obvious to the |
  1061.   most casual observer..."        | GCS d+/-- p+ c++ l+ m+ s++/+ g+ w+ t+ r+ x+
  1062.