~ubuntu-branches/ubuntu/jaunty/ghostscript/jaunty-updates

« back to all changes in this revision

Viewing changes to base/gscoord.c

  • Committer: Bazaar Package Importer
  • Author(s): Till Kamppeter
  • Date: 2009-01-20 16:40:45 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20090120164045-lnfhi0n30o5lwhwa
Tags: 8.64.dfsg.1~svn9377-0ubuntu1
* New upstream release (SVN rev 9377)
   o Fixes many bugs concerning PDF rendering, to make the PDF printing
     workflow correctly working.
   o Fixes long-standing bugs in many drivers, like input paper tray and
     duplex options not working for the built-in PCL 4, 5, 5c, 5e, and
     6/XL drivers, PDF input not working for bjc600, bjc800, and cups
     output devices, several options not working and uninitialized
     memory with cups output device.
   o Merged nearly all patches of the Ubuntu and Debian packages upstream.
   o Fixes LP: #317810, LP: #314439, LP: #314018.
* debian/patches/03_libpaper_support.dpatch,
  debian/patches/11_gs-cjk_font_glyph_handling_fix.dpatch,
  debian/patches/12_gs-cjk_vertical_writing_metrics_fix.dpatch,
  debian/patches/13_gs-cjk_cjkps_examples.dpatch,
  debian/patches/20_bbox_segv_fix.dpatch,
  debian/patches/21_brother_7x0_gdi_fix.dpatch,
  debian/patches/22_epsn_margin_workaround.dpatch,
  debian/patches/24_gs_man_fix.dpatch,
  debian/patches/25_toolbin_insecure_tmp_usage_fix.dpatch,
  debian/patches/26_assorted_script_fixes.dpatch,
  debian/patches/29_gs_css_fix.dpatch,
  debian/patches/30_ps2pdf_man_improvement.dpatch,
  debian/patches/31_fix-gc-sigbus.dpatch,
  debian/patches/34_ftbfs-on-hurd-fix.dpatch,
  debian/patches/35_disable_libcairo.dpatch,
  debian/patches/38_pxl-duplex.dpatch,
  debian/patches/39_pxl-resolution.dpatch,
  debian/patches/42_gs-init-ps-delaybind-fix.dpatch,
  debian/patches/45_bjc600-bjc800-pdf-input.dpatch,
  debian/patches/48_cups-output-device-pdf-duplex-uninitialized-memory-fix.dpatch,
  debian/patches/50_lips4-floating-point-exception.dpatch,
  debian/patches/52_cups-device-logging.dpatch,
  debian/patches/55_pcl-input-slot-fix.dpatch,
  debian/patches/57_pxl-input-slot-fix.dpatch,
  debian/patches/60_pxl-cups-driver-pdf.dpatch,
  debian/patches/62_onebitcmyk-pdf.dpatch,
  debian/patches/65_too-big-temp-files-1.dpatch,
  debian/patches/67_too-big-temp-files-2.dpatch,
  debian/patches/70_take-into-account-data-in-stream-buffer-before-refill.dpatch:
  Removed, applied upstream.
* debian/patches/01_docdir_fix_for_debian.dpatch,
  debian/patches/02_gs_man_fix_debian.dpatch,
  debian/patches/01_docdir-fix-for-debian.dpatch,
  debian/patches/02_docdir-fix-for-debian.dpatch: Renamed patches to
  make merging with Debian easier.
* debian/patches/32_improve-handling-of-media-size-changes-from-gv.dpatch, 
  debian/patches/33_bad-params-to-xinitimage-on-large-bitmaps.dpatch:
  regenerated for new source directory structure.
* debian/rules: Corrected paths to remove cidfmap (it is in Resource/Init/
  in GS 8.64) and to install headers (source paths are psi/ and base/ now).
* debian/rules: Remove all fontmaps, as DeFoMa replaces them.
* debian/local/pdftoraster/pdftoraster.c,
  debian/local/pdftoraster/pdftoraster.convs, debian/rules: Removed
  added pdftoraster filter and use the one which comes with Ghostscript.
* debian/ghostscript.links: s/8.63/8.64/

Show diffs side-by-side

added added

removed removed

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