Esempio n. 1
0
static int trim_rgb(gstack_t* stack)
{
  size_t n = gstack_size(stack);
  rgb_stop_t stop;
  gstack_t *stack0;

  if ((stack0 = gstack_new(sizeof(rgb_stop_t), n, n)) == NULL)
    return 1;

  while (! gstack_empty(stack))
    {
      gstack_pop(stack, &stop);
      gstack_push(stack0, &stop);

      if (stop.z >= 409600)
	{
	  while (! gstack_empty(stack))
	    gstack_pop(stack, &stop);
	}
    }

  while (! gstack_empty(stack0))
    {
      gstack_pop(stack0, &stop);
      gstack_push(stack, &stop);
    }

  gstack_destroy(stack0);

  return 0;
}
Esempio n. 2
0
extern int paths_serialise(gstack_t* paths, size_t* nA, arrow_t** pA)
{
  size_t n = paths_count(paths);

  if (n>0)
    {
      arrow_t *A = malloc(n*sizeof(arrow_t));

      *pA = A;

      gstack_t *path;

      if (!A) return 1;

      while (gstack_pop(paths, &path) == 0)
	{
	  corner_t corner;

	  while (gstack_pop(path, &corner) == 0)
	    {
	      *A = corner.A;
	      A++;
	    }
	}
    }

  *nA = n;

  return 0;
}
Esempio n. 3
0
static int merged_svg(gstack_t *ross, svg_t *svg)
{
  svg_stop_t ss;
  rgbop_stop_t ros;

  while (gstack_pop(ross, &ros) == 0)
    {
      ss.colour.red   = svg_it_rgb(ros.r);
      ss.colour.green = svg_it_rgb(ros.g);
      ss.colour.blue  = svg_it_rgb(ros.b);
      ss.opacity      = svg_it_op(ros.op);
      ss.value        = svg_it_z(ros.z);
      svg_append(ss,svg);
    }

  return 0;
}
Esempio n. 4
0
static int pssvg_convert(grd5_t *grd5, svgset_t *svgset, pssvg_opt_t opt)
{
  int n = grd5->n;
  gstack_t *gstack;

  if ((gstack = gstack_new(sizeof(svg_t*), n, 1)) == NULL)
    return 1;

  int err = pssvg_convert_all(grd5, svgset, gstack, opt);

  if (! err)
    {
      size_t m = gstack_size(gstack);

      if (m == 0)
	{
	  btrace("no gradients converted");
	  err++;
	}
      else
	{
	  if (m < n)
	    btrace("only %zd/%d gradient converted", m, n);

	  if (gstack_reverse(gstack) != 0)
	    err++;
	  else
	    {
	      svgset->n = m;

	      if ((svgset->svg = malloc(m*sizeof(svg_t*))) == NULL)
		err++;
	      else
		{
		  for (size_t i = 0 ; i < m ; i++)
		    gstack_pop(gstack, svgset->svg+i);
		}
	    }
	}
    }

  gstack_destroy(gstack);

  return err;
}
Esempio n. 5
0
static gstack_t* merge(gstack_t *rss, gstack_t *oss)
{
  gstack_t *ross;
  int err = 0;
  size_t n = gstack_size(rss) + gstack_size(oss);

  /* get the first two of each type of stop */

  rgb_stop_t rs0, rs1;

  err += gstack_pop(rss, &rs0);
  err += gstack_pop(rss, &rs1);

  if (err)
    {
      btrace("%i errors rgb", err);
      return NULL;
    }

  op_stop_t os0, os1;

  err += gstack_pop(oss, &os0);
  err += gstack_pop(oss, &os1);

  if (err)
    {
      btrace("%i errors op", err);
      return NULL;
    }

  if ((rs0.z != 0) || (os0.z != 0))
    {
      btrace("nonzero initial stop");
      btrace("RGB     %.3f", svg_it_z(rs0.z));
      btrace("Opacity %.3f", svg_it_z(os0.z));
      return NULL;
    }

  /* merged stack to return */

  if ((ross = gstack_new(sizeof(rgbop_stop_t), n, n)) == NULL)
    return NULL;

  rgbop_stop_t ros;

  while (1)
    {
      ros = stop_merge(rs0, os0);
      gstack_push(ross, &ros);

      if (rs1.z > os1.z)
	{
	  rs0 = rgb_stop_interp(rs0, rs1, os1.z);
	  os0 = os1;

	  if (gstack_pop(oss, &os1) != 0)
	    {
	      btrace("early termination of opacity channel");
	      break;
	    }
	}
      else if (rs1.z < os1.z)
	{
	  os0 = op_stop_interp(os0, os1, rs1.z);
	  rs0 = rs1;

	  if (gstack_pop(rss, &rs1) != 0)
	    {
	      btrace("early termination of rgb channel");
	      break;
	    }
	}
      else
	{
	  rs0 = rs1;
	  os0 = os1;

	  int
            odone = gstack_pop(oss, &os1),
            rdone = gstack_pop(rss, &rs1);

	  if (odone && rdone)
	    {
	      ros = stop_merge(rs0, os0);
	      gstack_push(ross, &ros);
	      gstack_reverse(ross);

	      return ross;
	    }
	  else if (odone && !rdone)
	    {
	      btrace("early termination of opacity channel");
	      break;
	    }
	  else if (rdone && ! odone)
	    {
	      btrace("early termination of rgb channel");
	      break;
	    }
	  else
	    {
	      /* OK, so now we continue */
	    }
	}
    }

  /* something has gone pear-shaped */

  gstack_destroy(ross);

  btrace("merge failed");

  return NULL;
}
Esempio n. 6
0
static int path_decimate(gstack_t** path, double* Dmin)
{
  size_t n = gstack_size(*path);
  double xmin = pow(*Dmin, 2);
  corner_t cns[n];

  /*
    empty the stack into a corners array - we do this
    in reverse order so the gstack_push below gives us
    a gstack_t in the same order (needed due to an
    assumed orientation of the boundaries)
  */

  for (int i = 0 ; i < n ; i++)
    {
      if (gstack_pop(*path, (void*)(cns+(n-1-i))) != 0)
	return -1;
    }

  /* cache metric tensor and ellipse centres */

  vector_t e[n];
  m2_t mt[n];

  for (int i = 0 ; i < n ; i++)
    {
      ellipse_t E;

      arrow_ellipse(&(cns[i].A), &E);

      mt[i] = ellipse_mt(E);
      e[i] = E.centre;
    }

  /* create ellipse intersection graph */

  graph_t G;

  if (graph_init(n,&G) != 0)
    return -1;

  size_t err = 0;

  for (int i = 0 ; i < n-1 ; i++)
    {
      for (int j = i+1 ; j < n ; j++)
	{
	  double x = contact_mt(vsub(e[j], e[i]), mt[i], mt[j]);

	  /*
	    failed contact() results in edge not being
	    included in the graph so possible intesection
	    survives - save the number for a warning (below)
	  */

	  if (x<0)
	    {
	      err++;
	      continue;
	    }

	  /*
	    weight of each node is the maximum of the
	    contact-distances of the incoming edges
	  */

	  if (x < xmin)
	    {
	      double
		w1 = graph_get_weight(G, i),
		w2 = graph_get_weight(G, j);

	      graph_set_weight(G, i, MAX(w1, x));
	      graph_set_weight(G, j, MAX(w2, x));

	      if (graph_add_edge(G, i, j) != 0)
		return -1;
	    }
	}
    }

  if (err)
    fprintf(stderr,"failed contact distance for %i pairs\n", (int)err);

  /* greedy node deletion to obtain non-intersecting subset */

  size_t maxi;

  while (graph_maxedge(G, &maxi) > 0)
    if (graph_del_node(G, maxi) != 0)
      return -1;

  /* dump back into gstack */

  for (int i = 0 ; i < n ; i++)
    if ( !graph_node_flag(G, i, NODE_STALE) )
      gstack_push(*path, (void*)(cns+i));

  graph_clean(&G);

  return 1;
}