ps_clrtbl.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. /* Function: ps_colortable
  2. **
  3. ** Author: Paul W. Carlson April 1992
  4. */
  5. #include <grass/raster.h>
  6. #include <grass/glocale.h>
  7. #include "colortable.h"
  8. #include "local_proto.h"
  9. #define NSTEPS 5 /* number of steps to divide color box when
  10. showing color for category data range */
  11. #define FONTFIT_FACT 4.0 /* how agressive to be with shrinking the font size
  12. to get it to fit in the column (normal range: 2-4) */
  13. #define PRETEXT_MULT 2.0 /* space between box and text (this*fontsize) */
  14. int PS_colortable(void)
  15. {
  16. char *label;
  17. int num_cats;
  18. int i, j, k, jj;
  19. int R, G, B;
  20. int center_cols;
  21. DCELL dmin, dmax, val;
  22. struct Colors colors;
  23. double t, l /*, r */;
  24. double x1, x2, y, dy, fontsize, tl;
  25. double col_width;
  26. int do_color;
  27. double grey_color_val;
  28. RASTER_MAP_TYPE rast_type;
  29. /* let user know what's happenning */
  30. G_message(_("Creating color table for <%s in %s>..."),
  31. ct.name, ct.mapset);
  32. if (Rast_read_cats(ct.name, ct.mapset, &PS.cats) == -1) {
  33. G_warning(_("Category file for <%s> not available"), ct.name);
  34. return 1;
  35. }
  36. if (Rast_read_colors(ct.name, ct.mapset, &colors) == -1)
  37. G_warning(_("Unable to read colors for colorbar"));
  38. rast_type = Rast_map_type(ct.name, ct.mapset);
  39. do_color = (PS.grey == 0 && PS.level == 2);
  40. /* How many categories to show */
  41. num_cats = Rast_number_of_cats(&PS.cats);
  42. G_debug(3, "clrtbl: %d categories", num_cats);
  43. if (!num_cats) {
  44. G_warning(_("Your cats/ file is invalid. A cats/ file with categories "
  45. "and labels is required for 'colortable' when using "
  46. "categorical legends; see the r.category help page. "
  47. "Colortable creation has been skipped."));
  48. return 1;
  49. }
  50. /* set font */
  51. fontsize = (double)ct.fontsize;
  52. fprintf(PS.fp, "(%s) FN %.1f SF\n", ct.font, fontsize);
  53. /* set colortable location */
  54. dy = 1.5 * fontsize;
  55. if (ct.y < PS.top_marg) {
  56. G_warning(_("Colorbar y location beyond page margins. Adjusting."));
  57. ct.y = PS.top_marg;
  58. }
  59. t = 72.0 * (PS.page_height - ct.y);
  60. if (ct.x < PS.left_marg) {
  61. G_warning(_("Colorbar x location beyond page margins. Adjusting."));
  62. ct.x = PS.left_marg + 0.1;
  63. }
  64. l = 72.0 * ct.x + 0.5;
  65. if (ct.width <= 0.0 || ct.width > PS.page_width - PS.right_marg - ct.x)
  66. ct.width = PS.page_width - PS.right_marg - ct.x;
  67. /* r = l + 72.0 * ct.width; */ /* unused */
  68. col_width = ct.width / (double)ct.cols;
  69. G_debug(3, "clrtbl: adjusted ct.x=[%.3f] ct.y=[%.3f] ct.width=[%.3f] "
  70. "col_width=[%.3f]", ct.x, ct.y, ct.width, col_width);
  71. /* read cats into PostScript array "a" */
  72. fprintf(PS.fp, "/a [\n");
  73. for (i = 0; i <= num_cats; i++) {
  74. if (!i && !ct.nodata)
  75. i++; /* step over 'no data' */
  76. if (!i)
  77. fprintf(PS.fp, "(%s)\n", "no data");
  78. else {
  79. fprintf(PS.fp, "(%s)\n",
  80. Rast_get_ith_d_cat(&PS.cats, i - 1, &dmin, &dmax));
  81. G_debug(5, "i=%d dmin=%f dmax=%f catlabel=[%s]", i, dmin, dmax,
  82. Rast_get_ith_d_cat(&PS.cats, i - 1, &dmin, &dmax));
  83. }
  84. }
  85. fprintf(PS.fp, "] def\n");
  86. /* get width of widest string in PostScript variable "mw" */
  87. fprintf(PS.fp, "/mw 0 def 0 1 a length 1 sub { /i XD\n");
  88. fprintf(PS.fp, "a i get SW pop /t XD t mw gt {/mw t def} if } for\n");
  89. /* shrink font size to fit in width */
  90. if (ct.cols == 1)
  91. tl = 72.0 * col_width - 2.0 * fontsize;
  92. else
  93. tl = 72.0 * col_width - FONTFIT_FACT * fontsize;
  94. G_debug(5, "clrtbl: fontsize=%.1f adjusted tl=%.1f", fontsize, tl);
  95. fprintf(PS.fp, "/s %.1f def\n", fontsize);
  96. fprintf(PS.fp, "mw %.1f gt {/s s %.1f mul mw div def } if\n", tl, tl);
  97. fprintf(PS.fp, "(%s) FN s SF\n", ct.font);
  98. /* make proc to center multiple columns */
  99. center_cols = (ct.cols > 1);
  100. if (center_cols) {
  101. fprintf(PS.fp, "/k %d def\n", ct.cols - 1);
  102. fprintf(PS.fp, "/mlw 0 def 0 k a length 1 sub { /i XD\n");
  103. fprintf(PS.fp,
  104. "a i get SW pop /t XD t mlw gt {/mlw t def} if } for\n");
  105. fprintf(PS.fp, "/xo mw mlw sub D2 s mul %1.0f div %1.0f add def\n",
  106. fontsize, fontsize);
  107. fprintf(PS.fp, "/mvx {xo add} BD\n");
  108. }
  109. y = t - fontsize;
  110. k = 0;
  111. for (i = 0; i <= num_cats;) {
  112. if (!i && !ct.nodata)
  113. i++; /* step over 'no data' */
  114. /* test for bottom of page */
  115. y -= dy;
  116. if (y < 72.0 * PS.bot_marg) {
  117. y = 72.0 * (PS.page_height - PS.top_marg) - 0.5 * fontsize;
  118. fprintf(PS.fp, "showpage\n");
  119. }
  120. for (j = 0; j < ct.cols; j++) {
  121. /* get the data range */
  122. /* fill box and outline in black */
  123. if (i) {
  124. label = Rast_get_ith_d_cat(&PS.cats, i - 1, &dmin, &dmax);
  125. G_debug(5, "j=%d i=%d label=[%s]", j, i, label);
  126. }
  127. x1 = l + (double)j *72.0 * col_width;
  128. x2 = x1 + fontsize;
  129. if (!i || dmax == dmin) {
  130. /* draw a 1-color rectangle */
  131. /* set box fill color */
  132. if (!i)
  133. Rast_get_null_value_color(&R, &G, &B, &colors);
  134. else {
  135. if (rast_type == CELL_TYPE) {
  136. CELL cmin = (CELL)dmin;
  137. Rast_get_c_color(&cmin, &R, &G, &B, &colors);
  138. }
  139. else if (rast_type == FCELL_TYPE) {
  140. FCELL fmin = (FCELL)dmin;
  141. Rast_get_f_color(&fmin, &R, &G, &B, &colors);
  142. }
  143. else if (rast_type == DCELL_TYPE)
  144. Rast_get_color(&dmin, &R, &G, &B, &colors, rast_type);
  145. else G_fatal_error("Please contact development team");
  146. G_debug(5, " dmin=%f RGB=%d:%d:%d", dmin, R, G, B);
  147. }
  148. if (do_color)
  149. fprintf(PS.fp, "%.3f %.3f %.3f C\n",
  150. (double)R / 255., (double)G / 255.,
  151. (double)B / 255.);
  152. else {
  153. grey_color_val =
  154. (.3 * (double)R + .59 * (double)G +
  155. .11 * (double)B) / 255.;
  156. fprintf(PS.fp, "%.3f setgray\n", grey_color_val);
  157. }
  158. fprintf(PS.fp, "%.1f ", x1);
  159. if (center_cols)
  160. fprintf(PS.fp, "mvx ");
  161. fprintf(PS.fp, "%.1f ", y);
  162. fprintf(PS.fp, "%.1f ", x2);
  163. if (center_cols)
  164. fprintf(PS.fp, "mvx ");
  165. fprintf(PS.fp, "%.1f ", y + fontsize);
  166. /* no border fprintf(PS.fp, "B CF stroke\n"); */
  167. /* grey border fprintf(PS.fp, "B F .247 .247 .247 C 1 W stroke\n"); */
  168. fprintf(PS.fp, "B F ");
  169. set_ps_color(&ct.color);
  170. fprintf(PS.fp, "%.2f W stroke\n", ct.lwidth);
  171. }
  172. else {
  173. /* split the rectangle into NSTEPS horizontal strips and
  174. draw each with the corresponding value's color */
  175. for (jj = 0; jj < NSTEPS; jj++) {
  176. /* set box fill color */
  177. val = dmin + (double)jj *(dmax - dmin) / NSTEPS;
  178. Rast_get_d_color(&val, &R, &G, &B, &colors);
  179. fprintf(PS.fp, "%.3f %.3f %.3f C\n",
  180. (double)R / 255., (double)G / 255.,
  181. (double)B / 255.);
  182. fprintf(PS.fp, "%.1f ", x1);
  183. if (center_cols)
  184. fprintf(PS.fp, "mvx ");
  185. fprintf(PS.fp, "%.1f ",
  186. y + (fontsize * (double)jj) / NSTEPS);
  187. fprintf(PS.fp, "%.1f ", x2);
  188. if (center_cols)
  189. fprintf(PS.fp, "mvx ");
  190. fprintf(PS.fp, "%.1f ",
  191. y + (fontsize * (double)(jj + 1)) / NSTEPS);
  192. fprintf(PS.fp, "B CF stroke\n");
  193. } /* done filling the box */
  194. /* outline the box in the specified color, see above */
  195. fprintf(PS.fp, "%.1f ", x1);
  196. if (center_cols)
  197. fprintf(PS.fp, "mvx ");
  198. fprintf(PS.fp, "%.1f ", y);
  199. fprintf(PS.fp, "%.1f ", x2);
  200. if (center_cols)
  201. fprintf(PS.fp, "mvx ");
  202. fprintf(PS.fp, "%.1f ", y + fontsize);
  203. fprintf(PS.fp, "B ");
  204. set_ps_color(&ct.color);
  205. fprintf(PS.fp, "%.2f W stroke\n", ct.lwidth);
  206. } /* done drawing the box */
  207. /* do the text */
  208. set_ps_color(&ct.color);
  209. fprintf(PS.fp, "a %d get %.1f ", k++, x1 + PRETEXT_MULT * fontsize);
  210. if (center_cols)
  211. fprintf(PS.fp, "mvx ");
  212. fprintf(PS.fp, "%.1f MS\n", y);
  213. i++;
  214. if (i > num_cats)
  215. j = ct.cols + 1;
  216. }
  217. }
  218. y -= dy;
  219. if (PS.min_y > y)
  220. PS.min_y = y;
  221. Rast_free_colors(&colors);
  222. return 0;
  223. }