Ejemplo n.º 1
0
void
_set_common_mi_attributes (plDrawState *drawstate, void * ptr)
{
  int line_style, num_dashes, offset;
  unsigned int *dashbuf;
  bool dash_array_allocated = false;
  miGCAttribute attributes[5];
  int values [5];
  unsigned int local_dashbuf[PL_MAX_DASH_ARRAY_LEN];
  miGC *pGC;

  pGC = (miGC *)ptr;		/* recover passed libxmi GC */

  /* set all miGC attributes that are not dash related */

  /* set five integer-valued miGC attributes */
  attributes[0] = MI_GC_FILL_RULE;
  values[0] = (drawstate->fill_rule_type == PL_FILL_NONZERO_WINDING ? 
	       MI_WINDING_RULE : MI_EVEN_ODD_RULE);
  attributes[1] = MI_GC_JOIN_STYLE;
  values[1] = mi_join_style[drawstate->join_type];
  attributes[2] = MI_GC_CAP_STYLE;
  values[2] = mi_cap_style[drawstate->cap_type];
  attributes[3] = MI_GC_ARC_MODE;
  values[3] = MI_ARC_CHORD;	/* libplot convention */
  attributes[4] = MI_GC_LINE_WIDTH;
  values[4] = drawstate->quantized_device_line_width;
  miSetGCAttribs (pGC, 5, attributes, values);

  /* set a double-valued miGC attribute */
  miSetGCMiterLimit (pGC, drawstate->miter_limit);

  /* now determine and set dashing-related attributes */

  if (drawstate->dash_array_in_effect)
    /* have user-specified dash array */
    {
      int i;
      
      num_dashes = drawstate->dash_array_len;
      if (num_dashes > 0)
	/* non-solid line type */
	{
	  bool odd_length;
	  double min_sing_val, max_sing_val;
	  int dash_cycle_length;

	  /* compute minimum singular value of user->device coordinate map,
	     which we use as a multiplicative factor to convert line widths
	     (cf. g_linewidth.c), dash lengths, etc. */
	  _matrix_sing_vals (drawstate->transform.m, 
			     &min_sing_val, &max_sing_val);
	  
	  line_style = MI_LINE_ON_OFF_DASH;
	  odd_length = (num_dashes & 1 ? true : false);
	  {
	    int array_len;
	    
	    array_len = (odd_length ? 2 : 1) * num_dashes;
	    if (array_len <= PL_MAX_DASH_ARRAY_LEN)
	      dashbuf = local_dashbuf; /* use dash buffer on stack */
	    else
	      {
		dashbuf = (unsigned int *)_pl_xmalloc (array_len * sizeof(unsigned int));
		dash_array_allocated = true;
	      }
	  }
	  dash_cycle_length = 0;
	  for (i = 0; i < num_dashes; i++)
	    {
	      double unrounded_dashlen;
	      int dashlen;

	      unrounded_dashlen = 
		min_sing_val * drawstate->dash_array[i];

	      dashlen = IROUND(unrounded_dashlen);
	      dashlen = IMAX(dashlen, 1);

	      dashbuf[i] = (unsigned int)dashlen;
	      dash_cycle_length += dashlen;
	      if (odd_length)
		{
		  dashbuf[num_dashes + i] = (unsigned int)dashlen;
		  dash_cycle_length += dashlen;
		}
	    }
	  if (odd_length)
	    num_dashes *= 2;

	  offset = IROUND(min_sing_val * drawstate->dash_offset);
	  if (dash_cycle_length > 0)
	    /* choose an offset in range 0..dash_cycle_length-1 */
	    {
	      while (offset < 0)
		offset += dash_cycle_length;
	      offset %= dash_cycle_length;
	    }
	}
      else
	/* zero-length dash array, i.e. solid line type */
	{
	  line_style = MI_LINE_SOLID;
	  dashbuf = NULL;
	  offset = 0;
	}
    }
  else
    /* have one of the canonical line types */
    {
      if (drawstate->line_type == PL_L_SOLID)
	{
	  line_style = MI_LINE_SOLID;
	  num_dashes = 0;
	  dashbuf = NULL;
	  offset = 0;
	}
      else
	{
	  const int *dash_array;
	  int scale, i;
	  
	  line_style = MI_LINE_ON_OFF_DASH;
	  num_dashes =
	    _pl_g_line_styles[drawstate->line_type].dash_array_len;
	  dash_array = _pl_g_line_styles[drawstate->line_type].dash_array;
	  dashbuf = local_dashbuf; /* it is large enough */
	  offset = 0;

	  /* scale by line width in terms of pixels, if nonzero */
	  scale = drawstate->quantized_device_line_width;
	  if (scale <= 0)
	    scale = 1;

	  for (i = 0; i < num_dashes; i++)
	    {
	      int dashlen;
	      
	      dashlen = scale * dash_array[i];
	      dashlen = IMAX(dashlen, 1);
	      dashbuf[i] = (unsigned int)dashlen;
	    }
	}
    }

  /* set dash-related attributes in libxmi's graphics context */
  miSetGCAttrib (pGC, MI_GC_LINE_STYLE, line_style);
  if (line_style != (int)MI_LINE_SOLID)
    miSetGCDashes (pGC, num_dashes, dashbuf, offset);

  if (dash_array_allocated)
    free (dashbuf);
}
Ejemplo n.º 2
0
int main ()
{
  miPoint points[4];        /* 3 line segments in the polyline */
  miArc arc;                /* 1 arc to be drawn */
  miPixel pixels[4];        /* pixel values for drawing and dashing */
  unsigned int dashes[2];   /* length of `on' and `off' dashes */
  miGC *pGC;                /* graphics context */
  miPaintedSet *paintedSet; /* opaque object to be painted */
  miCanvas *canvas;         /* drawing canvas (including pixmap) */
  miPoint offset;           /* for miPaintedSet -> miCanvas transfer */
  int i, j;
     
  /* define polyline: vertices are (25,5) (5,5), (5,25), (35,22) */
  points[0].x = 25;  points[0].y = 5;
  points[1].x = 5;   points[1].y = 5;
  points[2].x = 5;   points[2].y = 25;
  points[3].x = 35;  points[3].y = 22;
     
  /* define elliptic arc */
  arc.x = 20; arc.y = 15;   /* upper left corner of bounding box */
  arc.width = 30;           /* x range of box: 20..50 */
  arc.height = 16;          /* y range of box: 15..31 */
  arc.angle1 = 0 * 64;      /* starting angle (1/64'ths of a degree) */
  arc.angle2 = 270 * 64;    /* angle range (1/64'ths of a degree) */
     
  /* create and modify graphics context */
  pixels[0] = 1;            /* pixel value for `off' dashes, if drawn */
  pixels[1] = 2;            /* default pixel for drawing */
  pixels[2] = 3;            /* another pixel, for multicolored dashes */
  pixels[3] = 4;            /* another pixel, for multicolored dashes */
  dashes[0] = 4;            /* length of `on' dashes */
  dashes[1] = 2;            /* length of `off' dashes */
  pGC = miNewGC (4, pixels);
  miSetGCAttrib (pGC, MI_GC_LINE_STYLE, MI_LINE_ON_OFF_DASH);
  miSetGCDashes (pGC, 2, dashes, 0);
  miSetGCAttrib (pGC, MI_GC_LINE_WIDTH, 0); /* Bresenham algorithm */
     
  /* create empty painted set */
  paintedSet = miNewPaintedSet ();
     
  /* paint dashed polyline and dashed arc onto painted set */
  miDrawLines (paintedSet, pGC, MI_COORD_MODE_ORIGIN, 4, points);
  miDrawArcs (paintedSet, pGC, 1, &arc);
     
  /* create 60x35 canvas (initPixel=0); merge painted set onto it */
  canvas = miNewCanvas (60, 35, 0);
  offset.x = 0; offset.y = 0;
  miCopyPaintedSetToCanvas (paintedSet, canvas, offset);
     
  /* write canvas's pixmap (a 60x35 array of miPixels) to stdout */
  for (j = 0; j < canvas->drawable->height; j++)
    {
      for (i = 0; i < canvas->drawable->width; i++)
	/* note: column index precedes row index */
	printf ("%d", canvas->drawable->pixmap[j][i]);
      printf ("\n");
    }
     
  /* clean up */
  miDeleteCanvas (canvas);
  miDeleteGC (pGC);
  miClearPaintedSet (paintedSet); /* not necessary */
  miDeletePaintedSet (paintedSet);
     
  return 0;
}