Exemple #1
0
/*!
   Transforms the given bounding box \c bb with the the inverse of
   the matrix \c m.
   The result is the enclosing bounding box of the transformed 
   rectangle of the bounding box and is stored in \c res.
   The pointers \c bb and \c res may point to the same memory location.
 */
void hpgs_matrix_ixform_bbox(hpgs_bbox *res,
                             const hpgs_bbox *bb, const hpgs_matrix *m)
{
  hpgs_point ll = { bb->llx, bb->lly };
  hpgs_point ur = { bb->urx, bb->ury };

  hpgs_point lr = { bb->llx, bb->ury };
  hpgs_point ul = { bb->urx, bb->lly };

  hpgs_matrix_ixform(&ll,&ll,m);
  hpgs_matrix_ixform(&ur,&ur,m);

  hpgs_matrix_ixform(&lr,&lr,m);
  hpgs_matrix_ixform(&ul,&ul,m);

  res->llx = HPGS_MIN(HPGS_MIN(ll.x,ur.x),HPGS_MIN(lr.x,ul.x));
  res->lly = HPGS_MIN(HPGS_MIN(ll.y,ur.y),HPGS_MIN(lr.y,ul.y));

  res->urx = HPGS_MAX(HPGS_MAX(ll.x,ur.x),HPGS_MAX(lr.x,ul.x));
  res->ury = HPGS_MAX(HPGS_MAX(ll.y,ur.y),HPGS_MAX(lr.y,ul.y));
}
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
}
/* 
  Change the page matrix according to this content bounding box.
*/
void hpgs_reader_set_page_matrix (hpgs_reader *reader, const hpgs_bbox *bb)
{
  hpgs_bbox rbb;
  double xscale,yscale;
  hpgs_point rcp;

  hpgs_matrix_ixform(&rcp,&reader->current_point,&reader->page_matrix);
  
  // save the content bounding box for propagating it to the
  // page_asset function.
  reader->content_bbox = *bb;

  if  (reader->page_mode == 0)
    {
      reader->page_bbox = *bb;
      hpgs_matrix_set_identity(&reader->page_matrix);
      reader->page_scale = 1.0;
      goto restore_cb;
    }

  reader->page_matrix.mxx =  cos(reader->page_angle * M_PI / 180.0);
  reader->page_matrix.mxy = -sin(reader->page_angle * M_PI / 180.0);

  reader->page_matrix.myx =  sin(reader->page_angle * M_PI / 180.0);
  reader->page_matrix.myy =  cos(reader->page_angle * M_PI / 180.0);
  
  reader->page_matrix.dx = 0.0;
  reader->page_matrix.dy = 0.0;

  if (reader->page_mode == 2) // dynamic page.
    {
      hpgs_matrix_xform_bbox(&rbb,&reader->page_matrix,bb);

      reader->page_bbox.llx = 0.0;
      reader->page_bbox.lly = 0.0;

      reader->page_bbox.urx = (rbb.urx-rbb.llx) + 2.0 * reader->page_border;
      reader->page_bbox.ury = (rbb.ury-rbb.lly) + 2.0 * reader->page_border;

      reader->page_matrix.dx = reader->page_border - rbb.llx;
      reader->page_matrix.dy = reader->page_border - rbb.lly;

      // do we fit on the maximal page size?
      if ((reader->page_width <= 0.0 || reader->page_bbox.urx <= reader->page_width) &&
          (reader->page_height <= 0.0 || reader->page_bbox.ury <= reader->page_height) )
        {
          reader->page_scale = 1.0;
          goto restore_cb;
        }

      if (reader->page_bbox.urx > reader->page_width)
        xscale = reader->page_width/reader->page_bbox.urx;
      else
        xscale = 1.0;

      if (reader->page_bbox.ury> reader->page_height)
        yscale = reader->page_height/reader->page_bbox.ury;
      else
        yscale = 1.0;

      reader->page_scale = HPGS_MIN(xscale,yscale);

      double rscale = 0.0;
      double xx = 1.0;

      // transform the scale to a human-interceptable scale.
      do
        {
          xx *= 0.1;
          rscale = floor(reader->page_scale / xx);
        }
      while (rscale < 2.0);

      reader->page_scale = rscale * xx;

      reader->page_matrix.mxx *= reader->page_scale;
      reader->page_matrix.mxy *= reader->page_scale;

      reader->page_matrix.myx *= reader->page_scale;
      reader->page_matrix.myy *= reader->page_scale;

      reader->page_matrix.dx *= reader->page_scale;
      reader->page_matrix.dy *= reader->page_scale;

      reader->page_bbox.urx *= reader->page_scale;
      reader->page_bbox.ury *= reader->page_scale;

      goto restore_cb;
    }

  // fixed page.
  reader->page_bbox.llx = 0.0;
  reader->page_bbox.lly = 0.0;

  reader->page_bbox.urx = reader->page_width;
  reader->page_bbox.ury = reader->page_height;

  hpgs_matrix_xform_bbox(&rbb,&reader->page_matrix,bb);

  xscale = (reader->page_width - 2.0 * reader->page_border) / (rbb.urx-rbb.llx);
  yscale = (reader->page_height - 2.0 * reader->page_border) / (rbb.ury-rbb.lly);
  
  reader->page_scale = HPGS_MIN(xscale,yscale);

  reader->page_matrix.mxx *= reader->page_scale;
  reader->page_matrix.mxy *= reader->page_scale;
  
  reader->page_matrix.myx *= reader->page_scale;
  reader->page_matrix.myy *= reader->page_scale;
  
  if (reader->page_scale == xscale)
    {
      reader->page_matrix.dx = reader->page_border - reader->page_scale * rbb.llx;
      reader->page_matrix.dy =
        0.5 * (reader->page_height - reader->page_scale * (rbb.ury-rbb.lly)) - reader->page_scale * rbb.lly;
    }
  else
    {
      reader->page_matrix.dx = 
        0.5 * (reader->page_width - reader->page_scale * (rbb.urx-rbb.llx)) - reader->page_scale * rbb.llx;
      reader->page_matrix.dy = reader->page_border - reader->page_scale * rbb.lly;
    }

 restore_cb:
  hpgs_matrix_xform(&reader->current_point,&reader->page_matrix,&rcp);
}