home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / g / gs252src.zip / GS252 / GSCOORD.C < prev    next >
C/C++ Source or Header  |  1992-09-15  |  9KB  |  317 lines

  1. /* Copyright (C) 1989, 1992 Aladdin Enterprises.  All rights reserved.
  2.    Distributed by Free Software Foundation, Inc.
  3.  
  4. This file is part of Ghostscript.
  5.  
  6. Ghostscript is distributed in the hope that it will be useful, but
  7. WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  8. to anyone for the consequences of using it or for whether it serves any
  9. particular purpose or works at all, unless he says so in writing.  Refer
  10. to the Ghostscript General Public License for full details.
  11.  
  12. Everyone is granted permission to copy, modify and redistribute
  13. Ghostscript, but only under the conditions described in the Ghostscript
  14. General Public License.  A copy of this license is supposed to have been
  15. given to you along with Ghostscript so you can know your rights and
  16. responsibilities.  It should be in a file named COPYING.  Among other
  17. things, the copyright notice and this notice must be preserved on all
  18. copies.  */
  19.  
  20. /* gscoord.c */
  21. /* Coordinate system operators for Ghostscript library */
  22. #include "math_.h"
  23. #include "gx.h"
  24. #include "gserrors.h"
  25. #include "gxarith.h"
  26. #include "gxfixed.h"
  27. #include "gxmatrix.h"
  28. #include "gzstate.h"
  29. #include "gzdevice.h"            /* requires gsstate */
  30. #include "gscoord.h"            /* requires gsmatrix, gsstate */
  31.  
  32. /* Choose whether to enable the new rounding code in update_ctm_fixed. */
  33. /* I'm pretty sure this is the right thing to do, but since this change */
  34. /* is being made 1 day before releasing version 2.4, I'm feeling cautious. */
  35. #define round_ctm_fixed 1
  36.  
  37. /* Forward declarations */
  38. #ifdef DEBUG
  39. private void trace_ctm(P1(const gs_state *));
  40. private void trace_matrix(P1(const gs_matrix *));
  41. #endif
  42.  
  43. /* Macro for ensuring ctm_inverse is valid */
  44. #ifdef DEBUG
  45. #define print_inverse(pgs)\
  46. if ( gs_debug['x'] )\
  47.     dprintf("[x]Inverting:\n"), trace_ctm(pgs), trace_matrix(&pgs->ctm_inverse)
  48. #else
  49. #define print_inverse(pgs) 0
  50. #endif
  51. #define ensure_inverse_valid(pgs)\
  52.     if ( !pgs->inverse_valid )\
  53.        {    int code = ctm_set_inverse(pgs);\
  54.         if ( code < 0 ) return code;\
  55.        }
  56.  
  57. private int
  58. ctm_set_inverse(gs_state *pgs)
  59. {    int code = gs_matrix_invert(&ctm_only(pgs), &pgs->ctm_inverse);
  60.     print_inverse(pgs);
  61.     if ( code < 0 ) return code;
  62.     pgs->inverse_valid = 1;
  63.     return 0;
  64. }
  65.  
  66. /* Machinery for updating fixed version of ctm. */
  67. /*
  68.  * We (conditionally) adjust the floating point translation
  69.  * so that it exactly matches the (rounded) fixed translation.
  70.  * This avoids certain unpleasant rounding anomalies, such as
  71.  * 0 0 moveto currentpoint not returning 0 0, and () stringwidth
  72.  * not returning 0 0.
  73.  */
  74. #if round_ctm_fixed            /* ****** NOTA BENE ****** */
  75. #  define update_t_fixed(mat, t, t_fixed)\
  76.     (mat).t = fixed2float((mat).t_fixed = float2fixed((mat).t))
  77. #else                    /* !round_update_fixed */
  78. #  define update_t_fixed(mat, t, t_fixed)\
  79.     (mat).t_fixed = float2fixed((mat).t)
  80. #endif                    /* (!)round_update_fixed */
  81. #define update_matrix_fixed(mat)\
  82.   update_t_fixed(mat, tx, tx_fixed),\
  83.   update_t_fixed(mat, ty, ty_fixed)
  84. #define update_ctm(pgs)\
  85.   update_matrix_fixed(pgs->ctm),\
  86.   pgs->inverse_valid = 0,\
  87.   pgs->char_tm_valid = 0
  88.  
  89. void
  90. gs_update_matrix_fixed(gs_matrix_fixed *pmat)
  91. {    update_matrix_fixed(*pmat);
  92. }
  93.  
  94. /* ------ Coordinate system definition ------ */
  95.  
  96. int
  97. gs_initmatrix(gs_state *pgs)
  98. {    gx_device *dev = pgs->device->info;
  99.     (*dev->procs->get_initial_matrix)(dev, &ctm_only(pgs));
  100.     update_ctm(pgs);
  101. #ifdef DEBUG
  102. if ( gs_debug['x'] )
  103.     dprintf("[x]initmatrix:\n"), trace_ctm(pgs);
  104. #endif
  105.     return 0;
  106. }
  107.  
  108. int
  109. gs_defaultmatrix(const gs_state *pgs, gs_matrix *pmat)
  110. {    gx_device *dev = pgs->device->info;
  111.     (*dev->procs->get_initial_matrix)(dev, pmat);
  112.     return 0;
  113. }
  114.  
  115. int
  116. gs_currentmatrix(const gs_state *pgs, gs_matrix *pmat)
  117. {    *pmat = ctm_only(pgs);
  118.     return 0;
  119. }
  120.  
  121. int
  122. gs_setmatrix(gs_state *pgs, const gs_matrix *pmat)
  123. {    ctm_only(pgs) = *pmat;
  124.     update_ctm(pgs);
  125. #ifdef DEBUG
  126. if ( gs_debug['x'] )
  127.     dprintf("[x]setmatrix:\n"), trace_ctm(pgs);
  128. #endif
  129.     return 0;
  130. }
  131.  
  132. int
  133. gs_translate(gs_state *pgs, floatp dx, floatp dy)
  134. {    gs_point pt;
  135.     int code;
  136.     if ( (code = gs_distance_transform(dx, dy, &ctm_only(pgs), &pt)) < 0 )
  137.         return code;
  138.     pgs->ctm.tx += pt.x;
  139.     pgs->ctm.ty += pt.y;
  140.     update_ctm(pgs);
  141. #ifdef DEBUG
  142. if ( gs_debug['x'] )
  143.     dprintf4("[x]translate: %f %f -> %f %f\n",
  144.          dx, dy, pt.x, pt.y),
  145.     trace_ctm(pgs);
  146. #endif
  147.     return 0;
  148. }
  149.  
  150. int
  151. gs_scale(gs_state *pgs, floatp sx, floatp sy)
  152. {    pgs->ctm.xx *= sx;
  153.     pgs->ctm.xy *= sx;
  154.     pgs->ctm.yx *= sy;
  155.     pgs->ctm.yy *= sy;
  156.     pgs->inverse_valid = 0, pgs->char_tm_valid = 0;
  157. #ifdef DEBUG
  158. if ( gs_debug['x'] )
  159.     dprintf2("[x]scale: %f %f\n", sx, sy), trace_ctm(pgs);
  160. #endif
  161.     return 0;
  162. }
  163.  
  164. int
  165. gs_rotate(gs_state *pgs, floatp ang)
  166. {    int code = gs_matrix_rotate(&ctm_only(pgs), ang, &ctm_only(pgs));
  167.     pgs->inverse_valid = 0, pgs->char_tm_valid = 0;
  168. #ifdef DEBUG
  169. if ( gs_debug['x'] )
  170.     dprintf1("[x]rotate: %f\n", ang), trace_ctm(pgs);
  171. #endif
  172.     return code;
  173. }
  174.  
  175. int
  176. gs_concat(gs_state *pgs, const gs_matrix *pmat)
  177. {    int code = gs_matrix_multiply(pmat, &ctm_only(pgs), &ctm_only(pgs));
  178.     update_ctm(pgs);
  179. #ifdef DEBUG
  180. if ( gs_debug['x'] )
  181.     dprintf("[x]concat:\n"), trace_matrix(pmat), trace_ctm(pgs);
  182. #endif
  183.     return code;
  184. }
  185.  
  186. /* ------ Coordinate transformation ------ */
  187.  
  188. int
  189. gs_transform(gs_state *pgs, floatp x, floatp y, gs_point *pt)
  190. {    return gs_point_transform(x, y, &ctm_only(pgs), pt);
  191. }
  192.  
  193. int
  194. gs_dtransform(gs_state *pgs, floatp dx, floatp dy, gs_point *pt)
  195. {    return gs_distance_transform(dx, dy, &ctm_only(pgs), pt);
  196. }
  197.  
  198. int
  199. gs_itransform(gs_state *pgs, floatp x, floatp y, gs_point *pt)
  200. {    /* If the matrix isn't skewed, we get more accurate results */
  201.     /* by using transform_inverse than by using the inverse matrix. */
  202.     if ( !is_skewed(&pgs->ctm) )
  203.        {    return gs_point_transform_inverse(x, y, &ctm_only(pgs), pt);
  204.        }
  205.     else
  206.        {    ensure_inverse_valid(pgs);
  207.         return gs_point_transform(x, y, &pgs->ctm_inverse, pt);
  208.        }
  209. }
  210.  
  211. int
  212. gs_idtransform(gs_state *pgs, floatp dx, floatp dy, gs_point *pt)
  213. {    /* If the matrix isn't skewed, we get more accurate results */
  214.     /* by using transform_inverse than by using the inverse matrix. */
  215.     if ( !is_skewed(&pgs->ctm) )
  216.        {    return gs_distance_transform_inverse(dx, dy,
  217.                              &ctm_only(pgs), pt);
  218.        }
  219.     else
  220.        {    ensure_inverse_valid(pgs);
  221.         return gs_distance_transform(dx, dy, &pgs->ctm_inverse, pt);
  222.        }
  223. }
  224.  
  225. /* ------ For internal use only ------ */
  226.  
  227. /* Set the translation to a fixed value, */
  228. /* and mark char_tm as valid. */
  229. /* Used by gschar.c to prepare for a BuildChar procedure. */
  230. int
  231. gs_translate_to_fixed(register gs_state *pgs, fixed px, fixed py)
  232. {    pgs->ctm.tx = fixed2float(pgs->ctm.tx_fixed = px);
  233.     pgs->ctm.ty = fixed2float(pgs->ctm.ty_fixed = py);
  234.     pgs->inverse_valid = 0;
  235.     pgs->char_tm_valid = 1;
  236.     return 0;
  237. }
  238.  
  239. /* Compute the coefficients for fast fixed-point distance transformations */
  240. /* from a transformation matrix. */
  241. /* We should cache the coefficients with the ctm.... */
  242. int
  243. gx_matrix_to_fixed_coeff(const gs_matrix *pmat, register fixed_coeff *pfc,
  244.   int max_bits)
  245. {    gs_matrix ctm;
  246.     int scale = -10000;
  247.     int expt, shift;
  248.     ctm = *pmat;
  249.     pfc->skewed = 0;
  250.     if ( !is_fzero(ctm.xx) )
  251.        {    (void)frexp(ctm.xx, &scale);
  252.        }
  253.     if ( !is_fzero(ctm.xy) )
  254.        {    (void)frexp(ctm.xy, &expt);
  255.         if ( expt > scale ) scale = expt;
  256.         pfc->skewed = 1;
  257.        }
  258.     if ( !is_fzero(ctm.yx) )
  259.        {    (void)frexp(ctm.yx, &expt);
  260.         if ( expt > scale ) scale = expt;
  261.         pfc->skewed = 1;
  262.        }
  263.     if ( !is_fzero(ctm.yy) )
  264.        {    (void)frexp(ctm.yy, &expt);
  265.         if ( expt > scale ) scale = expt;
  266.        }
  267.     scale = sizeof(long) * 8 - 1 - max_bits - scale;
  268.     shift = scale - _fixed_shift;
  269.     if ( shift > 0 )
  270.        {    pfc->shift = shift;
  271.         pfc->round = (fixed)1 << (shift - 1);
  272.        }
  273.     else
  274.        {    pfc->shift = 0;
  275.         pfc->round = 0;
  276.         scale -= shift;
  277.        }
  278. #define set_c(c)\
  279.   if ( is_fzero(ctm.c) ) pfc->c.f = 0, pfc->c.l = 0;\
  280.   else pfc->c.f = ldexp(ctm.c, _fixed_shift), pfc->c.l = (long)ldexp(ctm.c, scale)
  281.     set_c(xx);
  282.     set_c(xy);
  283.     set_c(yx);
  284.     set_c(yy);
  285. #ifdef DEBUG
  286. if ( gs_debug['x'] )
  287.    {    dprintf7("[x]ctm: [%6g %6g %6g %6g ; %6g %6g] scale=%d\n",
  288.          ctm.xx, ctm.xy, ctm.yx, ctm.yy, ctm.tx, ctm.ty, scale);
  289.     dprintf5("   fc: [%lx %lx %lx %lx] shift=%d\n",
  290.          pfc->xx, pfc->xy, pfc->yx, pfc->yy,
  291.          pfc->shift);
  292.    }
  293. #endif
  294.     pfc->max_bits = max_bits;
  295.     return 0;
  296. }
  297.  
  298. /* ------ Debugging printout ------ */
  299.  
  300. #ifdef DEBUG
  301.  
  302. /* Print a matrix */
  303. private void
  304. trace_ctm(const gs_state *pgs)
  305. {    const gs_matrix_fixed *pmat = &pgs->ctm;
  306.     trace_matrix((gs_matrix *)pmat);
  307.     dprintf2("\t\tt_fixed: [%6g %6g]\n",
  308.          fixed2float(pmat->tx_fixed), fixed2float(pmat->ty_fixed));
  309. }
  310. private void
  311. trace_matrix(register const gs_matrix *pmat)
  312. {    dprintf6("\t[%6g %6g %6g %6g %6g %6g]\n",
  313.          pmat->xx, pmat->xy, pmat->yx, pmat->yy, pmat->tx, pmat->ty);
  314. }
  315.  
  316. #endif
  317.