draw.c 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365
  1. /* draw.c:
  2. * Compute position of legend, title, labels and ticks
  3. * Extracted from original d.legend/main.c for background purpose
  4. * Moving to seperate file: Adam Laza, GSoC 2016
  5. *
  6. * Copyright (C) 2014 by Hamish Bowman, and the GRASS Development Team*
  7. * This program is free software under the GPL (>=v2)
  8. * Read the COPYING file that comes with GRASS for details.
  9. */
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <math.h>
  13. #include <grass/gis.h>
  14. #include <grass/raster.h>
  15. #include <grass/raster3d.h>
  16. #include <grass/display.h>
  17. #include <grass/glocale.h>
  18. #include "local_proto.h"
  19. void draw(const char *map_name, int maptype, int color, int thin, int lines,
  20. int steps, int fp, int label_indent, int hide_catnum,
  21. int hide_catstr, int show_ticks, int hide_nodata, int do_smooth,
  22. struct Categories cats, struct Colors colors, double X0, double X1,
  23. double Y0, double Y1, int flip, int UserRange, double UserRangeMin,
  24. double UserRangeMax, double *catlist, int catlistCount,
  25. int use_catlist, int ticksCount, double fontsize,
  26. double tit_fontsize, const char *title, double *tick_values,
  27. double t_step, int colorb, int colorbg, struct Option *opt_use,
  28. struct Option *opt_at, struct Option *opt_fontsize,
  29. struct Option *opt_tstep, struct Option *opt_range, struct Flag *histo,
  30. struct Flag *hidestr, int log_sc, int draw, int digits, char *units)
  31. {
  32. char buff[512];
  33. int black, white;
  34. int cats_num;
  35. int cur_dot_row;
  36. int do_cats;
  37. int dots_per_line;
  38. int i, j, k;
  39. double t, b, l, r;
  40. char *cstr;
  41. double x_box[5], y_box[5];
  42. struct Range range;
  43. struct FPRange fprange, render_range;
  44. CELL min_ind, max_ind;
  45. DCELL dmin, dmax, val;
  46. CELL min_colr, max_colr;
  47. DCELL min_dcolr, max_dcolr;
  48. int x0, x1, y0, y1, xyTemp;
  49. int SigDigits;
  50. unsigned int MaxLabelLen;
  51. char DispFormat[5]; /* %.Xf\0 */
  52. double maxCat;
  53. int horiz;
  54. char *units_bottom;
  55. double t_start;
  56. double max_hist;
  57. double txsiz, titsiz;
  58. int tcell;
  59. float ScaleFactor = 1.0;
  60. double x_tit, y_tit, x1_tit;
  61. double x0bg, y0bg, x1bg, y1bg;
  62. double wleg, lleg;
  63. int true_l, true_r;
  64. int dx, dy;
  65. double coef;
  66. double ppl;
  67. double bb,bt,bl,br;
  68. char MaxLabel[512];
  69. double num;
  70. int MaxLabelW, LabelW;
  71. if (draw) {
  72. /* init colors */
  73. black = D_translate_color(DEFAULT_FG_COLOR);
  74. white = D_translate_color(DEFAULT_BG_COLOR);
  75. }
  76. /* Figure out where to put text */
  77. D_setup_unity(0);
  78. D_get_src(&t, &b, &l, &r);
  79. x0 = l + (int)((r - l) * X0 / 100.);
  80. x1 = l + (int)((r - l) * X1 / 100.);
  81. y0 = t + (int)((b - t) * (100. - Y0) / 100.); /* make lower left the origin */
  82. y1 = t + (int)((b - t) * (100. - Y1) / 100.);
  83. if (y0 > y1) { /* allow for variety in order of corner */
  84. flip = !flip; /* selection without broken output */
  85. xyTemp = y0;
  86. y0 = y1;
  87. y1 = xyTemp;
  88. }
  89. if (x0 > x1) {
  90. xyTemp = x0;
  91. x0 = x1;
  92. x1 = xyTemp;
  93. }
  94. if (x0 == x1)
  95. x1++; /* avoid 0 width boxes */
  96. if (y0 == y1)
  97. y1++;
  98. if (draw) {
  99. if ((x0 < l) || (x1 > r) || (y0 < t) || (y1 > b)) /* for mouse or at= 0- or 100+; needs to be after order check */
  100. G_warning(_("Legend box lies outside of frame. Text may not display properly."));
  101. }
  102. horiz = (x1 - x0 > y1 - y0);
  103. if (horiz && draw)
  104. G_message(_("Drawing horizontal legend as box width exceeds height"));
  105. if (!fp && horiz) /* better than nothing */
  106. do_smooth = TRUE;
  107. MaxLabelLen = 0; /* init variable */
  108. MaxLabelW = 0;
  109. /* How many categories to show */
  110. /* not fp */
  111. if (!fp) {
  112. if (Rast_read_range(map_name, "", &range) == -1)
  113. G_fatal_error(_("Range information for <%s> not available (run r.support)"),
  114. map_name);
  115. Rast_get_range_min_max(&range, &min_ind, &max_ind);
  116. if (Rast_is_c_null_value(&min_ind))
  117. G_fatal_error(_("Input map contains no data"));
  118. Rast_get_c_color_range(&min_colr, &max_colr, &colors);
  119. if (UserRange) {
  120. if (min_ind < UserRangeMin)
  121. min_ind = (int)ceil(UserRangeMin);
  122. if (max_ind > UserRangeMax)
  123. max_ind = (int)floor(UserRangeMax);
  124. if (min_ind > UserRangeMin) {
  125. min_ind =
  126. UserRangeMin <
  127. min_colr ? min_colr : (int)ceil(UserRangeMin);
  128. if (draw)
  129. G_warning(_("Requested range exceeds lower limit of actual data"));
  130. }
  131. if (max_ind < UserRangeMax) {
  132. max_ind =
  133. UserRangeMax >
  134. max_colr ? max_colr : (int)floor(UserRangeMax);
  135. if (draw)
  136. G_warning(_("Requested range exceeds upper limit of actual data"));
  137. }
  138. }
  139. /* cats_num is total number of categories in raster */
  140. /* do_cats is total number of categories to be displayed */
  141. /* k is number of cats to be displayed after skipping unlabeled cats */
  142. /* lines is number of text lines/legend window */
  143. cats_num = max_ind - min_ind + 1;
  144. if (lines == 0)
  145. lines = cats_num;
  146. do_cats = cats_num > lines ? lines : cats_num;
  147. if (do_cats == cats_num)
  148. lines = (int)ceil((1.0 * lines) / thin);
  149. if (!use_catlist) {
  150. catlist = (double *)G_calloc(lines + 1, sizeof(double));
  151. catlistCount = lines;
  152. }
  153. /* see how many boxes there REALLY will be */
  154. maxCat = 0.0;
  155. for (i = min_ind, j = 1, k = 0; j <= do_cats && i <= max_ind;
  156. j++, i += thin) {
  157. if (!flip)
  158. cstr = Rast_get_c_cat(&i, &cats);
  159. else {
  160. CELL cat = max_ind - (i - min_ind);
  161. cstr = Rast_get_c_cat(&cat, &cats);
  162. }
  163. if (!use_catlist)
  164. catlist[j - 1] = (double)i;
  165. if (!cstr[0]) { /* no cat label found, skip str output */
  166. if (hide_nodata)
  167. continue;
  168. }
  169. else { /* ie has a label */
  170. if (!hide_catstr && (MaxLabelLen < strlen(cstr))) {
  171. MaxLabelLen = strlen(cstr);
  172. sprintf(MaxLabel, "%s", cstr);
  173. }
  174. }
  175. if (!hide_catnum)
  176. if (i > maxCat)
  177. maxCat = (double)i;
  178. k++; /* count of actual boxes drawn (hide_nodata option invaidates using j-1) */
  179. }
  180. lines = k;
  181. /* figure out how long the category + label will be */
  182. if (use_catlist) {
  183. MaxLabelLen = 0;
  184. maxCat = 0; /* reset */
  185. for (i = 0, k = 0; i < catlistCount; i++) {
  186. if ((catlist[i] < min_ind) || (catlist[i] > max_ind)) {
  187. G_fatal_error(_("use=%s out of range [%d,%d] (extend with range= ?)"),
  188. opt_use->answers[i], min_ind, max_ind);
  189. }
  190. cstr = Rast_get_d_cat(&catlist[i], &cats);
  191. if (!cstr[0]) { /* no cat label found, skip str output */
  192. if (hide_nodata)
  193. continue;
  194. }
  195. else { /* ie has a label */
  196. if (!hide_catstr && (MaxLabelLen < strlen(cstr)))
  197. MaxLabelLen = strlen(cstr);
  198. }
  199. if (!hide_catnum)
  200. if (catlist[i] > maxCat)
  201. maxCat = catlist[i];
  202. k++;
  203. }
  204. if (0 == k) /* nothing to draw */
  205. lines = 0;
  206. }
  207. /* following covers both the above if(do_cats == cats_num) and k++ loop */
  208. if (lines < 1) {
  209. lines = 1; /* ward off the dpl floating point exception */
  210. G_fatal_error(_("Nothing to draw! (no categories with labels? out of range?)"));
  211. }
  212. /* Figure number of lines, number of pixles per line and text size */
  213. dots_per_line = ((y1 - y0) / lines);
  214. /* switch to a smooth legend for CELL maps with too many cats */
  215. /* an alternate solution is to set dots_per_line=1 */
  216. if ((dots_per_line == 0) && (do_smooth == FALSE)) {
  217. if (!use_catlist) {
  218. if (draw)
  219. G_message(_("Forcing a smooth legend: too many categories for current window height"));
  220. do_smooth = TRUE;
  221. }
  222. }
  223. /* center really tiny legends */
  224. if (opt_at->answer == NULL) { /* if defualt scaling */
  225. if (!do_smooth && (dots_per_line < 4)) /* if so small that there's no box */
  226. if ((b - (dots_per_line * lines)) / (b * 1.0) > 0.15) /* if there's more than a 15% blank at the bottom */
  227. y0 = ((b - t) - (dots_per_line * lines)) / 2;
  228. }
  229. /* D_text_size(dots_per_line*4/5., dots_per_line*4/5.); redundant */
  230. /* if(Rast_is_c_null_value(&min_ind) && Rast_is_c_null_value(&max_ind))
  231. {
  232. min_ind = 1;
  233. max_ind = 0;
  234. } */
  235. if (horiz)
  236. sprintf(DispFormat, "%%d");
  237. else {
  238. if (maxCat > 0.0)
  239. sprintf(DispFormat, "%%%dd", (int)(log10(fabs(maxCat))) + 1);
  240. else
  241. sprintf(DispFormat, "%%2d");
  242. }
  243. } /* end of if(!fp) */
  244. else { /* is fp */
  245. if (maptype == MAP_TYPE_RASTER2D) {
  246. if (Rast_read_fp_range(map_name, "", &fprange) == -1)
  247. G_fatal_error(_("Range information for <%s> not available"),
  248. map_name);
  249. }
  250. else {
  251. if (Rast3d_read_range(map_name, "", &fprange) == -1)
  252. G_fatal_error(_("Range information for <%s> not available"),
  253. map_name);
  254. }
  255. Rast_get_fp_range_min_max(&fprange, &dmin, &dmax);
  256. Rast_get_d_color_range(&min_dcolr, &max_dcolr, &colors);
  257. if (UserRange) {
  258. if (dmin < UserRangeMin)
  259. dmin = UserRangeMin;
  260. if (dmax > UserRangeMax)
  261. dmax = UserRangeMax;
  262. if (dmin > UserRangeMin) {
  263. dmin = UserRangeMin < min_dcolr ? min_dcolr : UserRangeMin;
  264. G_warning(_("Color range exceeds lower limit of actual data"));
  265. }
  266. if (dmax < UserRangeMax) {
  267. dmax = UserRangeMax > max_dcolr ? max_dcolr : UserRangeMax;
  268. G_warning(_("Color range exceeds upper limit of actual data"));
  269. }
  270. }
  271. /* In case of log. scale raster doesn't contain negative or zero values */
  272. if (log_sc)
  273. if ((dmin<=0) || (dmax<=0))
  274. G_fatal_error(_("Range [%.3f, %.3f] out of the logarithm domain."),
  275. dmin, dmax);
  276. if (use_catlist) {
  277. for (i = 0; i < catlistCount; i++) {
  278. if ((catlist[i] < dmin) || (catlist[i] > dmax)) {
  279. G_fatal_error(_("use=%s out of range [%.3f, %.3f] (extend with range= ?)"),
  280. opt_use->answers[i], dmin, dmax);
  281. }
  282. if (strlen(opt_use->answers[i]) > MaxLabelLen)
  283. MaxLabelLen = strlen(opt_use->answers[i]);
  284. }
  285. }
  286. do_cats = 0; /* if only to get rid of the compiler warning */
  287. cats_num = 0; /* if only to get rid of the compiler warning */
  288. /* determine how many significant digits to display based on range */
  289. if (digits != -1) /* number of digits given by user */
  290. sprintf(DispFormat, "%%.%df", digits);
  291. else {/* automatic calculation */
  292. if (0 == (dmax - dmin)) /* trap divide by 0 for single value rasters */
  293. sprintf(DispFormat, "%%f");
  294. else {
  295. SigDigits = (int)ceil(log10(fabs(25 / (dmax - dmin))));
  296. if (SigDigits < 0)
  297. SigDigits = 0;
  298. if (SigDigits < 7)
  299. sprintf(DispFormat, "%%.%df", SigDigits);
  300. else
  301. sprintf(DispFormat, "%%.2g"); /* eg 4.2e-9 */
  302. }
  303. }
  304. } /* end of is fp */
  305. if (use_catlist) {
  306. cats_num = catlistCount;
  307. do_cats = catlistCount;
  308. lines = catlistCount;
  309. do_smooth = FALSE;
  310. }
  311. if (do_smooth) {
  312. if (horiz) {
  313. if (draw) {
  314. lleg = x1 - x0;
  315. dx = 0;
  316. dy = y1 - y0;
  317. }
  318. if (fp)
  319. flip = !flip; /* horiz floats look better not flipped by default */
  320. }
  321. else {
  322. if (draw) {
  323. lleg = y1 - y0;
  324. dy = 0;
  325. dx = x1 - x0;
  326. }
  327. }
  328. /* Draw colors */
  329. /* Draw the legend bar */
  330. if (draw) {
  331. for (k = 0; k < lleg; k++) {
  332. if (log_sc) { /* logarithmic scale */
  333. num = k / lleg;
  334. val = dmin * pow(dmax/dmin, num);
  335. D_d_color(val, &colors);
  336. if (!flip) {
  337. if (horiz)
  338. D_box_abs(x0 + k, y0, x0 + k + 1, y0 + dy);
  339. else
  340. D_box_abs(x0, y0 + k, x0 + dx, y0 + k + 1);
  341. }
  342. else {
  343. if (horiz)
  344. D_box_abs(x1 - k, y0, x1 - k - 1, y0 + dy);
  345. else
  346. D_box_abs(x0, y1 - k, x0 + dx, y1 - k - 1);
  347. }
  348. } /* linear scale */
  349. else{
  350. if (!fp) {
  351. if (!flip)
  352. tcell = min_ind + k * (double)(1 + max_ind - min_ind) / lleg;
  353. else
  354. tcell = (max_ind + 1) - k * (double)(1 + max_ind - min_ind) / lleg;
  355. D_color((CELL) tcell, &colors);
  356. }
  357. else {
  358. if (!flip)
  359. val = dmin + k / lleg * (dmax - dmin);
  360. else
  361. val = dmax - k / lleg * (dmax - dmin);
  362. D_d_color(val, &colors);
  363. }
  364. if (dx < dy)
  365. D_box_abs(x0 + k, y0, x0 + k + (dx ? -dx : 1),
  366. y0 - (dy ? -dy : 1));
  367. else
  368. D_box_abs(x0, y0 + k, x0 - (dx ? -dx : 1),
  369. y0 + k + (dy ? -dy : 1));
  370. }
  371. }
  372. }
  373. /* Format text */
  374. if (!fp) { /* cut down labelnum so they don't repeat */
  375. if (do_cats < steps)
  376. steps = do_cats;
  377. }
  378. /* Draw text and ticks */
  379. if (!horiz)
  380. txsiz = (y1 - y0) / 20;
  381. else
  382. txsiz = (x1 - x0) / 20;
  383. wleg = x1 - x0;
  384. lleg = y1 - y0;
  385. /* scale text to fit in window if position not manually set */
  386. /* usually not needed, except when frame is really narrow */
  387. if (opt_at->answer == NULL) { /* ie default scaling */
  388. ScaleFactor = ((r - x1) / ((MaxLabelLen + 1) * txsiz * 0.81)); /* ?? txsiz*.81=actual text width. */
  389. if (ScaleFactor < 1.0) {
  390. txsiz = txsiz * ScaleFactor;
  391. }
  392. }
  393. if (opt_fontsize->answer != NULL)
  394. txsiz = fontsize;
  395. if (txsiz < 0)
  396. txsiz = 0; /* keep it sane */
  397. if (tit_fontsize == 0)
  398. titsiz = txsiz;
  399. else
  400. titsiz = tit_fontsize;
  401. if (draw) {
  402. D_text_size(txsiz, txsiz);
  403. D_use_color(color);
  404. }
  405. /* Draw labels and ticks */
  406. /* LABELNUM OPTION */
  407. if (steps >= 2) {
  408. for (k = 0; k < steps; k++) {
  409. if (!fp) {
  410. if (!flip)
  411. tcell =
  412. min_ind + k * (double)(max_ind -
  413. min_ind) / (steps - 1);
  414. else
  415. tcell =
  416. max_ind - k * (double)(max_ind -
  417. min_ind) / (steps - 1);
  418. if (!cstr[0]) /* no cats found, disable str output */
  419. hide_catstr = 1;
  420. else
  421. hide_catstr = hidestr->answer;
  422. buff[0] = 0; /* blank string */
  423. if (!hide_catnum) { /* num */
  424. sprintf(buff, DispFormat, tcell);
  425. if (!hide_catstr) /* both */
  426. strcat(buff, ")");
  427. D_text_size(txsiz, txsiz);
  428. D_get_text_box(buff,&bb,&bt, &bl, &br);
  429. LabelW = br - bl;
  430. if (LabelW > MaxLabelW) {
  431. MaxLabelW = LabelW;
  432. sprintf(MaxLabel, "%s", buff);
  433. }
  434. }
  435. if (!hide_catstr) { /* str */
  436. sprintf(buff + strlen(buff), " %s", cstr);
  437. if (strlen(units)>0)
  438. strcat(buff, units);
  439. D_text_size(txsiz, txsiz);
  440. D_get_text_box(buff,&bb,&bt, &bl, &br);
  441. LabelW = br - bl;
  442. if (LabelW > MaxLabelW) {
  443. MaxLabelW = LabelW;
  444. sprintf(MaxLabel, "%s", buff);
  445. }
  446. }
  447. }
  448. else { /* ie FP map */
  449. if (hide_catnum)
  450. buff[0] = 0; /* no text */
  451. else {
  452. if (log_sc) {
  453. num = log10(dmax) - k * ((log10(dmax) - log10(dmin)) / (steps - 1));
  454. val = pow(10,num);
  455. }
  456. else{
  457. if (!flip)
  458. val = dmin + k * (dmax - dmin) / (steps - 1);
  459. else
  460. val = dmax - k * (dmax - dmin) / (steps - 1);
  461. }
  462. sprintf(buff, DispFormat, val);
  463. if (strlen(units)>0)
  464. strcat(buff, units);
  465. D_text_size(txsiz, txsiz);
  466. D_get_text_box(buff,&bb,&bt, &bl, &br);
  467. LabelW = br - bl;
  468. if (LabelW > MaxLabelW) {
  469. MaxLabelW = LabelW;
  470. sprintf(MaxLabel, "%s", buff);
  471. }
  472. }
  473. }
  474. if (draw) {
  475. if (!hide_catnum) {
  476. D_text_size(txsiz, txsiz);
  477. D_get_text_box(buff, &bb, &bt, &bl, &br);
  478. if (!horiz) {
  479. if (log_sc) {
  480. coef = (log10(val) - log10(dmin)) / (log10(dmax) - log10(dmin));
  481. if (flip)
  482. D_pos_abs(x1 + label_indent,
  483. y1 - coef * lleg + (bb - bt) / 2);
  484. else
  485. D_pos_abs(x1 + label_indent,
  486. y0 + coef * lleg + (bb - bt) / 2);
  487. }
  488. else {
  489. ppl = (lleg) / (steps * 1.0 - 1);
  490. D_pos_abs(x1 + label_indent,
  491. y0 + ppl * k + (bb - bt) / 2);
  492. }
  493. if (show_ticks) {
  494. D_use_color(black);
  495. if (log_sc)
  496. if (flip)
  497. D_line_abs(x1, y1 - coef * lleg,
  498. x1 + 6, y1 - coef * lleg);
  499. else
  500. D_line_abs(x1, y0 + coef * lleg,
  501. x1 + 6, y0 + coef * lleg);
  502. else
  503. D_line_abs(x1, y0 + ppl * k,
  504. x1 + 6, y0 + ppl * k);
  505. }
  506. }
  507. else {
  508. if (log_sc) {
  509. coef = (log10(val) - log10(dmin)) / (log10(dmax) - log10(dmin));
  510. if (flip)
  511. D_pos_abs(x1 - coef * wleg - ((br - bl) / 2),
  512. y1 + label_indent + txsiz);
  513. else
  514. D_pos_abs(x0 + coef * wleg - ((br - bl) / 2),
  515. y1 + label_indent + txsiz);
  516. }
  517. else {
  518. ppl = (wleg) / (steps * 1.0 - 1);
  519. D_pos_abs(x0 + ppl * k - ((br - bl) / 2),
  520. y1 + label_indent + txsiz);
  521. }
  522. if (show_ticks) {
  523. D_use_color(black);
  524. if (log_sc)
  525. if (flip)
  526. D_line_abs(x1 - coef * wleg, y1,
  527. x1 - coef * wleg, y1 + 6);
  528. else
  529. D_line_abs(x0 + coef * wleg, y1,
  530. x0 + coef * wleg, y1 + 6);
  531. else
  532. D_line_abs(x0 + ppl * k, y1,
  533. x0 + ppl * k, y1 + 6);
  534. }
  535. }
  536. if (color)
  537. D_use_color(color);
  538. D_text(buff);
  539. }
  540. }
  541. } /* for */
  542. }
  543. if (!fp) {
  544. dmin = min_ind;
  545. dmax = max_ind;
  546. sprintf(DispFormat, "%s", "%.0f");
  547. }
  548. /* LABEL_VALUE OPTION */
  549. if (ticksCount > 0) {
  550. for (i = 0; i < ticksCount; i++) {
  551. if ((tick_values[i] < dmin) || (tick_values[i] > dmax)) {
  552. G_fatal_error(_("tick_value=%.3f out of range [%.3f, %.3f]"),
  553. tick_values[i], dmin, dmax);
  554. }
  555. sprintf(buff, DispFormat, tick_values[i]);
  556. if (strlen(units)>0)
  557. strcat(buff, units);
  558. D_text_size(txsiz, txsiz);
  559. D_get_text_box(buff,&bb,&bt, &bl, &br);
  560. LabelW = br - bl;
  561. if (LabelW > MaxLabelW) {
  562. MaxLabelW = LabelW;
  563. sprintf(MaxLabel, "%s", buff);
  564. }
  565. if (log_sc) {
  566. coef = (log10(tick_values[i]) - log10(dmin)) / (log10(dmax) - log10(dmin));
  567. }
  568. else
  569. coef = (tick_values[i] - dmin) / ((dmax - dmin) * 1.0);
  570. if (draw) {
  571. if (!flip) {
  572. if (!horiz) {
  573. if (show_ticks) {
  574. D_use_color(black);
  575. D_line_abs(x1, y0 + coef * lleg,
  576. x1 + 6, y0 + coef * lleg);
  577. }
  578. D_pos_abs(x1 + label_indent,
  579. y0 + coef * lleg + txsiz / 2);
  580. }
  581. else {
  582. if (show_ticks) {
  583. D_use_color(black);
  584. D_line_abs(x0 + coef * wleg, y1,
  585. x0 + coef * wleg, y1 + 6);
  586. }
  587. D_pos_abs(x0 + coef * wleg -
  588. (strlen(buff) * txsiz * .81 / 2),
  589. y1 + label_indent + txsiz);
  590. }
  591. }
  592. else {
  593. if (!horiz) {
  594. if (show_ticks) {
  595. D_use_color(black);
  596. D_line_abs(x1, y1 - coef * lleg,
  597. x1 + 6, y1 - coef * lleg);
  598. }
  599. D_pos_abs(x1 + label_indent,
  600. y1 - coef * lleg + txsiz / 2);
  601. }
  602. else {
  603. if (show_ticks) {
  604. D_use_color(black);
  605. D_line_abs(x1 - coef * wleg, y1,
  606. x1 - coef * wleg, y1 + 6);
  607. }
  608. D_pos_abs(x1 - coef * wleg -
  609. (strlen(buff) * txsiz * .81 / 2),
  610. y1 + label_indent + txsiz);
  611. }
  612. }
  613. D_use_color(color);
  614. D_text(buff);
  615. }
  616. }
  617. }
  618. /* LABEL_STEP OPTION */
  619. if (opt_tstep->answer) {
  620. if (log_sc) { /* logarithmic */
  621. t_start=0;
  622. while (log10(dmin) + t_start < log10(dmax)){
  623. num = ceil(log10(dmin)) + t_start;
  624. val = pow(10,num);
  625. sprintf(buff, DispFormat, val);
  626. if (strlen(units)>0)
  627. strcat(buff, units);
  628. D_text_size(txsiz, txsiz);
  629. D_get_text_box(buff,&bb,&bt, &bl, &br);
  630. LabelW = br - bl;
  631. if (LabelW > MaxLabelW) {
  632. MaxLabelW = LabelW;
  633. sprintf(MaxLabel, "%s", buff);
  634. }
  635. coef = (log10(val) - log10(dmin)) / (log10(dmax) - log10(dmin));
  636. if (draw){
  637. if (!flip){
  638. if (!horiz){
  639. if (show_ticks) {
  640. D_use_color(black);
  641. D_line_abs(x1, y0 + coef * lleg,
  642. x1 + 6, y0 + coef * lleg);
  643. }
  644. D_pos_abs(x1 + label_indent,
  645. y0 + coef * lleg + txsiz / 2);
  646. }
  647. else{
  648. if (show_ticks) {
  649. D_use_color(black);
  650. D_line_abs(x0 + coef * wleg, y1,
  651. x0 + coef * wleg, y1 + 6);
  652. }
  653. D_pos_abs(x0 + coef * wleg -
  654. (strlen(buff) * txsiz * .81 / 2),
  655. y1 + label_indent + txsiz);
  656. }
  657. }
  658. else{
  659. if (!horiz){
  660. if (show_ticks) {
  661. D_use_color(black);
  662. D_line_abs(x1, y1 - coef * lleg,
  663. x1 + 6, y1 - coef * lleg);
  664. }
  665. D_pos_abs(x1 + label_indent,
  666. y1 - coef * lleg + txsiz / 2);
  667. }
  668. else{
  669. if (show_ticks){
  670. D_use_color(black);
  671. D_line_abs(x1 - coef * wleg, y1,
  672. x1 - coef * wleg, y1 + 6);
  673. }
  674. D_pos_abs(x1 - coef * wleg -
  675. (strlen(buff) * txsiz * .81 / 2),
  676. y1 + label_indent + txsiz);
  677. }
  678. }
  679. D_use_color(color);
  680. D_text(buff);
  681. }
  682. t_start += t_step;
  683. }
  684. }
  685. else { /* linear */
  686. t_start = ceil(dmin / t_step) * t_step;
  687. if (t_start == -0)
  688. t_start = 0;
  689. if (!flip) {
  690. if (!horiz)
  691. while (t_start <= dmax) {
  692. sprintf(buff, DispFormat, t_start);
  693. if (strlen(units)>0)
  694. strcat(buff, units);
  695. D_text_size(txsiz, txsiz);
  696. D_get_text_box(buff,&bb,&bt, &bl, &br);
  697. LabelW = br - bl;
  698. if (LabelW > MaxLabelW) {
  699. MaxLabelW = LabelW;
  700. sprintf(MaxLabel, "%s", buff);
  701. }
  702. if (draw) {
  703. coef = (t_start - dmin) / ((dmax - dmin) * 1.0);
  704. if (show_ticks) {
  705. D_use_color(black);
  706. D_line_abs(x1, y0 + coef * lleg,
  707. x1 + 6, y0 + coef * lleg);
  708. }
  709. D_pos_abs(x1 + label_indent,
  710. y0 + coef * lleg + txsiz / 2);
  711. D_use_color(color);
  712. D_text(buff);
  713. }
  714. t_start += t_step;
  715. }
  716. else
  717. while (t_start <= dmax) {
  718. sprintf(buff, DispFormat, t_start);
  719. if (strlen(units)>0)
  720. strcat(buff, units);
  721. D_text_size(txsiz, txsiz);
  722. D_get_text_box(buff,&bb,&bt, &bl, &br);
  723. LabelW = br - bl;
  724. if (LabelW > MaxLabelW) {
  725. MaxLabelW = LabelW;
  726. sprintf(MaxLabel, "%s", buff);
  727. }
  728. if (draw) {
  729. coef = (t_start - dmin) / ((dmax - dmin) * 1.0);
  730. if (show_ticks) {
  731. D_use_color(black);
  732. D_line_abs(x0 + coef * wleg, y1,
  733. x0 + coef * wleg, y1 + 6);
  734. }
  735. D_pos_abs(x0 + coef * wleg -
  736. (strlen(buff) * txsiz * .81 / 2),
  737. y1 + label_indent + txsiz);
  738. D_use_color(color);
  739. D_text(buff);
  740. }
  741. t_start += t_step;
  742. }
  743. }
  744. else {
  745. if (!horiz)
  746. while (t_start <= dmax) {
  747. sprintf(buff, DispFormat, t_start);
  748. if (strlen(units)>0)
  749. strcat(buff, units);
  750. D_text_size(txsiz, txsiz);
  751. D_get_text_box(buff,&bb,&bt, &bl, &br);
  752. LabelW = br - bl;
  753. if (LabelW > MaxLabelW) {
  754. MaxLabelW = LabelW;
  755. sprintf(MaxLabel, "%s", buff);
  756. }
  757. if (draw) {
  758. coef = (t_start - dmin) / ((dmax - dmin) * 1.0);
  759. if (show_ticks) {
  760. D_use_color(black);
  761. D_line_abs(x1, y1 - coef * lleg,
  762. x1 + 6, y1 - coef * lleg);
  763. }
  764. D_pos_abs(x1 + label_indent,
  765. y1 - coef * lleg + txsiz / 2);
  766. D_use_color(color);
  767. D_text(buff);
  768. }
  769. t_start += t_step;
  770. }
  771. else
  772. while (t_start <= dmax) {
  773. sprintf(buff, DispFormat, t_start);
  774. if (strlen(units)>0)
  775. strcat(buff, units);
  776. D_text_size(txsiz, txsiz);
  777. D_get_text_box(buff,&bb,&bt, &bl, &br);
  778. LabelW = br - bl;
  779. if (LabelW > MaxLabelW) {
  780. MaxLabelW = LabelW;
  781. sprintf(MaxLabel, "%s", buff);
  782. }
  783. if (draw) {
  784. coef = (t_start - dmin) / ((dmax - dmin) * 1.0);
  785. if (show_ticks){
  786. D_use_color(black);
  787. D_line_abs(x1 - coef * wleg, y1,
  788. x1 - coef * wleg, y1 + 6);
  789. }
  790. D_pos_abs(x1 - coef * wleg -
  791. (strlen(buff) * txsiz * .81 / 2),
  792. y1 + label_indent + txsiz);
  793. D_use_color(color);
  794. D_text(buff);
  795. }
  796. t_start += t_step;
  797. }
  798. }
  799. }
  800. }
  801. if (draw) {
  802. /* Draw boxes outside of legend bar */
  803. /* White box */
  804. D_use_color(white);
  805. D_begin();
  806. D_move_abs(x0 + 1, y0 + 1);
  807. D_cont_rel(0, lleg - 2);
  808. D_cont_rel(wleg - 2, 0);
  809. D_cont_rel(0, -lleg + 2);
  810. D_close();
  811. D_end();
  812. D_stroke();
  813. /* Black box */
  814. D_use_color(black);
  815. D_begin();
  816. D_move_abs(x0, y0);
  817. D_cont_rel(0, lleg);
  818. D_cont_rel(wleg, 0);
  819. D_cont_rel(0, -lleg);
  820. D_close();
  821. D_end();
  822. D_stroke();
  823. }
  824. /* Display sidebar histogram, if requested.
  825. / In case of horizontal legend, maximum of histogram - max_hist
  826. will efect the title position */
  827. max_hist = 0;
  828. if (histo->answer) {
  829. render_range.min = (DCELL) (fp ? dmin : min_ind);
  830. render_range.max = (DCELL) (fp ? dmax : max_ind);
  831. /* reuse flag to indicate if user-specified or default ranging */
  832. render_range.first_time = opt_range->answer ? TRUE : FALSE;
  833. if (draw)
  834. max_hist =
  835. histogram(map_name, x0, y0, wleg, lleg, color, flip,
  836. horiz, maptype, fp, render_range, 1);
  837. else
  838. max_hist =
  839. histogram(map_name, x0, y0, wleg, lleg, color, flip,
  840. horiz, maptype, fp, render_range, 0);
  841. }
  842. /* display title or units */
  843. if (strlen(title) > 0) {
  844. D_text_size(titsiz, titsiz);
  845. D_get_text_box(title, &bb, &bt, &bl, &br);
  846. /* title */
  847. if (horiz) {
  848. x_tit = (x0 + x1) / 2. - (br - bl) / 2;
  849. y_tit = y0 - (titsiz) - max_hist;
  850. }
  851. else {
  852. x_tit = x0;
  853. y_tit = y0 - txsiz;
  854. }
  855. x1_tit = x_tit + (br - bl);
  856. if (draw) {
  857. D_use_color(color);
  858. /* use tit_fontsize */
  859. D_text_size(titsiz, titsiz);
  860. D_pos_abs(x_tit, y_tit);
  861. D_text(title);
  862. /* restart fontsize */
  863. D_text_size(txsiz, txsiz);
  864. }
  865. }
  866. else {
  867. /* units */
  868. /* print units label, if present */
  869. if (maptype == MAP_TYPE_RASTER2D)
  870. units_bottom = Rast_read_units(map_name, "");
  871. else
  872. units = "";
  873. /* FIXME: does the raster3d really need to be opened to read the units?
  874. units_bottom = Rast3d_get_unit(map_fid); */
  875. if (!units_bottom)
  876. units_bottom = "";
  877. if (strlen(units_bottom)) {
  878. D_text_size(titsiz, titsiz);
  879. D_get_text_box(title, &bb, &bt, &bl, &br);
  880. if (horiz) {
  881. x_tit =
  882. (x0 + x1) / 2. - (br - bl) / 2;
  883. y_tit = y1 + (txsiz * 2.75);
  884. }
  885. else {
  886. x_tit = x0;
  887. }
  888. x1_tit = x_tit + (br - bl);
  889. if (draw) {
  890. D_use_color(color);
  891. D_pos_abs(x_tit, y_tit);
  892. D_text(units_bottom);
  893. }
  894. }
  895. } /* end of display units) */
  896. if (!draw) {
  897. /* Draw background */
  898. D_text_size(txsiz, txsiz);
  899. D_get_text_box(MaxLabel, &bb, &bt, &bl, &br);
  900. if (!horiz) {
  901. x0bg = x0 - max_hist - txsiz;
  902. x1bg = x0 + wleg + label_indent + (br - bl) + txsiz;
  903. if (x1bg < x1_tit)
  904. x1bg = x1_tit + txsiz;
  905. y1bg = y0 + lleg + txsiz;
  906. if (strlen(title) > 0)
  907. y0bg = y0 - titsiz -2 * txsiz;
  908. else
  909. y0bg = y0 - txsiz;
  910. }
  911. else {
  912. x0bg = x0 - (br - bl) / 2 - txsiz;
  913. x1bg = x0 + wleg + (br - bl) / 2 + txsiz;
  914. if (x1bg < x1_tit) {
  915. x0bg = x_tit - txsiz;
  916. x1bg = x1_tit + txsiz;
  917. }
  918. y1bg = y0 + lleg + label_indent + 1.5 * txsiz;
  919. if (strlen(title) > 0)
  920. y0bg = y0 - (2.5 * titsiz) - max_hist;
  921. else
  922. y0bg = y0 - titsiz - max_hist;
  923. }
  924. if (colorbg != 0) {
  925. D_use_color(colorbg);
  926. D_box_abs(x0bg, y0bg, x1bg, y1bg);
  927. }
  928. D_use_color(colorb);
  929. D_begin();
  930. D_move_abs(x0bg, y0bg);
  931. D_cont_abs(x0bg, y1bg);
  932. D_cont_abs(x1bg, y1bg);
  933. D_cont_abs(x1bg, y0bg);
  934. D_close();
  935. D_end();
  936. D_stroke();
  937. }
  938. } /* end of if(do_smooth) */
  939. else { /* non FP, no smoothing */
  940. ScaleFactor = 1.0;
  941. if (histo->answer)
  942. G_warning(_("Histogram plotting not implemented for categorical legends. "
  943. "Use the '-s' flag"));
  944. /* set legend box bounds */
  945. true_l = l;
  946. true_r = r; /* preserve window width */
  947. l = x0;
  948. t = y0;
  949. r = x1;
  950. b = y1;
  951. /* figure out box height */
  952. if (do_cats == cats_num)
  953. dots_per_line = (b - t) / (lines + 1); /* +1 line for the two 1/2s at top and bottom */
  954. else
  955. dots_per_line = (b - t) / (lines + 2); /* + another line for 'x of y categories' text */
  956. /* adjust text size */
  957. /* txsiz = (int)((y1-y0)/(1.5*(lines+5))); */
  958. txsiz = (y1 - y0) / (2.0 * lines);
  959. if (tit_fontsize == 0)
  960. titsiz = txsiz;
  961. else
  962. titsiz = tit_fontsize;
  963. /* scale text to fit in window if position not manually set */
  964. if (opt_at->answer == NULL) { /* ie defualt scaling */
  965. ScaleFactor = ((true_r - true_l) / ((MaxLabelLen + 3) * txsiz * 0.81)); /* ?? txsiz*.81=actual text width. */
  966. if (ScaleFactor < 1.0) {
  967. txsiz = txsiz * ScaleFactor;
  968. dots_per_line = (int)floor(dots_per_line * ScaleFactor);
  969. }
  970. }
  971. if (dots_per_line < txsiz)
  972. txsiz = dots_per_line;
  973. if (opt_fontsize->answer != NULL)
  974. txsiz = fontsize;
  975. /* Set up box arrays */
  976. x_box[0] = 0;
  977. y_box[0] = 0;
  978. x_box[1] = 0;
  979. y_box[1] = (5 - dots_per_line);
  980. x_box[2] = (dots_per_line - 5);
  981. y_box[2] = 0;
  982. x_box[3] = 0;
  983. y_box[3] = (dots_per_line - 5);
  984. x_box[4] = (5 - dots_per_line);
  985. y_box[4] = 0;
  986. /* Draw away */
  987. /* if(ScaleFactor < 1.0) */
  988. /* cur_dot_row = ((b-t) - (dots_per_line*lines))/2; *//* this will center the legend */
  989. /* else */
  990. cur_dot_row = t + dots_per_line / 2;
  991. /* j = (do_cats == cats_num ? 1 : 2 ); */
  992. if (draw) {
  993. D_pos_abs(x0, y0);
  994. D_text_size(txsiz, txsiz);
  995. }
  996. for (i = 0, k = 0; i < catlistCount; i++)
  997. /* for(i=min_ind, j=1, k=0; j<=do_cats && i<=max_ind; j++, i+=thin) */
  998. {
  999. if (!flip)
  1000. cstr = Rast_get_d_cat(&catlist[i], &cats);
  1001. else
  1002. cstr = Rast_get_d_cat(&catlist[catlistCount - i - 1], &cats);
  1003. if (!cstr[0]) { /* no cat label found, skip str output */
  1004. hide_catstr = 1;
  1005. if (hide_nodata)
  1006. continue;
  1007. }
  1008. else
  1009. hide_catstr = hidestr->answer;
  1010. k++; /* count of actual boxes drawn (hide_nodata option invaidates using j-1) */
  1011. cur_dot_row += dots_per_line;
  1012. if (draw) {
  1013. /* Black box */
  1014. D_use_color(black);
  1015. D_begin();
  1016. D_move_abs(l + 2, (cur_dot_row - 1));
  1017. D_cont_rel(0, (3 - dots_per_line));
  1018. D_cont_rel((dots_per_line - 3), 0);
  1019. D_cont_rel(0, (dots_per_line - 3));
  1020. D_close();
  1021. D_end();
  1022. D_stroke();
  1023. /* White box */
  1024. D_use_color(white);
  1025. D_begin();
  1026. D_move_abs(l + 3, (cur_dot_row - 2));
  1027. D_cont_rel(0, (5 - dots_per_line));
  1028. D_cont_rel((dots_per_line - 5), 0);
  1029. D_cont_rel(0, (dots_per_line - 5));
  1030. D_close();
  1031. D_end();
  1032. D_stroke();
  1033. /* Color solid box */
  1034. if (!fp) {
  1035. if (!flip)
  1036. D_color((CELL) (int)catlist[i], &colors);
  1037. else
  1038. D_color((CELL) (int)catlist[catlistCount - i - 1],
  1039. &colors);
  1040. }
  1041. else {
  1042. if (!flip)
  1043. D_d_color(catlist[i], &colors);
  1044. else
  1045. D_d_color(catlist[catlistCount - i - 1], &colors);
  1046. }
  1047. D_pos_abs(l + 3, (cur_dot_row - 2));
  1048. D_polygon_rel(x_box, y_box, 5);
  1049. /* Draw text */
  1050. D_use_color(color);
  1051. }
  1052. if (!fp) {
  1053. /* nothing, box only */
  1054. buff[0] = 0;
  1055. if (!hide_catnum) { /* num */
  1056. sprintf(buff, DispFormat, (int)catlist[i]);
  1057. if (strlen(units)>0)
  1058. strcat(buff, units);
  1059. D_text_size(txsiz, txsiz);
  1060. D_get_text_box(buff,&bb,&bt, &bl, &br);
  1061. LabelW = br - bl;
  1062. if (LabelW > MaxLabelW) {
  1063. MaxLabelW = LabelW;
  1064. sprintf(MaxLabel, "%s", buff);
  1065. }
  1066. if (!flip) {
  1067. sprintf(buff, DispFormat, (int)catlist[i]);
  1068. if (strlen(units)>0)
  1069. strcat(buff, units);
  1070. D_text_size(txsiz, txsiz);
  1071. D_get_text_box(buff,&bb,&bt, &bl, &br);
  1072. LabelW = br - bl;
  1073. if (LabelW > MaxLabelW) {
  1074. MaxLabelW = LabelW;
  1075. sprintf(MaxLabel, "%s", buff);
  1076. }
  1077. }
  1078. else {
  1079. sprintf(buff, DispFormat,
  1080. (int)catlist[catlistCount - i - 1]);
  1081. if (strlen(units)>0)
  1082. strcat(buff, units);
  1083. D_text_size(txsiz, txsiz);
  1084. D_get_text_box(buff,&bb,&bt, &bl, &br);
  1085. LabelW = br - bl;
  1086. if (LabelW > MaxLabelW) {
  1087. MaxLabelW = LabelW;
  1088. sprintf(MaxLabel, "%s", buff);
  1089. }
  1090. }
  1091. if (!hide_catstr) /* both */
  1092. strcat(buff, ")");
  1093. }
  1094. if (!hide_catstr) { /* str */
  1095. sprintf(buff + strlen(buff), " %s", cstr);
  1096. if (strlen(units)>0)
  1097. strcat(buff, units);
  1098. D_text_size(txsiz, txsiz);
  1099. D_get_text_box(buff,&bb,&bt, &bl, &br);
  1100. LabelW = br - bl;
  1101. if (LabelW > MaxLabelW) {
  1102. MaxLabelW = LabelW;
  1103. sprintf(MaxLabel, " %s", buff);
  1104. }
  1105. }
  1106. }
  1107. else { /* is fp */
  1108. if (!flip) {
  1109. if (use_catlist) {
  1110. /* pass through format exactly as given by the user in
  1111. the use= command line parameter (helps with log scale) */
  1112. sprintf(buff, "%s", opt_use->answers[i]);
  1113. if (strlen(units)>0)
  1114. strcat(buff, units);
  1115. D_text_size(txsiz, txsiz);
  1116. D_get_text_box(buff,&bb,&bt, &bl, &br);
  1117. LabelW = br - bl;
  1118. if (LabelW > MaxLabelW) {
  1119. MaxLabelW = LabelW;
  1120. sprintf(MaxLabel, " %s", buff);
  1121. }
  1122. }
  1123. else {
  1124. /* automatically generated/tuned decimal precision format */
  1125. sprintf(buff, DispFormat, catlist[i]);
  1126. if (strlen(units)>0)
  1127. strcat(buff, units);
  1128. D_text_size(txsiz, txsiz);
  1129. D_get_text_box(buff,&bb,&bt, &bl, &br);
  1130. LabelW = br - bl;
  1131. if (LabelW > MaxLabelW) {
  1132. MaxLabelW = LabelW;
  1133. sprintf(MaxLabel, "%s", buff);
  1134. }
  1135. }
  1136. }
  1137. else {
  1138. if (use_catlist){
  1139. sprintf(buff, "%s", opt_use->answers[catlistCount - i - 1]);
  1140. if (strlen(units)>0)
  1141. strcat(buff, units);
  1142. D_text_size(txsiz, txsiz);
  1143. D_get_text_box(buff,&bb,&bt, &bl, &br);
  1144. LabelW = br - bl;
  1145. if (LabelW > MaxLabelW) {
  1146. MaxLabelW = LabelW;
  1147. sprintf(MaxLabel, " %s", buff);
  1148. }
  1149. }
  1150. else {
  1151. sprintf(buff, DispFormat, catlist[catlistCount - i - 1]);
  1152. if (strlen(units)>0)
  1153. strcat(buff, units);
  1154. D_text_size(txsiz, txsiz);
  1155. D_get_text_box(buff,&bb,&bt, &bl, &br);
  1156. LabelW = br - bl;
  1157. if (LabelW > MaxLabelW) {
  1158. MaxLabelW = LabelW;
  1159. sprintf(MaxLabel, " %s", buff);
  1160. }
  1161. }
  1162. }
  1163. }
  1164. if (draw) {
  1165. D_pos_abs((l + 3 + dots_per_line), (cur_dot_row) - 3);
  1166. if (color)
  1167. D_text(buff);
  1168. }
  1169. }
  1170. if (0 == k)
  1171. G_fatal_error(_("Nothing to draw! (no categories with labels?)")); /* "(..., out of range?)" */
  1172. /* display title */
  1173. if (strlen(title) > 0) {
  1174. x_tit = x0;
  1175. y_tit = y0 - txsiz;
  1176. D_text_size(titsiz, titsiz);
  1177. D_get_text_box(title, &bb, &bt, &bl, &br);
  1178. x1_tit = x_tit + (br - bl);
  1179. if (draw) {
  1180. D_use_color(color);
  1181. /* use tit_fontsize */
  1182. D_text_size(titsiz, titsiz);
  1183. D_pos_abs(x_tit, y_tit);
  1184. D_text(title);
  1185. /* restart fontsize */
  1186. D_text_size(txsiz, txsiz);
  1187. }
  1188. }
  1189. /* Display info line about numbers of categories */
  1190. if (do_cats != cats_num) {
  1191. cur_dot_row += dots_per_line;
  1192. /* sprintf(buff, "%d of %d categories\n", (j-1), cats_num); */
  1193. sprintf(buff, "%d of %d categories\n", k, cats_num);
  1194. if (strlen(buff) > MaxLabelLen) {
  1195. MaxLabelLen = strlen(buff);
  1196. sprintf(MaxLabel, "%d of %d categories\n", k, cats_num);
  1197. }
  1198. if (draw) {
  1199. if (opt_fontsize->answer != NULL)
  1200. txsiz = fontsize;
  1201. D_text_size(txsiz, txsiz);
  1202. D_use_color(black);
  1203. D_pos_abs((l + 3 + dots_per_line), (cur_dot_row));
  1204. if (color)
  1205. D_text(buff);
  1206. }
  1207. }
  1208. if (!draw) {
  1209. /* Draw background */
  1210. D_text_size(txsiz, txsiz);
  1211. D_get_text_box(MaxLabel, &bb, &bt, &bl, &br);
  1212. x0bg = x0 - txsiz;
  1213. x1bg =
  1214. x0 + dots_per_line + 3 + (br - bl) + txsiz;
  1215. if (x1bg < x1_tit)
  1216. x1bg = x1_tit + txsiz;
  1217. y1bg = cur_dot_row + txsiz;
  1218. if (strlen(title) > 0)
  1219. y0bg = y0 - 2 * txsiz - titsiz;
  1220. else
  1221. y0bg = y0 - txsiz;
  1222. if (colorbg != 0) {
  1223. D_use_color(colorbg);
  1224. D_box_abs(x0bg, y0bg, x1bg, y1bg);
  1225. }
  1226. D_use_color(colorb);
  1227. D_begin();
  1228. D_move_abs(x0bg, y0bg);
  1229. D_cont_abs(x0bg, y1bg);
  1230. D_cont_abs(x1bg, y1bg);
  1231. D_cont_abs(x1bg, y0bg);
  1232. D_close();
  1233. D_end();
  1234. D_stroke();
  1235. }
  1236. }
  1237. D_save_command(G_recreate_command());
  1238. }