Exemple #1
0
/*
  HPGL command LT (Line Type)
*/
int hpgs_reader_do_LT(hpgs_reader *reader)
{
  float dashes[20];
  int i,ndash;
  int linetype=0;
  double patlen = 4.0;
  int    mode = 0;

  if (hpgs_reader_checkpath(reader)) return -1;

  if (!reader->eoc &&
      hpgs_reader_read_int(reader,&linetype)) return -1;

  if (!reader->eoc &&
      hpgs_reader_read_double(reader,&patlen)) return -1;

  if (!reader->eoc &&
      hpgs_reader_read_int(reader,&mode)) return -1;

  if (linetype < -8 || linetype > 8)
    {
      if (reader->verbosity)
	hpgs_log(hpgs_i18n("LT: Illegal linetype %d.\n"),linetype);
      return 0;
    }

  // line type are store as percentages.
  patlen *= 0.01;

  if (mode)
    patlen *= MM_TO_PT;
  else
    patlen *= hypot(reader->P2.x-reader->P1.x,
		    reader->P2.y-reader->P1.y ) * 0.01 * HP_TO_PT;

  ndash = reader->linetype_nsegs[linetype+8];
  if (ndash > 20) ndash = 20;

  for (i=0;i<ndash;++i)
    dashes[i] = reader->linetype_segs[linetype+8][i] * patlen;
  
  return hpgs_setdash(reader->device,
		      dashes,ndash,0.0);
}
Exemple #2
0
/*
  Do the pen select.
*/
int hpgs_reader_do_setpen(hpgs_reader *reader, int pen)
{
  double width;

  if (hpgs_reader_checkpath(reader)) return -1;

  if (pen < 0)
    return hpgs_set_error(hpgs_i18n("Illegal pen numer %d."),pen);

  if (pen >= reader->npens)
    {
      if (pen < 256)
        {
          if (hpgs_reader_set_number_of_pens(reader,pen+1))
            return -1;
        }
      else
        {
          if (reader->verbosity)
            hpgs_log(hpgs_i18n("Illegal pen number %d replaced by %d.\n"),
                     pen, pen % reader->npens);
          pen = pen %  reader->npens;
        }
    }

  reader->current_pen = pen;

  width = reader->pen_widths[pen];

  if (reader->pen_width_relative)
    width *= hypot(reader->P2.x-reader->P1.x,
		   reader->P2.y-reader->P1.y ) * 0.001 * HP_TO_PT;
  else
    width *= HP_TO_PT / reader->world_scale;

  width *= reader->page_scale;

  if (hpgs_setlinewidth(reader->device,width*reader->lw_factor))
    return -1;

  return hpgs_setrgbcolor(reader->device,
			  &reader->pen_colors[pen]);
}
/* 
  HPGL command IR (Input point Relative)
*/
int hpgs_reader_do_IR (hpgs_reader *reader)
{
  // get default input point.
  double p1x=0.0,p1y=0.0,p2x,p2y;

  int angle = reader->y_size >= reader->x_size ? 90 : 0;
  
  angle += reader->rotation;

  switch (angle % 360)
    {
    case 90:
      p1x = reader->x_size;
      p1y = 0.0;
      p2x = 0.0;
      p2y = reader->y_size;
      break;
    case 180:
      break;
      p1x = reader->x_size;
      p1y = reader->y_size;
      p2x = 0.0;
      p2y = 0.0;
      break;
    case 270:
      p1x = 0.0;
      p1y = reader->y_size;
      p2x = reader->x_size;
      p2y = 0.0;
      break;
    default:
      p1x = 0.0;
      p1y = 0.0;
      p2x = reader->x_size;
      p2y = reader->y_size;
    }

  // read input point
  if (!reader->eoc)
    {
      double x,y;

      if (hpgs_reader_read_double(reader,&x)) return -1;
      if (hpgs_reader_read_double(reader,&y)) return -1;

      p1x = reader->x_size * x * 0.01;
      p2x = p1x + reader->delta_P.x;
      p1y = reader->y_size * y * 0.01;
      p2y = p1y + reader->delta_P.y;
    }

  if (!reader->eoc)
    {
      if (hpgs_reader_read_double(reader,&p2x)) return -1;
      if (hpgs_reader_read_double(reader,&p2y)) return -1;

      p2x = reader->x_size * p2x * 0.01;
      p2y = reader->y_size * p2y * 0.01;

      reader->delta_P.x = p2x - p1x;
      reader->delta_P.y = p2y - p1y; 
    }

  reader->P1.x = p1x;
  reader->P1.y = p1y;
  reader->P2.x = p2x;
  reader->P2.y = p2y;
  
#ifdef HPGS_DEBUG_XFORM
  hpgs_log("IR: P1 = %g,%g.\n",reader->P1.x,reader->P1.y);
  hpgs_log("IR: P2 = %g,%g.\n",reader->P2.x,reader->P2.y);
#endif

  hpgs_reader_set_default_transformation(reader);

  return 0;
}
/* 
  HPGL command IP (Input Point)
*/
int hpgs_reader_do_IP (hpgs_reader *reader)
{
  // get default input point.
  int angle = reader->y_size >= reader->x_size ? 90 : 0;
  
  angle += reader->rotation;

  switch (angle % 360)
    {
    case 90:
      reader->P1.x = reader->x_size;
      reader->P1.y = 0.0;
      reader->P2.x = 0.0;
      reader->P2.y = reader->y_size;
      break;
    case 180:
      break;
      reader->P1.x = reader->x_size;
      reader->P1.y = reader->y_size;
      reader->P2.x = 0.0;
      reader->P2.y = 0.0;
      break;
    case 270:
      reader->P1.x = 0.0;
      reader->P1.y = reader->y_size;
      reader->P2.x = reader->x_size;
      reader->P2.y = 0.0;
      break;
    default: /* 0 */ 
      reader->P1.x = 0.0;
      reader->P1.y = 0.0;
      reader->P2.x = reader->x_size;
      reader->P2.y = reader->y_size;
    }


  // read input point
  if (!reader->eoc)
    {
      if (hpgs_reader_read_double(reader,
                                  angle%180 ?
                                  &reader->P1.y :
                                  &reader->P1.x  )) return -1;
      if (reader->eoc) return -1;
      if (hpgs_reader_read_double(reader,angle%180 ?
                                  &reader->P2.x :
                                  &reader->P1.y  )) return -1;
    }

  if (!reader->eoc)
    {
      if (hpgs_reader_read_double(reader,
                                  angle%180 ?
                                  &reader->P2.y :
                                  &reader->P2.x  )) return -1;
      if (reader->eoc) return -1;
      if (hpgs_reader_read_double(reader,
                                  angle%180 ?
                                  &reader->P1.x :
                                  &reader->P2.y  )) return -1;
    }

  reader->delta_P.x = reader->P2.x - reader->P1.x; 
  reader->delta_P.y = reader->P2.y - reader->P1.y; 

#ifdef HPGS_DEBUG_XFORM
  hpgs_log("IP: angle = %d.\n",angle);
  hpgs_log("IP: P1 = %g,%g.\n",reader->P1.x,reader->P1.y);
  hpgs_log("IP: P2 = %g,%g.\n",reader->P2.x,reader->P2.y);
#endif

  reader->sc_type = -1;
  hpgs_reader_set_default_transformation(reader);

  return 0;
}
/* 
  HPGL command RO (ROtate)
*/
int hpgs_reader_do_RO (hpgs_reader *reader)
{
  int rot=0;
  hpgs_point p1,p2;
  double dx,dy;

  if (!reader->eoc &&
      hpgs_reader_read_int(reader,&rot)) return -1;

  switch ((rot - reader->rotation) % 360)
    {
    case 90:
      p1.x = -reader->P1.y;
      p1.y =  reader->P1.x;
      p2.x = -reader->P2.y;
      p2.y =  reader->P2.x;
      break;
    case 180:
      p1.x = -reader->P1.x;
      p1.y = -reader->P1.y;
      p2.x = -reader->P2.x;
      p2.y = -reader->P2.y;
      break;
    case 270:
      p1.x =  reader->P1.y;
      p1.y = -reader->P1.x;
      p2.x =  reader->P2.y;
      p2.y = -reader->P2.x;
      break;
    default: /* 0,360 */
      p1.x = reader->P1.x;
      p1.y = reader->P1.y;
      p2.x = reader->P2.x;
      p2.y = reader->P2.y;
      break;
    }
  
  dx = p1.x < p2.x ? p1.x : p2.x;
  dy = p1.y < p2.y ? p1.y : p2.y;

#ifdef HPGS_DEBUG_XFORM
  hpgs_log("RO: rot_old,rot = %d,%d.\n",reader->rotation,rot);
  hpgs_log("RO: P1 = %g,%g.\n",reader->P1.x,reader->P1.y);
  hpgs_log("RO: P2 = %g,%g.\n",reader->P2.x,reader->P2.y);
#endif

  reader->P1.x = p1.x-dx;
  reader->P1.y = p1.y-dy;
  reader->P2.x = p2.x-dx;
  reader->P2.y = p2.y-dy;

#ifdef HPGS_DEBUG_XFORM
  hpgs_log("RO: P1 = %g,%g.\n",reader->P1.x,reader->P1.y);
  hpgs_log("RO: P2 = %g,%g.\n",reader->P2.x,reader->P2.y);
#endif

  reader->rotation = rot;

  hpgs_reader_set_default_transformation(reader);

  return 0;
}
static void apply_scale(hpgs_reader *reader,
                        const hpgs_point *p1, const hpgs_point *p2)
{
  double xf,yf;
  double dx = 0.0,dy=0.0;
  hpgs_point p2u;

  if (reader->sc_type < 0) return;

  // get P2 in old user coordinates
  p2u.x = reader->frame_x + p2->x * HP_TO_PT;
  p2u.y = reader->frame_y + p2->y * HP_TO_PT;

  hpgs_matrix_ixform(&p2u,&p2u,&reader->world_matrix);

#ifdef HPGS_DEBUG_XFORM
    {
      hpgs_point p1u;

      p1u.x = reader->frame_x + p1->x * HP_TO_PT;
      p1u.y = reader->frame_y + p1->y * HP_TO_PT;

      hpgs_matrix_ixform(&p1u,&p1u,&reader->world_matrix);

      hpgs_log("SC: P1 = %g,%g.\n",p1->x,p1->y);
      hpgs_log("SC: P2 = %g,%g.\n",p2->x,p2->y);
      hpgs_log("SC: p1u = %g,%g.\n",p1u.x,p1u.y);
      hpgs_log("SC: p2u = %g,%g.\n",p2u.x,p2u.y);
      hpgs_log("SC: xmin,xmax = %g,%g.\n",reader->sc_xmin,reader->sc_xmax);
      hpgs_log("SC: ymin,ymax = %g,%g.\n",reader->sc_ymin,reader->sc_ymax);
    }
#endif

  switch (reader->sc_type)
    {
    case 0:
      xf = p2u.x / (reader->sc_xmax - reader->sc_xmin);
      yf = p2u.y / (reader->sc_ymax - reader->sc_ymin);
      break;
    case 1:
      xf = p2u.x / (reader->sc_xmax - reader->sc_xmin);
      yf = p2u.y / (reader->sc_ymax - reader->sc_ymin);

      if (xf < yf)
	{
	  dy = (yf-xf) * (reader->sc_ymax - reader->sc_ymin) * 0.01 * reader->sc_left;
	  yf = xf;
	}
      else
	{
	  dx = (xf-yf) * (reader->sc_xmax - reader->sc_xmin) * 0.01 * reader->sc_bottom;
	  xf = yf;
	}
      break;

    case 2:
      xf = reader->sc_xmax;
      yf = reader->sc_ymax;
      break;

    default:
      return;
    }

#ifdef HPGS_DEBUG_XFORM
  hpgs_log("SC: xf,yf = %g,%g.\n",xf,yf);
#endif

  dx -= reader->sc_xmin * xf;
  dy -= reader->sc_ymin * yf;

  // concatenate transformation matrices.
  //
  // | 1    0   0 |  | 1   0   0 |   
  // | x0 mxx mxy |* | dx  xf  0 | = 
  // | y0 myx myy |  | dy  0  yf |   
  //
  // | 1                     0      0 |
  // | x0+mxx*dx+mxy*dy mxx*xf mxy*yf |
  // | y0+myx*dx+myy*dy myx*xf myy*yf |
  //

  reader->world_matrix.dx += reader->world_matrix.mxx*dx + reader->world_matrix.mxy*dy;
  reader->world_matrix.dy += reader->world_matrix.myx*dx + reader->world_matrix.myy*dy;

  reader->world_matrix.mxx *= xf;
  reader->world_matrix.myx *= xf;
  reader->world_matrix.mxy *= yf;
  reader->world_matrix.myy *= yf;

#ifdef HPGS_DEBUG_XFORM
  hpgs_log("SC: %10g %10g %10g\n",reader->world_matrix.dx,reader->world_matrix.mxx,reader->world_matrix.mxy);
  hpgs_log("SC: %10g %10g %10g\n",reader->world_matrix.dy,reader->world_matrix.myx,reader->world_matrix.myy);
#endif
}
void hpgs_reader_set_default_transformation (hpgs_reader *reader)
{
  // transformation matrix for user to PS coordinates.
  int angle = reader->y_size >= reader->x_size ? 90 : 0;

  hpgs_point p1 = reader->P1;
  hpgs_point p2 = reader->P2;

  angle += reader->rotation;

  if ((angle % 180) == 90)
    {
      p2.y -= p1.y;
      p1.y = 0.0;
    }


  reader->world_matrix.dx = reader->frame_x + p1.x * HP_TO_PT;
  reader->world_matrix.dy = reader->frame_y + p1.y * HP_TO_PT;

  switch (angle % 360)
    {
    case 90:
      reader->world_matrix.mxx = 0.0;
      reader->world_matrix.mxy = -HP_TO_PT;
      reader->world_matrix.myx = HP_TO_PT;
      reader->world_matrix.myy = 0.0;
      break;
    case 180:
      reader->world_matrix.mxx = -HP_TO_PT;
      reader->world_matrix.mxy = 0.0;
      reader->world_matrix.myx = 0.0;
      reader->world_matrix.myy = -HP_TO_PT;
      break;
    case 270:
      reader->world_matrix.mxx = 0.0;
      reader->world_matrix.mxy = HP_TO_PT;
      reader->world_matrix.myx = -HP_TO_PT;
      reader->world_matrix.myy = 0.0;
      break;
    default: // 0
      reader->world_matrix.mxx = HP_TO_PT;
      reader->world_matrix.mxy = 0.0;
      reader->world_matrix.myx = 0.0;
      reader->world_matrix.myy = HP_TO_PT;
    }

#ifdef HPGS_DEBUG_XFORM
  hpgs_log("xform: %10g %10g %10g\n",reader->world_matrix.dx,reader->world_matrix.mxx,reader->world_matrix.mxy);
  hpgs_log("xform: %10g %10g %10g\n",reader->world_matrix.dy,reader->world_matrix.myx,reader->world_matrix.myy);
#endif

  apply_scale(reader,&p1,&p2);

  reader->world_scale =
    sqrt (fabs(reader->world_matrix.mxx * reader->world_matrix.myy -
               reader->world_matrix.mxy * reader->world_matrix.myx  ) );

  // finally transform from model space to the page.
  hpgs_matrix_concat(&reader->total_matrix,&reader->page_matrix,&reader->world_matrix);

  reader->total_scale = reader->page_scale * reader->world_scale;
}
/*! 
   Sets a clip frame to the given device, which encloses all regions
   of the device, which are cover by the image taking into account
   the given ROP3 transfer function.

   The argument \c data must contain a pointer to a two-dimensional
   array of raw pixels of the size of the image. This array is filled
   with pixel values as if the image has been painted to a white
   destination area using the given ROP3 function.

   Return values:
     \li 0 The clip frame is empty, no operation has been performed on
           the output device.

     \li 1 The clip frame is not empty, the clip path has been
           set to the output device using clipsave/moveto/lineto/clip
           operations.

     \li 2 The clip frame covers the whole image, no operation has been
           performed on the output device.

     \li 3 The clip frame is not empty, the visible pixels have all the same color
           and clip path has been set to the output device using
           moveto/lineto/setrgbcolor/fill operations. The image does not have to be
           transferred by subsequent functions, the rgb color of the device has been
           altered.

     \li -1 An error occured on the output device.

*/
int hpgs_image_rop3_clip(hpgs_device *device,
                         hpgs_palette_color *data,
                         const hpgs_image *img,
                         const hpgs_point *ll, const hpgs_point *lr,
                         const hpgs_point *ur,
                         const hpgs_palette_color *p,
                         hpgs_xrop3_func_t xrop3)
{
  // The upper bound for clip_lines_sz is (w+1)*(h+1)*2.
  // This formula is chosen so, that for w==1 and h==1,
  // this result is achieved. For larger pictures, we
  // use 1/8th of the upper bound, which is pretty conservative.
  // If not doing so, the algorithm easily consumes up to 1GB or more,
  // which is too much for alloca, too. So this estimation combined
  // with the usage of malloc should make the code robust.
  size_t clip_lines_sz = ((img->width+1)*(img->height+1)+31)/4;

  hpgs_img_clip_line *clip_lines = (hpgs_img_clip_line *)
    malloc(sizeof(hpgs_img_clip_line)*clip_lines_sz);

  hpgs_img_clip_seg *segs0 = (hpgs_img_clip_seg *)
    hpgs_alloca(sizeof(hpgs_img_clip_seg)*(img->width+1));

  hpgs_img_clip_seg *segs1 = (hpgs_img_clip_seg *)
    hpgs_alloca(sizeof(hpgs_img_clip_seg)*(img->width+1));

  if (!clip_lines || !segs0 || !segs1)
    return hpgs_set_error(hpgs_i18n("hpgs_image_rop3_clip: Out of memory allocating temporary storage."));

  int n_clip_lines = 0;
  int ret = -1;
  int i_seg0,n_segs0 = 0;
  int i_seg1,n_segs1 = 0;

  hpgs_point ul;
  int i,j;

  hpgs_bool all_visible = HPGS_TRUE;
  hpgs_palette_color *first_visible_pixel = 0;
  hpgs_bool single_color = HPGS_FALSE;

  ul.x = ll->x + (ur->x - lr->x);
  ul.y = ll->y + (ur->y - lr->y);

  // first, accumulate lines.
  for (i=0;i<img->height+1;++i)
    {
      // cut the current raster line
      int t_last = 1;
      n_segs1 = 0;

      // this is here in order to construct all lines
      // for the very last grid line
      if (i<img->height)
        {
          for (j=0;j<img->width;++j)
            {
              int t;
              hpgs_paint_color s;
              unsigned r,g,b;
              
              hpgs_image_get_pixel(img,j,i,&s,0);

              r = xrop3(s.r,p->r);
              g = xrop3(s.g,p->g);
              b = xrop3(s.b,p->b);

              // transparent ?
              t = (r == 0x00ff && g == 0x00ff && b == 0x00ff);

              if (t != t_last) // last pixel different transparency ?
                {
                  segs1[n_segs1].j = j;
                  segs1[n_segs1].i_vert = -1;
                  ++n_segs1;
                }

              t_last = t;

              data->r = (unsigned char)r;
              data->g = (unsigned char)g;
              data->b = (unsigned char)b;

              if (!t)
                {
                  if (!first_visible_pixel)
                    {
                      first_visible_pixel = data;
                      single_color = HPGS_TRUE;
                    }
                  else if (single_color &&
                           (first_visible_pixel->r != data->r ||
                            first_visible_pixel->g != data->g ||
                            first_visible_pixel->b != data->b   ))
                    single_color = HPGS_FALSE;
                }

              ++data;
            }

          if (n_segs1 != 1 || segs1[0].j > 0)
            all_visible = HPGS_FALSE;

          // close trailing visible segment.
          if (t_last == 0)
            {
              segs1[n_segs1].j = j;
              segs1[n_segs1].i_vert = -1;
              ++n_segs1;
            }
        }

      assert(n_segs1 <= (img->width+1));

#ifdef HPGS_IMAGE_ROP_DEBUG
      hpgs_log("i=%d: segs1:",i);

      for (j=0;j<n_segs1;++j)
        hpgs_log("%c%d",j?',':' ',segs1[j].j);
      hpgs_log("\n");

      j=n_clip_lines;
#endif

      // construct lines.
      i_seg0 = 0;
      i_seg1 = 0;
      t_last = -1;

      while (i_seg0 < n_segs0 || i_seg1 < n_segs1)
        {
          if (i_seg1 >= n_segs1 || (i_seg0 < n_segs0 && segs0[i_seg0].j < segs1[i_seg1].j))
            {
              // horizontal line.
              if (t_last >= 0)
                {
                  clip_lines[n_clip_lines].i0 = i; 
                  clip_lines[n_clip_lines].i1 = i; 
                  // check for the orientation.
                  if (i_seg0 & 1)
                    {
                      clip_lines[n_clip_lines].j0 = t_last; 
                      clip_lines[n_clip_lines].j1 = segs0[i_seg0].j;
                    }
                  else
                    {
                      clip_lines[n_clip_lines].j0 = segs0[i_seg0].j;
                      clip_lines[n_clip_lines].j1 = t_last; 
                    }

                  if (++n_clip_lines >= clip_lines_sz &&
                      grow_clip_lines(device,&clip_lines,&clip_lines_sz))
                    goto cleanup;

                  t_last = -1;
                }
              else
                t_last = segs0[i_seg0].j;


              ++i_seg0;
            }
          else if (i_seg0 >= n_segs0 ||  segs1[i_seg1].j < segs0[i_seg0].j)
            {
              // horizontal line.
              if (t_last >= 0)
                {
                  clip_lines[n_clip_lines].i0 = i; 
                  clip_lines[n_clip_lines].i1 = i; 
                  // check for the orientation.
                  if (i_seg1 & 1)
                    {
                      clip_lines[n_clip_lines].j0 = segs1[i_seg1].j; 
                      clip_lines[n_clip_lines].j1 = t_last;
                    }
                  else
                    {
                      clip_lines[n_clip_lines].j0 = t_last; 
                      clip_lines[n_clip_lines].j1 = segs1[i_seg1].j;
                    }
                  if (++n_clip_lines >= clip_lines_sz &&
                      grow_clip_lines(device,&clip_lines,&clip_lines_sz))
                    goto cleanup;
                  t_last = -1;
                }
              else
                t_last = segs1[i_seg1].j;

              // create vertical line.
              clip_lines[n_clip_lines].j0 = segs1[i_seg1].j; 
              clip_lines[n_clip_lines].j1 = segs1[i_seg1].j; 

              // check for the orientation.
              if (i_seg1 & 1)
                {
                  clip_lines[n_clip_lines].i0 = i+1;
                  clip_lines[n_clip_lines].i1 = i;
                }
              else
                {
                  clip_lines[n_clip_lines].i0 = i;
                  clip_lines[n_clip_lines].i1 = i+1;
                }

              segs1[i_seg1].i_vert = n_clip_lines;
              if (++n_clip_lines >= clip_lines_sz &&
                  grow_clip_lines(device,&clip_lines,&clip_lines_sz))
                goto cleanup;

              ++i_seg1;
            }
          else
            {
              assert(segs0[i_seg0].j == segs1[i_seg1].j);
              
              // horizontal line.
              if (t_last >= 0)
                {
                  clip_lines[n_clip_lines].i0 = i; 
                  clip_lines[n_clip_lines].i1 = i; 
                  // check for the orientation.
                  if (i_seg1 & 1)
                    {
                      clip_lines[n_clip_lines].j0 = segs1[i_seg1].j; 
                      clip_lines[n_clip_lines].j1 = t_last;
                    }
                  else
                    {
                      clip_lines[n_clip_lines].j0 = t_last; 
                      clip_lines[n_clip_lines].j1 = segs1[i_seg1].j;
                    }

                  if (++n_clip_lines >= clip_lines_sz &&
                      grow_clip_lines(device,&clip_lines,&clip_lines_sz))
                    goto cleanup;
                }

              if ((i_seg0 & 1) == (i_seg1 & 1))
                {
                  // extend segment
                  int il = segs0[i_seg0].i_vert;
                  if (i_seg1 & 1)
                    clip_lines[il].i0 = i+1;
                  else
                    clip_lines[il].i1= i+1;
                  
                  segs1[i_seg1].i_vert = il;
                  t_last = -1;
                }
              else
                {
                  // create new segment.
                  clip_lines[n_clip_lines].j0 = segs1[i_seg1].j;
                  clip_lines[n_clip_lines].j1 = segs1[i_seg1].j;

                  if (i_seg1 & 1)
                    {
                      clip_lines[n_clip_lines].i0 = i+1;
                      clip_lines[n_clip_lines].i1 = i;
                    }
                  else
                    {
                      clip_lines[n_clip_lines].i0 = i;
                      clip_lines[n_clip_lines].i1 = i+1;
                    }

                  segs1[i_seg1].i_vert = n_clip_lines;

                  if (++n_clip_lines >= clip_lines_sz &&
                      grow_clip_lines(device,&clip_lines,&clip_lines_sz))
                    goto cleanup;

                  t_last = segs1[i_seg1].j;
                }

              ++i_seg0;
              ++i_seg1;
            }
        }

#ifdef HPGS_IMAGE_ROP_DEBUG
      hpgs_log("i=%d: lines: ",i);

      for (;j<n_clip_lines;++j)
        hpgs_log("(%d,%d,%d,%d)",
                clip_lines[j].i0,clip_lines[j].j0,
                clip_lines[j].i1,clip_lines[j].j1);
      hpgs_log("\n");
#endif
      assert (t_last == -1);

      // swap clip segment caches
      {
        hpgs_img_clip_seg *tmp = segs0;
        segs0=segs1;
        segs1=tmp;
      }
      n_segs0 = n_segs1;
    }

#ifdef HPGS_IMAGE_ROP_DEBUG
  hpgs_log("clip_img: n_clip_lines,all_visible = %d,%d.\n",
           n_clip_lines,all_visible);
#endif

  if (n_clip_lines <= 0) { ret = 0; goto cleanup; }
  if (all_visible && !single_color)  { ret = 2; goto cleanup; }

  assert(n_clip_lines <= (img->width+1)*(img->height+1)*2);

  // OK, now create the lookup key of the lines.
  for (i=0;i<n_clip_lines;++i)
    {
      clip_lines[i].key = MK_LINE_KEY(clip_lines[i].i0,clip_lines[i].j0);
      clip_lines[i].usage = 0;
    }

  // sort the table
  qsort(clip_lines,n_clip_lines,sizeof(hpgs_img_clip_line),compare_clip_lines);

  if (!single_color && hpgs_clipsave(device)) goto cleanup;

  // now construct the clip path.
  for (i = 0;i<n_clip_lines;++i)
    {
      hpgs_img_clip_line *line = clip_lines+i;
      int iline = 0;

      if (line->usage) continue;

      do
        {
          hpgs_point p;
          int key,i0,i1;

          p.x = ul.x +
            line->j0 * (lr->x - ll->x) / img->width +
            line->i0 * (lr->x - ur->x) / img->height ;
          
          p.y = ul.y +
            line->j0 * (lr->y - ll->y) / img->width +
            line->i0 * (lr->y - ur->y) / img->height ;
          
          key = MK_LINE_KEY(line->i1,line->j1);

          if (iline)
            {
              if (hpgs_lineto(device,&p))  goto cleanup;
            }
          else
            {
              if (hpgs_moveto(device,&p))  goto cleanup;
            }

#ifdef HPGS_IMAGE_ROP_DEBUG
          hpgs_log("(%d,%d,%d,%d)",
                  line->i0,line->j0,
                  line->i1,line->j1);
#endif
          ++iline;
          line->usage=1;

          // binary search
          i0 = 0;
          i1 = n_clip_lines;

          while (i1>i0)
            {
              int ii = i0+(i1-i0)/2;
              
              if (clip_lines[ii].key < key)
                i0 = ii+1;
              else
                i1 = ii;
            }

          while (clip_lines[i0].usage &&
                 i0 < n_clip_lines-1 &&
                 clip_lines[i0+1].key == key)
            ++i0;

          assert(i0 < n_clip_lines && key == clip_lines[i0].key);

          line = clip_lines+i0;

          assert (line);

          if (line->usage && line < clip_lines + n_clip_lines &&
              line[1].key == key)
            ++line;
        }
      while (!line->usage);

      assert (line->i0 == clip_lines[i].i0 &&
              line->j0 == clip_lines[i].j0   );

#ifdef HPGS_IMAGE_ROP_DEBUG
      hpgs_log("\n");
#endif
      if (hpgs_closepath(device)) goto cleanup;
    }

  if (single_color)
    {
      hpgs_color c;

      c.r = first_visible_pixel->r / 255.0;
      c.g = first_visible_pixel->g / 255.0;
      c.b = first_visible_pixel->b / 255.0;

      if (hpgs_setrgbcolor(device,&c)) goto cleanup;
      if (hpgs_fill(device,HPGS_FALSE)) goto cleanup;
      if (hpgs_newpath(device)) goto cleanup;

      ret = 3;
    }

  else
    {
      if (hpgs_clip(device,HPGS_FALSE)) goto cleanup;
      if (hpgs_newpath(device)) goto cleanup;

      ret = 1;
    }

 cleanup:
  if (clip_lines) free(clip_lines);
  return ret;
}
Exemple #9
0
/* 
  HPGL command PW (Pen Width)
*/
int hpgs_reader_do_PW (hpgs_reader *reader)
{
  int pen=-1;
  double width=1.0;

  if (!reader->eoc)
    if (hpgs_reader_read_double(reader,&width)) return -1;
  if (!reader->eoc)
    {
      if (hpgs_reader_read_int(reader,&pen)) return -1;

      if (pen < 0 || pen >= reader->npens)
        {
          if (pen >= reader->npens && pen < 256)
            {
              if (hpgs_reader_set_number_of_pens(reader,pen+1))
                return -1;
            }
          else
            {
              if (reader->verbosity)
                hpgs_log(hpgs_i18n("PW: Illegal pen number %d.\n"),pen);
              
              return 0;
            }
        }
    }

  if (reader->verbosity >= 2)
    hpgs_log("PW: pen,width,rel = %d,%g,%d.\n",pen,width,reader->pen_width_relative);

  if (reader->pen_width_relative)
    width *= 10.0;
  else
    width *= MM_TO_PT;

  if (pen < 0)
    {
      int i;
      for (i=0;i<reader->npens;++i)
	reader->pen_widths[i] = width;
    }
  else
    reader->pen_widths[pen] = width;

  if (pen < 0 || pen == reader->current_pen)
    {
      if (hpgs_reader_checkpath(reader)) return -1;

      if (reader->pen_width_relative)
        width *= hypot(reader->P2.x-reader->P1.x,
                       reader->P2.y-reader->P1.y ) * 0.001 * HP_TO_PT;
      else
        width *= HP_TO_PT / reader->world_scale;

      width *= reader->page_scale;

      if (hpgs_setlinewidth(reader->device,width*reader->lw_factor))
	return -1;
    }

  return 0;
}
Exemple #10
0
/* 
  HPGL command PC (Pen Color)
*/
int hpgs_reader_do_PC (hpgs_reader *reader)
{
  int pen=-1;
  double r=-1.0e20,g=-1.0e20,b=-1.0e20;

  if (!reader->eoc && hpgs_reader_read_int(reader,&pen)) return -1;
  if (!reader->eoc && hpgs_reader_read_double(reader,&r)) return -1;
  if (!reader->eoc && hpgs_reader_read_double(reader,&g)) return -1;
  if (!reader->eoc && hpgs_reader_read_double(reader,&b)) return -1;

  if (pen >= reader->npens)
    {
      if (pen < 256)
        {
          if (hpgs_reader_set_number_of_pens(reader,pen+1))
            return -1;
        }
      else
        {
          if (reader->verbosity)
            hpgs_log(hpgs_i18n("PC: Illegal pen number %d.\n"),pen);

          return 0;
        }
    }

  if (pen < 0)
    {
      hpgs_reader_set_std_pen_colors(reader,0,reader->npens);
      pen = reader->current_pen;
    }
  else
    {
      if (r==-1.0e20 || g==-1.0e20 || b==-1.0e20)
        {
          hpgs_reader_set_std_pen_colors(reader,pen,1);
        }
      else
        {
          reader->pen_colors[pen].r =
            (r - reader->min_color.r) / (reader->max_color.r - reader->min_color.r);
          if (reader->pen_colors[pen].r < 0.0) reader->pen_colors[pen].r = 0.0;
          if (reader->pen_colors[pen].r > 1.0) reader->pen_colors[pen].r = 1.0;

          reader->pen_colors[pen].g =
            (g - reader->min_color.g) / (reader->max_color.g - reader->min_color.g);
          if (reader->pen_colors[pen].g < 0.0) reader->pen_colors[pen].g = 0.0;
          if (reader->pen_colors[pen].g > 1.0) reader->pen_colors[pen].g = 1.0;

          reader->pen_colors[pen].b =
            (b - reader->min_color.b) / (reader->max_color.b - reader->min_color.b);
          if (reader->pen_colors[pen].b < 0.0) reader->pen_colors[pen].b = 0.0;
          if (reader->pen_colors[pen].b > 1.0) reader->pen_colors[pen].b = 1.0;
        }
    }

  if (pen == reader->current_pen)
    if (hpgs_setrgbcolor(reader->device,
			 &reader->pen_colors[pen]))
      return -1;

  return 0;
}