gscoord.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540
  1. /* Copyright (C) 1989, 2000 Aladdin Enterprises. All rights reserved.
  2. This software is provided AS-IS with no warranty, either express or
  3. implied.
  4. This software is distributed under license and may not be copied,
  5. modified or distributed except as expressly authorized under the terms
  6. of the license contained in the file LICENSE in this distribution.
  7. For more information about licensing, please refer to
  8. http://www.ghostscript.com/licensing/. For information on
  9. commercial licensing, go to http://www.artifex.com/licensing/ or
  10. contact Artifex Software, Inc., 101 Lucas Valley Road #110,
  11. San Rafael, CA 94903, U.S.A., +1(415)492-9861.
  12. */
  13. /* $Id: gscoord.c,v 1.9 2004/03/13 18:28:52 igor Exp $ */
  14. /* Coordinate system operators for Ghostscript library */
  15. #include "math_.h"
  16. #include "gx.h"
  17. #include "gserrors.h"
  18. #include "gsccode.h" /* for gxfont.h */
  19. #include "gxfarith.h"
  20. #include "gxfixed.h"
  21. #include "gxmatrix.h"
  22. #include "gxfont.h" /* for char_tm */
  23. #include "gxpath.h" /* for gx_path_translate */
  24. #include "gzstate.h"
  25. #include "gxcoord.h" /* requires gsmatrix, gsstate */
  26. #include "gxdevice.h"
  27. /* Choose whether to enable the rounding code in update_ctm. */
  28. #define ROUND_CTM_FIXED 1
  29. /* Forward declarations */
  30. #ifdef DEBUG
  31. #define trace_ctm(pgs) trace_matrix_fixed(&(pgs)->ctm)
  32. private void trace_matrix_fixed(const gs_matrix_fixed *);
  33. private void trace_matrix(const gs_matrix *);
  34. #endif
  35. /* Macro for ensuring ctm_inverse is valid */
  36. #ifdef DEBUG
  37. # define print_inverse(pgs)\
  38. if ( gs_debug_c('x') )\
  39. dlprintf("[x]Inverting:\n"), trace_ctm(pgs), trace_matrix(&pgs->ctm_inverse)
  40. #else
  41. # define print_inverse(pgs) DO_NOTHING
  42. #endif
  43. #define ensure_inverse_valid(pgs)\
  44. if ( !pgs->ctm_inverse_valid )\
  45. { int code = ctm_set_inverse(pgs);\
  46. if ( code < 0 ) return code;\
  47. }
  48. private int
  49. ctm_set_inverse(gs_state * pgs)
  50. {
  51. int code = gs_matrix_invert(&ctm_only(pgs), &pgs->ctm_inverse);
  52. print_inverse(pgs);
  53. if (code < 0)
  54. return code;
  55. pgs->ctm_inverse_valid = true;
  56. return 0;
  57. }
  58. /* Machinery for updating fixed version of ctm. */
  59. /*
  60. * We (conditionally) adjust the floating point translation
  61. * so that it exactly matches the (rounded) fixed translation.
  62. * This avoids certain unpleasant rounding anomalies, such as
  63. * 0 0 moveto currentpoint not returning 0 0, and () stringwidth
  64. * not returning 0 0.
  65. */
  66. #if ROUND_CTM_FIXED
  67. # define update_t_fixed(mat, t, t_fixed, v)\
  68. (set_float2fixed_vars((mat).t_fixed, v),\
  69. set_fixed2float_var((mat).t, (mat).t_fixed))
  70. #else /* !ROUND_CTM_FIXED */
  71. # define update_t_fixed(mat, t, t_fixed, v)\
  72. ((mat).t = (v),\
  73. set_float2fixed_vars((mat).t_fixed, (mat).t))
  74. #endif /* (!)ROUND_CTM_FIXED */
  75. #define f_fits_in_fixed(f) f_fits_in_bits(f, fixed_int_bits)
  76. #define update_matrix_fixed(mat, xt, yt)\
  77. ((mat).txy_fixed_valid = (f_fits_in_fixed(xt) && f_fits_in_fixed(yt) ?\
  78. (update_t_fixed(mat, tx, tx_fixed, xt),\
  79. update_t_fixed(mat, ty, ty_fixed, yt), true) :\
  80. ((mat).tx = (xt), (mat).ty = (yt), false)))
  81. #define update_ctm(pgs, xt, yt)\
  82. (pgs->ctm_inverse_valid = false,\
  83. pgs->char_tm_valid = false,\
  84. update_matrix_fixed(pgs->ctm, xt, yt))
  85. /* ------ Coordinate system definition ------ */
  86. int
  87. gs_initmatrix(gs_state * pgs)
  88. {
  89. gs_matrix imat;
  90. gs_defaultmatrix(pgs, &imat);
  91. update_ctm(pgs, imat.tx, imat.ty);
  92. set_ctm_only(pgs, imat);
  93. #ifdef DEBUG
  94. if (gs_debug_c('x'))
  95. dlprintf("[x]initmatrix:\n"), trace_ctm(pgs);
  96. #endif
  97. return 0;
  98. }
  99. int
  100. gs_defaultmatrix(const gs_state * pgs, gs_matrix * pmat)
  101. {
  102. gx_device *dev;
  103. if (pgs->ctm_default_set) { /* set after Install */
  104. *pmat = pgs->ctm_default;
  105. return 1;
  106. }
  107. dev = gs_currentdevice_inline(pgs);
  108. gs_deviceinitialmatrix(dev, pmat);
  109. /* Add in the translation for the Margins. */
  110. pmat->tx += dev->Margins[0] *
  111. dev->HWResolution[0] / dev->MarginsHWResolution[0];
  112. pmat->ty += dev->Margins[1] *
  113. dev->HWResolution[1] / dev->MarginsHWResolution[1];
  114. return 0;
  115. }
  116. int
  117. gs_setdefaultmatrix(gs_state * pgs, const gs_matrix * pmat)
  118. {
  119. if (pmat == NULL)
  120. pgs->ctm_default_set = false;
  121. else {
  122. pgs->ctm_default = *pmat;
  123. pgs->ctm_default_set = true;
  124. }
  125. return 0;
  126. }
  127. int
  128. gs_currentmatrix(const gs_state * pgs, gs_matrix * pmat)
  129. {
  130. *pmat = ctm_only(pgs);
  131. return 0;
  132. }
  133. /* Set the current transformation matrix for rendering text. */
  134. /* Note that this may be based on a font other than the current font. */
  135. int
  136. gs_setcharmatrix(gs_state * pgs, const gs_matrix * pmat)
  137. {
  138. gs_matrix cmat;
  139. int code = gs_matrix_multiply(pmat, &ctm_only(pgs), &cmat);
  140. if (code < 0)
  141. return code;
  142. update_matrix_fixed(pgs->char_tm, cmat.tx, cmat.ty);
  143. char_tm_only(pgs) = cmat;
  144. #ifdef DEBUG
  145. if (gs_debug_c('x'))
  146. dlprintf("[x]setting char_tm:"), trace_matrix_fixed(&pgs->char_tm);
  147. #endif
  148. pgs->char_tm_valid = true;
  149. return 0;
  150. }
  151. /* Read (after possibly computing) the current transformation matrix */
  152. /* for rendering text. If force=true, update char_tm if it is invalid; */
  153. /* if force=false, don't update char_tm, and return an error code. */
  154. int
  155. gs_currentcharmatrix(gs_state * pgs, gs_matrix * ptm, bool force)
  156. {
  157. if (!pgs->char_tm_valid) {
  158. int code;
  159. if (!force)
  160. return_error(gs_error_undefinedresult);
  161. code = gs_setcharmatrix(pgs, &pgs->font->FontMatrix);
  162. if (code < 0)
  163. return code;
  164. }
  165. if (ptm != NULL)
  166. *ptm = char_tm_only(pgs);
  167. return 0;
  168. }
  169. int
  170. gs_setmatrix(gs_state * pgs, const gs_matrix * pmat)
  171. {
  172. update_ctm(pgs, pmat->tx, pmat->ty);
  173. set_ctm_only(pgs, *pmat);
  174. #ifdef DEBUG
  175. if (gs_debug_c('x'))
  176. dlprintf("[x]setmatrix:\n"), trace_ctm(pgs);
  177. #endif
  178. return 0;
  179. }
  180. int
  181. gs_imager_setmatrix(gs_imager_state * pis, const gs_matrix * pmat)
  182. {
  183. update_matrix_fixed(pis->ctm, pmat->tx, pmat->ty);
  184. set_ctm_only(pis, *pmat);
  185. #ifdef DEBUG
  186. if (gs_debug_c('x'))
  187. dlprintf("[x]imager_setmatrix:\n"), trace_ctm(pis);
  188. #endif
  189. return 0;
  190. }
  191. int
  192. gs_settocharmatrix(gs_state * pgs)
  193. {
  194. if (pgs->char_tm_valid) {
  195. pgs->ctm = pgs->char_tm;
  196. pgs->ctm_inverse_valid = false;
  197. return 0;
  198. } else
  199. return_error(gs_error_undefinedresult);
  200. }
  201. int
  202. gs_translate(gs_state * pgs, floatp dx, floatp dy)
  203. {
  204. gs_point pt;
  205. int code;
  206. if ((code = gs_distance_transform(dx, dy, &ctm_only(pgs), &pt)) < 0)
  207. return code;
  208. pt.x += pgs->ctm.tx;
  209. pt.y += pgs->ctm.ty;
  210. update_ctm(pgs, pt.x, pt.y);
  211. #ifdef DEBUG
  212. if (gs_debug_c('x'))
  213. dlprintf4("[x]translate: %f %f -> %f %f\n",
  214. dx, dy, pt.x, pt.y),
  215. trace_ctm(pgs);
  216. #endif
  217. return 0;
  218. }
  219. int
  220. gs_scale(gs_state * pgs, floatp sx, floatp sy)
  221. {
  222. pgs->ctm.xx *= sx;
  223. pgs->ctm.xy *= sx;
  224. pgs->ctm.yx *= sy;
  225. pgs->ctm.yy *= sy;
  226. pgs->ctm_inverse_valid = false, pgs->char_tm_valid = false;
  227. #ifdef DEBUG
  228. if (gs_debug_c('x'))
  229. dlprintf2("[x]scale: %f %f\n", sx, sy), trace_ctm(pgs);
  230. #endif
  231. return 0;
  232. }
  233. int
  234. gs_rotate(gs_state * pgs, floatp ang)
  235. {
  236. int code = gs_matrix_rotate(&ctm_only(pgs), ang,
  237. &ctm_only_writable(pgs));
  238. pgs->ctm_inverse_valid = false, pgs->char_tm_valid = false;
  239. #ifdef DEBUG
  240. if (gs_debug_c('x'))
  241. dlprintf1("[x]rotate: %f\n", ang), trace_ctm(pgs);
  242. #endif
  243. return code;
  244. }
  245. int
  246. gs_concat(gs_state * pgs, const gs_matrix * pmat)
  247. {
  248. gs_matrix cmat;
  249. int code = gs_matrix_multiply(pmat, &ctm_only(pgs), &cmat);
  250. if (code < 0)
  251. return code;
  252. update_ctm(pgs, cmat.tx, cmat.ty);
  253. set_ctm_only(pgs, cmat);
  254. #ifdef DEBUG
  255. if (gs_debug_c('x'))
  256. dlprintf("[x]concat:\n"), trace_matrix(pmat), trace_ctm(pgs);
  257. #endif
  258. return code;
  259. }
  260. /* ------ Coordinate transformation ------ */
  261. #define is_skewed(pmat) (!(is_xxyy(pmat) || is_xyyx(pmat)))
  262. int
  263. gs_transform(gs_state * pgs, floatp x, floatp y, gs_point * pt)
  264. {
  265. return gs_point_transform(x, y, &ctm_only(pgs), pt);
  266. }
  267. int
  268. gs_dtransform(gs_state * pgs, floatp dx, floatp dy, gs_point * pt)
  269. {
  270. return gs_distance_transform(dx, dy, &ctm_only(pgs), pt);
  271. }
  272. int
  273. gs_itransform(gs_state * pgs, floatp x, floatp y, gs_point * pt)
  274. { /* If the matrix isn't skewed, we get more accurate results */
  275. /* by using transform_inverse than by using the inverse matrix. */
  276. if (!is_skewed(&pgs->ctm)) {
  277. return gs_point_transform_inverse(x, y, &ctm_only(pgs), pt);
  278. } else {
  279. ensure_inverse_valid(pgs);
  280. return gs_point_transform(x, y, &pgs->ctm_inverse, pt);
  281. }
  282. }
  283. int
  284. gs_idtransform(gs_state * pgs, floatp dx, floatp dy, gs_point * pt)
  285. { /* If the matrix isn't skewed, we get more accurate results */
  286. /* by using transform_inverse than by using the inverse matrix. */
  287. if (!is_skewed(&pgs->ctm)) {
  288. return gs_distance_transform_inverse(dx, dy,
  289. &ctm_only(pgs), pt);
  290. } else {
  291. ensure_inverse_valid(pgs);
  292. return gs_distance_transform(dx, dy, &pgs->ctm_inverse, pt);
  293. }
  294. }
  295. int
  296. gs_imager_idtransform(const gs_imager_state * pis, floatp dx, floatp dy,
  297. gs_point * pt)
  298. {
  299. return gs_distance_transform_inverse(dx, dy, &ctm_only(pis), pt);
  300. }
  301. /* ------ For internal use only ------ */
  302. /* Set the translation to a fixed value, and translate any existing path. */
  303. /* Used by gschar.c to prepare for a BuildChar or BuildGlyph procedure. */
  304. int
  305. gx_translate_to_fixed(register gs_state * pgs, fixed px, fixed py)
  306. {
  307. double fpx = fixed2float(px);
  308. double fdx = fpx - pgs->ctm.tx;
  309. double fpy = fixed2float(py);
  310. double fdy = fpy - pgs->ctm.ty;
  311. fixed dx, dy;
  312. int code;
  313. if (pgs->ctm.txy_fixed_valid) {
  314. dx = float2fixed(fdx);
  315. dy = float2fixed(fdy);
  316. code = gx_path_translate(pgs->path, dx, dy);
  317. if (code < 0)
  318. return code;
  319. if (pgs->char_tm_valid && pgs->char_tm.txy_fixed_valid)
  320. pgs->char_tm.tx_fixed += dx,
  321. pgs->char_tm.ty_fixed += dy;
  322. } else {
  323. if (!gx_path_is_null(pgs->path))
  324. return_error(gs_error_limitcheck);
  325. }
  326. pgs->ctm.tx = fpx;
  327. pgs->ctm.tx_fixed = px;
  328. pgs->ctm.ty = fpy;
  329. pgs->ctm.ty_fixed = py;
  330. pgs->ctm.txy_fixed_valid = true;
  331. pgs->ctm_inverse_valid = false;
  332. if (pgs->char_tm_valid) { /* Update char_tm now, leaving it valid. */
  333. pgs->char_tm.tx += fdx;
  334. pgs->char_tm.ty += fdy;
  335. }
  336. #ifdef DEBUG
  337. if (gs_debug_c('x')) {
  338. dlprintf2("[x]translate_to_fixed %g, %g:\n",
  339. fixed2float(px), fixed2float(py));
  340. trace_ctm(pgs);
  341. dlprintf("[x] char_tm:\n");
  342. trace_matrix_fixed(&pgs->char_tm);
  343. }
  344. #endif
  345. gx_setcurrentpoint(pgs, fixed2float(pgs->ctm.tx_fixed), fixed2float(pgs->ctm.ty_fixed));
  346. pgs->current_point_valid = true;
  347. return 0;
  348. }
  349. /* Scale the CTM and character matrix for oversampling. */
  350. int
  351. gx_scale_char_matrix(register gs_state * pgs, int sx, int sy)
  352. {
  353. #define scale_cxy(s, vx, vy)\
  354. if ( s != 1 )\
  355. { pgs->ctm.vx *= s;\
  356. pgs->ctm.vy *= s;\
  357. pgs->ctm_inverse_valid = false;\
  358. if ( pgs->char_tm_valid )\
  359. { pgs->char_tm.vx *= s;\
  360. pgs->char_tm.vy *= s;\
  361. }\
  362. }
  363. scale_cxy(sx, xx, yx);
  364. scale_cxy(sy, xy, yy);
  365. #undef scale_cxy
  366. if_debug2('x', "[x]char scale: %d %d\n", sx, sy);
  367. return 0;
  368. }
  369. /* Compute the coefficients for fast fixed-point distance transformations */
  370. /* from a transformation matrix. */
  371. /* We should cache the coefficients with the ctm.... */
  372. int
  373. gx_matrix_to_fixed_coeff(const gs_matrix * pmat, register fixed_coeff * pfc,
  374. int max_bits)
  375. {
  376. gs_matrix ctm;
  377. int scale = -10000;
  378. int expt, shift;
  379. ctm = *pmat;
  380. pfc->skewed = 0;
  381. if (!is_fzero(ctm.xx)) {
  382. discard(frexp(ctm.xx, &scale));
  383. }
  384. if (!is_fzero(ctm.xy)) {
  385. discard(frexp(ctm.xy, &expt));
  386. if (expt > scale)
  387. scale = expt;
  388. pfc->skewed = 1;
  389. }
  390. if (!is_fzero(ctm.yx)) {
  391. discard(frexp(ctm.yx, &expt));
  392. if (expt > scale)
  393. scale = expt;
  394. pfc->skewed = 1;
  395. }
  396. if (!is_fzero(ctm.yy)) {
  397. discard(frexp(ctm.yy, &expt));
  398. if (expt > scale)
  399. scale = expt;
  400. }
  401. /*
  402. * There are two multiplications in fixed_coeff_mult: one involves a
  403. * factor that may have max_bits significant bits, the other may have
  404. * fixed_fraction_bits (_fixed_shift) bits. Ensure that neither one
  405. * will overflow.
  406. */
  407. if (max_bits < fixed_fraction_bits)
  408. max_bits = fixed_fraction_bits;
  409. scale = sizeof(long) * 8 - 1 - max_bits - scale;
  410. shift = scale - _fixed_shift;
  411. if (shift > 0) {
  412. pfc->shift = shift;
  413. pfc->round = (fixed) 1 << (shift - 1);
  414. } else {
  415. pfc->shift = 0;
  416. pfc->round = 0;
  417. scale -= shift;
  418. }
  419. #define SET_C(c)\
  420. if ( is_fzero(ctm.c) ) pfc->c = 0;\
  421. else pfc->c = (long)ldexp(ctm.c, scale)
  422. SET_C(xx);
  423. SET_C(xy);
  424. SET_C(yx);
  425. SET_C(yy);
  426. #undef SET_C
  427. #ifdef DEBUG
  428. if (gs_debug_c('x')) {
  429. dlprintf6("[x]ctm: [%6g %6g %6g %6g %6g %6g]\n",
  430. ctm.xx, ctm.xy, ctm.yx, ctm.yy, ctm.tx, ctm.ty);
  431. dlprintf6(" scale=%d fc: [0x%lx 0x%lx 0x%lx 0x%lx] shift=%d\n",
  432. scale, pfc->xx, pfc->xy, pfc->yx, pfc->yy,
  433. pfc->shift);
  434. }
  435. #endif
  436. pfc->max_bits = max_bits;
  437. return 0;
  438. }
  439. /*
  440. * Handle the case of a large value or a value with a fraction part.
  441. * See gxmatrix.h for more details.
  442. */
  443. fixed
  444. fixed_coeff_mult(fixed value, long coeff, const fixed_coeff *pfc, int maxb)
  445. {
  446. int shift = pfc->shift;
  447. /*
  448. * Test if the value is too large for simple long math.
  449. */
  450. if ((value + (fixed_1 << (maxb - 1))) & (-fixed_1 << maxb)) {
  451. /* The second argument of fixed_mult_quo must be non-negative. */
  452. return
  453. (coeff < 0 ?
  454. -fixed_mult_quo(value, -coeff, fixed_1 << shift) :
  455. fixed_mult_quo(value, coeff, fixed_1 << shift));
  456. } else {
  457. /*
  458. * The construction above guarantees that the multiplications
  459. * won't overflow the capacity of an int.
  460. */
  461. return (fixed)
  462. arith_rshift(fixed2int_var(value) * coeff
  463. + fixed2int(fixed_fraction(value) * coeff)
  464. + pfc->round, shift);
  465. }
  466. }
  467. /* ------ Debugging printout ------ */
  468. #ifdef DEBUG
  469. /* Print a matrix */
  470. private void
  471. trace_matrix_fixed(const gs_matrix_fixed * pmat)
  472. {
  473. trace_matrix((const gs_matrix *)pmat);
  474. if (pmat->txy_fixed_valid) {
  475. dprintf2("\t\tt_fixed: [%6g %6g]\n",
  476. fixed2float(pmat->tx_fixed),
  477. fixed2float(pmat->ty_fixed));
  478. } else {
  479. dputs("\t\tt_fixed not valid\n");
  480. }
  481. }
  482. private void
  483. trace_matrix(register const gs_matrix * pmat)
  484. {
  485. dlprintf6("\t[%6g %6g %6g %6g %6g %6g]\n",
  486. pmat->xx, pmat->xy, pmat->yx, pmat->yy, pmat->tx, pmat->ty);
  487. }
  488. #endif