g_miscmi.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /* This file is part of the GNU plotutils package. Copyright (C) 1995,
  2. 1996, 1997, 1998, 1999, 2000, 2005, 2008, Free Software Foundation, Inc.
  3. The GNU plotutils package is free software. You may redistribute it
  4. and/or modify it under the terms of the GNU General Public License as
  5. published by the Free Software foundation; either version 2, or (at your
  6. option) any later version.
  7. The GNU plotutils package is distributed in the hope that it will be
  8. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. General Public License for more details.
  11. You should have received a copy of the GNU General Public License along
  12. with the GNU plotutils package; see the file COPYING. If not, write to
  13. the Free Software Foundation, Inc., 51 Franklin St., Fifth Floor,
  14. Boston, MA 02110-1301, USA. */
  15. /* This file contains a function called by Bitmap Plotters (including PNM
  16. Plotters), and GIF Plotters, just before drawing. It sets the
  17. attributes in the graphics context (of type `miGC') used by the libxmi
  18. scan conversion routines. */
  19. #include "sys-defines.h"
  20. #include "extern.h"
  21. #include "xmi.h" /* use libxmi scan conversion module */
  22. /* libxmi joinstyles, indexed by internal number (miter/rd./bevel/triangular)*/
  23. static const int mi_join_style[] =
  24. { MI_JOIN_MITER, MI_JOIN_ROUND, MI_JOIN_BEVEL, MI_JOIN_TRIANGULAR };
  25. /* libxmi capstyles, indexed by internal number (butt/rd./project/triangular)*/
  26. static const int mi_cap_style[] =
  27. { MI_CAP_BUTT, MI_CAP_ROUND, MI_CAP_PROJECTING, MI_CAP_TRIANGULAR };
  28. void
  29. _set_common_mi_attributes (plDrawState *drawstate, void * ptr)
  30. {
  31. int line_style, num_dashes, offset;
  32. unsigned int *dashbuf;
  33. bool dash_array_allocated = false;
  34. miGCAttribute attributes[5];
  35. int values [5];
  36. unsigned int local_dashbuf[PL_MAX_DASH_ARRAY_LEN];
  37. miGC *pGC;
  38. pGC = (miGC *)ptr; /* recover passed libxmi GC */
  39. /* set all miGC attributes that are not dash related */
  40. /* set five integer-valued miGC attributes */
  41. attributes[0] = MI_GC_FILL_RULE;
  42. values[0] = (drawstate->fill_rule_type == PL_FILL_NONZERO_WINDING ?
  43. MI_WINDING_RULE : MI_EVEN_ODD_RULE);
  44. attributes[1] = MI_GC_JOIN_STYLE;
  45. values[1] = mi_join_style[drawstate->join_type];
  46. attributes[2] = MI_GC_CAP_STYLE;
  47. values[2] = mi_cap_style[drawstate->cap_type];
  48. attributes[3] = MI_GC_ARC_MODE;
  49. values[3] = MI_ARC_CHORD; /* libplot convention */
  50. attributes[4] = MI_GC_LINE_WIDTH;
  51. values[4] = drawstate->quantized_device_line_width;
  52. miSetGCAttribs (pGC, 5, attributes, values);
  53. /* set a double-valued miGC attribute */
  54. miSetGCMiterLimit (pGC, drawstate->miter_limit);
  55. /* now determine and set dashing-related attributes */
  56. if (drawstate->dash_array_in_effect)
  57. /* have user-specified dash array */
  58. {
  59. int i;
  60. num_dashes = drawstate->dash_array_len;
  61. if (num_dashes > 0)
  62. /* non-solid line type */
  63. {
  64. bool odd_length;
  65. double min_sing_val, max_sing_val;
  66. int dash_cycle_length;
  67. /* compute minimum singular value of user->device coordinate map,
  68. which we use as a multiplicative factor to convert line widths
  69. (cf. g_linewidth.c), dash lengths, etc. */
  70. _matrix_sing_vals (drawstate->transform.m,
  71. &min_sing_val, &max_sing_val);
  72. line_style = MI_LINE_ON_OFF_DASH;
  73. odd_length = (num_dashes & 1 ? true : false);
  74. {
  75. int array_len;
  76. array_len = (odd_length ? 2 : 1) * num_dashes;
  77. if (array_len <= PL_MAX_DASH_ARRAY_LEN)
  78. dashbuf = local_dashbuf; /* use dash buffer on stack */
  79. else
  80. {
  81. dashbuf = (unsigned int *)_pl_xmalloc (array_len * sizeof(unsigned int));
  82. dash_array_allocated = true;
  83. }
  84. }
  85. dash_cycle_length = 0;
  86. for (i = 0; i < num_dashes; i++)
  87. {
  88. double unrounded_dashlen;
  89. int dashlen;
  90. unrounded_dashlen =
  91. min_sing_val * drawstate->dash_array[i];
  92. dashlen = IROUND(unrounded_dashlen);
  93. dashlen = IMAX(dashlen, 1);
  94. dashbuf[i] = (unsigned int)dashlen;
  95. dash_cycle_length += dashlen;
  96. if (odd_length)
  97. {
  98. dashbuf[num_dashes + i] = (unsigned int)dashlen;
  99. dash_cycle_length += dashlen;
  100. }
  101. }
  102. if (odd_length)
  103. num_dashes *= 2;
  104. offset = IROUND(min_sing_val * drawstate->dash_offset);
  105. if (dash_cycle_length > 0)
  106. /* choose an offset in range 0..dash_cycle_length-1 */
  107. {
  108. while (offset < 0)
  109. offset += dash_cycle_length;
  110. offset %= dash_cycle_length;
  111. }
  112. }
  113. else
  114. /* zero-length dash array, i.e. solid line type */
  115. {
  116. line_style = MI_LINE_SOLID;
  117. dashbuf = NULL;
  118. offset = 0;
  119. }
  120. }
  121. else
  122. /* have one of the canonical line types */
  123. {
  124. if (drawstate->line_type == PL_L_SOLID)
  125. {
  126. line_style = MI_LINE_SOLID;
  127. num_dashes = 0;
  128. dashbuf = NULL;
  129. offset = 0;
  130. }
  131. else
  132. {
  133. const int *dash_array;
  134. int scale, i;
  135. line_style = MI_LINE_ON_OFF_DASH;
  136. num_dashes =
  137. _pl_g_line_styles[drawstate->line_type].dash_array_len;
  138. dash_array = _pl_g_line_styles[drawstate->line_type].dash_array;
  139. dashbuf = local_dashbuf; /* it is large enough */
  140. offset = 0;
  141. /* scale by line width in terms of pixels, if nonzero */
  142. scale = drawstate->quantized_device_line_width;
  143. if (scale <= 0)
  144. scale = 1;
  145. for (i = 0; i < num_dashes; i++)
  146. {
  147. int dashlen;
  148. dashlen = scale * dash_array[i];
  149. dashlen = IMAX(dashlen, 1);
  150. dashbuf[i] = (unsigned int)dashlen;
  151. }
  152. }
  153. }
  154. /* set dash-related attributes in libxmi's graphics context */
  155. miSetGCAttrib (pGC, MI_GC_LINE_STYLE, line_style);
  156. if (line_style != (int)MI_LINE_SOLID)
  157. miSetGCDashes (pGC, num_dashes, dashbuf, offset);
  158. if (dash_array_allocated)
  159. free (dashbuf);
  160. }