home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1996 February / PCWK0296.iso / sharewar / dos / program / gs300sr1 / gs300sr1.exe / GSIMAGE.C < prev    next >
C/C++ Source or Header  |  1994-07-27  |  17KB  |  525 lines

  1. /* Copyright (C) 1989, 1992, 1993, 1994 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of Aladdin Ghostscript.
  4.   
  5.   Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  6.   or distributor accepts any responsibility for the consequences of using it,
  7.   or for whether it serves any particular purpose or works at all, unless he
  8.   or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  9.   License (the "License") for full details.
  10.   
  11.   Every copy of Aladdin Ghostscript must include a copy of the License,
  12.   normally in a plain ASCII text file named PUBLIC.  The License grants you
  13.   the right to copy, modify and redistribute Aladdin Ghostscript, but only
  14.   under certain conditions described in the License.  Among other things, the
  15.   License requires that the copyright notice and this notice be preserved on
  16.   all copies.
  17. */
  18.  
  19. /* gsimage.c */
  20. /* Image setup procedures for Ghostscript library */
  21. #include "gx.h"
  22. #include "memory_.h"
  23. #include "gpcheck.h"
  24. #include "gserrors.h"
  25. #include "gsstruct.h"
  26. #include "gxfixed.h"
  27. #include "gxfrac.h"
  28. #include "gxarith.h"
  29. #include "gxmatrix.h"
  30. #include "gsccolor.h"
  31. #include "gspaint.h"
  32. #include "gzstate.h"
  33. #include "gxdevice.h"
  34. #include "gzpath.h"
  35. #include "gxcpath.h"
  36. #include "gxdevmem.h"
  37. #include "gximage.h"
  38.  
  39. /* Structure descriptor */
  40. private_st_gs_image_enum();
  41.  
  42. /* GC procedures */
  43. #define eptr ((gs_image_enum *)vptr)
  44. private ENUM_PTRS_BEGIN(image_enum_enum_ptrs) {
  45.     int bps;
  46.     gs_ptr_type_t ret;
  47.     /* Enumerate the data planes. */
  48.     index -= 4;
  49.     if ( index < eptr->plane_index )
  50.       { *pep = (void *)&eptr->planes[index];
  51.         return ptr_string_type;
  52.       }
  53.     /* Enumerate the used members of dev_colors. */
  54.     if ( eptr->spp != 1 )    /* colorimage, dev_colors not used */
  55.       return 0;
  56.     index -= eptr->num_planes + 3;
  57.     bps = eptr->bps;
  58.     if ( bps > 8 ) bps = 1;
  59.     if ( index >= (1 << bps) * st_device_color_max_ptrs ) /* done */
  60.       return 0;
  61.     ret = (*st_device_color.enum_ptrs)
  62.       (&eptr->dev_colors[index * (255 / ((1 << bps) - 1))],
  63.        sizeof(eptr->dev_colors[0]),
  64.        index % st_device_color_max_ptrs, pep);
  65.     if ( ret == 0 )        /* don't stop early */
  66.       { *pep = 0;
  67.         break;
  68.       }
  69.     return ret;
  70.     }
  71.     ENUM_PTR(0, gs_image_enum, pgs);
  72.     ENUM_PTR(1, gs_image_enum, buffer);
  73.     ENUM_PTR(2, gs_image_enum, line);
  74.     ENUM_PTR(3, gs_image_enum, clip_dev);
  75. ENUM_PTRS_END
  76. private RELOC_PTRS_BEGIN(image_enum_reloc_ptrs) {
  77.     int i;
  78.     RELOC_PTR(gs_image_enum, pgs);
  79.     RELOC_PTR(gs_image_enum, buffer);
  80.     RELOC_PTR(gs_image_enum, line);
  81.     RELOC_PTR(gs_image_enum, clip_dev);
  82.     for ( i = 0; i < eptr->plane_index; i++ )
  83.       RELOC_CONST_STRING_PTR(gs_image_enum, planes[i]);
  84.     if ( eptr->spp == 1 )
  85.       { int bps = eptr->bps;
  86.         if ( bps > 8 ) bps = 1;
  87.         for ( i = 0; i <= 255; i += 255 / ((1 << bps) - 1) )
  88.           (*st_device_color.reloc_ptrs)
  89.         (&eptr->dev_colors[i], sizeof(gx_device_color), gcst);
  90.       }
  91. } RELOC_PTRS_END
  92. #undef eptr
  93.  
  94. /* Forward declarations */
  95. private void image_init_map(P3(byte *, int, const float *));
  96. private int image_init(P9(gs_image_enum *, int, int, int,
  97.   int, int, gs_matrix *, gs_state *, fixed));
  98. /* Procedures for unpacking the input data into bytes or fracs. */
  99. extern iunpack_proc(image_unpack_1);
  100. extern iunpack_proc(image_unpack_1_spread);
  101. extern iunpack_proc(image_unpack_2);
  102. extern iunpack_proc(image_unpack_2_spread);
  103. extern iunpack_proc(image_unpack_4);
  104. extern iunpack_proc(image_unpack_8);
  105. extern iunpack_proc(image_unpack_8_spread);
  106. extern iunpack_proc(image_unpack_12);
  107. /* The image_render procedures work on fully expanded, complete rows. */
  108. /* These take a height argument, which is an integer > 0; */
  109. /* they return a negative code, or the number of */
  110. /* rows actually processed (which may be less than the height). */
  111. extern irender_proc(image_render_skip);
  112. extern irender_proc(image_render_simple);
  113. extern irender_proc(image_render_mono);
  114. extern irender_proc(image_render_color);
  115. extern irender_proc(image_render_frac);
  116.  
  117. /* Standard mask tables for spreading input data. */
  118. /* Note that the mask tables depend on the end-orientation of the CPU. */
  119. /* We can't simply define them as byte arrays, because */
  120. /* they might not wind up properly long- or short-aligned. */
  121. #define map4tox(z,a,b,c,d)\
  122.     z, z^a, z^b, z^(a+b),\
  123.     z^c, z^(a+c), z^(b+c), z^(a+b+c),\
  124.     z^d, z^(a+d), z^(b+d), z^(a+b+d),\
  125.     z^(c+d), z^(a+c+d), z^(b+c+d), z^(a+b+c+d)
  126. #if arch_is_big_endian
  127. private const bits32 map_4x1_to_32[16] =
  128.    {    map4tox(0L, 0xffL, 0xff00L, 0xff0000L, 0xff000000L)    };
  129. private const bits32 map_4x1_to_32_invert[16] =
  130.    {    map4tox(0xffffffffL, 0xffL, 0xff00L, 0xff0000L, 0xff000000L)    };
  131. #else                    /* !arch_is_big_endian */
  132. private const bits32 map_4x1_to_32[16] =
  133.    {    map4tox(0L, 0xff000000L, 0xff0000L, 0xff00L, 0xffL)    };
  134. private const bits32 map_4x1_to_32_invert[16] =
  135.    {    map4tox(0xffffffffL, 0xff000000L, 0xff0000L, 0xff00L, 0xffL)    };
  136. #endif
  137.  
  138. /* Allocate an image enumerator. */
  139. gs_image_enum *
  140. gs_image_enum_alloc(gs_memory_t *mem, client_name_t cname)
  141. {    return gs_alloc_struct(mem, gs_image_enum, &st_gs_image_enum, cname);
  142. }
  143.  
  144. /* Start processing an image */
  145. int
  146. gs_image_init(gs_image_enum *penum, gs_state *pgs,
  147.   int width, int height, int bps,
  148.   bool multi, const gs_color_space *pcs, const float *decode /* [spp*2] */,
  149.   gs_matrix *pmat)
  150. {    const gs_color_space_type _ds *pcst = pcs->type;
  151.     int spp = pcst->num_components;
  152.     int ci;
  153.     int device_color;
  154.     static const float default_decode[8] =
  155.         { 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0 };
  156.     if ( pgs->in_cachedevice )
  157.         return_error(gs_error_undefined);
  158.     if ( spp < 0 )            /* Pattern not allowed */
  159.         return_error(gs_error_rangecheck);
  160.     if ( decode == 0 )
  161.         decode = default_decode;
  162.     switch ( pcst->index )
  163.     {
  164.     case gs_color_space_index_DeviceGray:
  165.     case gs_color_space_index_DeviceRGB:
  166.     case gs_color_space_index_DeviceCMYK:
  167.         device_color = 1;
  168.         break;
  169.     default:        /* not a device color space */
  170.         device_color = 0;
  171.     }
  172.  
  173.     if ( spp == 1 )
  174.     {    /* Initialize the color table */
  175. #define ictype(i)\
  176.   penum->dev_colors[i].type
  177.         switch ( bps )
  178.         {
  179.         case 8:
  180.         {    register gx_device_color *pcht =
  181.                &penum->dev_colors[0];
  182.             register int n = 64;
  183.             do
  184.             {    pcht[0].type = pcht[1].type =
  185.                   pcht[2].type = pcht[3].type =
  186.                   &gx_dc_none;
  187.                 pcht += 4;
  188.             }
  189.             while ( --n > 0 );
  190.             break;
  191.         }
  192.         case 4:
  193.             ictype(17) = ictype(2*17) = ictype(3*17) =
  194.               ictype(4*17) = ictype(6*17) = ictype(7*17) =
  195.               ictype(8*17) = ictype(9*17) = ictype(11*17) =
  196.               ictype(12*17) = ictype(13*17) = ictype(14*17) =
  197.               &gx_dc_none;
  198.             /* falls through */
  199.         case 2:
  200.             ictype(5*17) = ictype(10*17) = &gx_dc_none;
  201.         }
  202. #undef ictype
  203.     }
  204.  
  205.     /* Initialize the maps from samples to intensities. */
  206.  
  207.     for ( ci = 0; ci < spp; ci++ )
  208.     {    sample_map *pmap = &penum->map[ci];
  209.  
  210.         /* If the decoding is [0 1] or [1 0], we can fold it */
  211.         /* into the expansion of the sample values; */
  212.         /* otherwise, we have to use the floating point method. */
  213.  
  214.         const float *this_decode = &decode[ci * 2];
  215.         const float *map_decode;    /* decoding used to */
  216.                 /* construct the expansion map */
  217.  
  218.         const float *real_decode;    /* decoding for */
  219.                 /* expanded samples */
  220.  
  221.         int no_decode;
  222.  
  223.         map_decode = real_decode = this_decode;
  224.         if ( map_decode[0] == 0.0 && map_decode[1] == 1.0 )
  225.             no_decode = 1;
  226.         else if ( map_decode[0] == 1.0 && map_decode[1] == 0.0 )
  227.             no_decode = 1,
  228.             real_decode = default_decode;
  229.         else
  230.             no_decode = 0,
  231.             device_color = 0,
  232.             map_decode = default_decode;
  233.         if ( bps > 2 || multi )
  234.         {    if ( bps <= 8 )
  235.               image_init_map(&pmap->table.lookup8[0], 1 << bps,
  236.                      map_decode);
  237.         }
  238.         else
  239.         {    /* The map index encompasses more than one pixel. */
  240.             byte map[4];
  241.             register int i;
  242.             image_init_map(&map[0], 1 << bps, map_decode);
  243.             switch ( bps )
  244.             {
  245.             case 1:
  246.             {    register bits32 *p = &pmap->table.lookup4x1to32[0];
  247.                 if ( map[0] == 0 && map[1] == 0xff )
  248.                     memcpy((byte *)p, map_4x1_to_32, 16 * 4);
  249.                 else if ( map[0] == 0xff && map[1] == 0 )
  250.                     memcpy((byte *)p, map_4x1_to_32_invert, 16 * 4);
  251.                 else
  252.                   for ( i = 0; i < 16; i++, p++ )
  253.                     ((byte *)p)[0] = map[i >> 3],
  254.                     ((byte *)p)[1] = map[(i >> 2) & 1],
  255.                     ((byte *)p)[2] = map[(i >> 1) & 1],
  256.                     ((byte *)p)[3] = map[i & 1];
  257.             }    break;
  258.             case 2:
  259.             {    register bits16 *p = &pmap->table.lookup2x2to16[0];
  260.                 for ( i = 0; i < 16; i++, p++ )
  261.                     ((byte *)p)[0] = map[i >> 2],
  262.                     ((byte *)p)[1] = map[i & 3];
  263.             }    break;
  264.             }
  265.         }
  266.         pmap->decode_base /* = decode_lookup[0] */ = real_decode[0];
  267.         pmap->decode_factor =
  268.           (real_decode[1] - real_decode[0]) /
  269.             (bps <= 8 ? 255.0 : (float)frac_1);
  270.         pmap->decode_max /* = decode_lookup[15] */ = real_decode[1];
  271.         if ( no_decode )
  272.             pmap->decoding = sd_none;
  273.         else if ( bps <= 4 )
  274.         {    static const int steps[] = { 0, 15, 5, 0, 1 };
  275.             int step = steps[bps];
  276.             int i;
  277.             pmap->decoding = sd_lookup;
  278.             for ( i = 15 - step; i > 0; i -= step )
  279.               pmap->decode_lookup[i] = pmap->decode_base +
  280.                 i * (255.0 / 15) * pmap->decode_factor;
  281.         }
  282.         else
  283.             pmap->decoding = sd_compute;
  284.         if ( spp == 1 )        /* and ci == 0 */
  285.         {    /* Pre-map entries 0 and 255. */
  286.             gs_client_color cc;
  287.             cc.paint.values[0] = real_decode[0];
  288.             (*pcst->remap_color)(&cc, pcs, &penum->icolor0, pgs);
  289.             cc.paint.values[0] = real_decode[1];
  290.             (*pcst->remap_color)(&cc, pcs, &penum->icolor1, pgs);
  291.         }
  292.     }
  293.  
  294.     penum->masked = 0;
  295.     penum->device_color = device_color;
  296.     return image_init(penum, width, height, bps, multi, spp,
  297.               pmat, pgs, (fixed)0);
  298. }
  299. /* Construct a mapping table for sample values. */
  300. /* map_size is 2, 4, 16, or 256.  Note that 255 % (map_size - 1) == 0. */
  301. private void
  302. image_init_map(byte *map, int map_size, const float *decode)
  303. {    float min_v = decode[0], max_v = decode[1];
  304.     byte *limit = map + map_size;
  305.     uint value = min_v * 0xffffL;
  306.     /* The division in the next statement is exact, */
  307.     /* see the comment above. */
  308.     uint diff = (max_v - min_v) * (0xffffL / (map_size - 1));
  309.     for ( ; map != limit; map++, value += diff )
  310.         *map = value >> 8;
  311. }
  312.  
  313. /* Start processing a masked image */
  314. int
  315. gs_imagemask_init(gs_image_enum *penum, gs_state *pgs,
  316.   int width, int height, bool invert, gs_matrix *pmat, bool adjust)
  317. {    gx_set_dev_color(pgs);
  318.     /* Initialize color entries 0 and 255. */
  319.     penum->icolor0.type = &gx_dc_pure;
  320.     penum->icolor0.colors.pure = gx_no_color_index;
  321.     penum->icolor1 = *pgs->dev_color;
  322.     penum->masked = 1;
  323.     memcpy(&penum->map[0].table.lookup4x1to32[0],
  324.            (invert ? map_4x1_to_32_invert : map_4x1_to_32),
  325.            16 * 4);
  326.     penum->map[0].decoding = sd_none;
  327.     return image_init(penum, width, height, 1, false, 1, pmat, pgs,
  328.               (adjust && pgs->in_cachedevice ?
  329.                float2fixed(0.25) : (fixed)0));
  330. }
  331.  
  332. /* Common setup for image and imagemask. */
  333. /* Caller has set penum->masked, map, dev_colors[]. */
  334. private int
  335. image_init(register gs_image_enum *penum, int width, int height, int bps,
  336.   bool multi, int spp, gs_matrix *pmat, gs_state *pgs, fixed adjust)
  337. {    int code;
  338.     int index_bps;
  339.     gs_matrix mat;
  340.     gs_fixed_rect clip_box;
  341.     int log2_xbytes = (bps <= 8 ? 0 : arch_log2_sizeof_frac);
  342.     int nplanes = (multi ? spp : 1);
  343.     int spread = nplanes << log2_xbytes;
  344.     uint bsize = (width + 8) * spp;    /* round up, +1 for end-of-run byte */
  345.     byte *buffer;
  346.     fixed mtx, mty;
  347.     if ( width < 0 || height < 0 )
  348.         return_error(gs_error_rangecheck);
  349.     switch ( bps )
  350.        {
  351.     case 1: index_bps = 0; break;
  352.     case 2: index_bps = 1; break;
  353.     case 4: index_bps = 2; break;
  354.     case 8: index_bps = 3; break;
  355.     case 12: index_bps = 4; break;
  356.     default: return_error(gs_error_rangecheck);
  357.        }
  358.     if ( width == 0 || height == 0 )
  359.         return 1;    /* empty image */
  360.     if (    (code = gs_matrix_invert(pmat, &mat)) < 0 ||
  361.         (code = gs_matrix_multiply(&mat, &ctm_only(pgs), &mat)) < 0
  362.        )    return code;
  363.     buffer = gs_alloc_bytes(pgs->memory, bsize, "image buffer");
  364.     if ( buffer == 0 )
  365.         return_error(gs_error_VMerror);
  366.     penum->width = width;
  367.     penum->height = height;
  368.     penum->bps = bps;
  369.     penum->log2_xbytes = log2_xbytes;
  370.     penum->spp = spp;
  371.     penum->num_planes = nplanes;
  372.     penum->spread = spread;
  373.     penum->fxx = float2fixed(mat.xx);
  374.     penum->fxy = float2fixed(mat.xy);
  375.     penum->fyx = float2fixed(mat.yx);
  376.     penum->fyy = float2fixed(mat.yy);
  377.     penum->skewed = (penum->fxy | penum->fyx) != 0;
  378.     mtx = float2fixed(mat.tx);
  379.     mty = float2fixed(mat.ty);
  380.     penum->pgs = pgs;
  381.     clip_box = pgs->clip_path->path.bbox;    /* box is known to be up to date */
  382.     penum->clip_box = clip_box;
  383.     penum->buffer = buffer;
  384.     penum->buffer_size = bsize;
  385.     penum->line = 0;
  386.     penum->line_size = 0;
  387.     penum->bytes_per_row =
  388.         (uint)(((ulong)width * (bps * spp) / nplanes + 7) >> 3);
  389.     penum->slow_loop = penum->skewed;
  390.     penum->clip_dev = 0;        /* in case we bail out */
  391.     /* If all four extrema of the image fall within the clipping */
  392.     /* rectangle, clipping is never required. */
  393.        {    gs_fixed_rect cbox;
  394.         fixed edx = float2fixed(mat.xx * width);
  395.         fixed edy = float2fixed(mat.yy * height);
  396.         fixed epx, epy, eqx, eqy;
  397.         if ( edx < 0 ) epx = edx, eqx = 0;
  398.         else epx = 0, eqx = edx;
  399.         if ( edy < 0 ) epy = edy, eqy = 0;
  400.         else epy = 0, eqy = edy;
  401.         if ( penum->skewed )
  402.         {    edx = float2fixed(mat.yx * height);
  403.             edy = float2fixed(mat.xy * width);
  404.             if ( edx < 0 ) epx += edx; else eqx += edx;
  405.             if ( edy < 0 ) epy += edy; else eqy += edy;
  406.         }
  407.         else
  408.         {    /*
  409.              * If the image is only 1 sample wide or high,
  410.              * and is less than 1 device pixel wide or high,
  411.              * move it slightly so that it covers pixel centers.
  412.              * This is a hack to work around a bug in TeX/dvips,
  413.              * which uses 1-bit-high images to draw horizontal
  414.              * (and vertical?) lines without positioning them
  415.              * properly.
  416.              */
  417.             fixed diff;
  418.             if ( width == 1 && eqx - epx < fixed_1 )
  419.                 diff = arith_rshift_1(penum->fxx),
  420.                 mtx = (((mtx + diff) | fixed_half)
  421.                     & -fixed_half) - diff;
  422.             if ( height == 1 && eqy - epy < fixed_1 )
  423.                 diff = arith_rshift_1(penum->fyy),
  424.                 mty = (((mty + diff) | fixed_half)
  425.                     & -fixed_half) - diff;
  426.         }
  427.         gx_cpath_box_for_check(pgs->clip_path, &cbox);
  428.         penum->never_clip =
  429.             mtx + epx >= cbox.p.x && mtx + eqx <= cbox.q.x &&
  430.             mty + epy >= cbox.p.y && mty + eqy <= cbox.q.y;
  431.         if_debug7('b',
  432.               "[b]Image: cbox=(%g,%g),(%g,%g)\n    mt=(%g,%g) never_clip=%d\n",
  433.               fixed2float(cbox.p.x), fixed2float(cbox.p.y),
  434.               fixed2float(cbox.q.x), fixed2float(cbox.q.y),
  435.               fixed2float(mtx), fixed2float(mty),
  436.               penum->never_clip);
  437.        }
  438.        {    static iunpack_proc((*procs[5])) = {
  439.             image_unpack_1, image_unpack_2,
  440.             image_unpack_4, image_unpack_8, image_unpack_12
  441.            };
  442.         static iunpack_proc((*spread_procs[5])) = {
  443.             image_unpack_1_spread, image_unpack_2_spread,
  444.             image_unpack_4, image_unpack_8_spread,
  445.             image_unpack_12
  446.            };
  447.         long dev_width;
  448.         if ( nplanes != 1 )
  449.           penum->unpack = spread_procs[index_bps];
  450.         else
  451.           penum->unpack = procs[index_bps];
  452.         penum->slow_loop |=
  453.             /* Use slow loop for imagemask with a halftone */
  454.             (penum->masked &&
  455.              !color_is_pure(pgs->dev_color));
  456.         if ( pgs->in_charpath )
  457.             penum->render = image_render_skip;
  458.         else if ( spp == 1 && bps == 1 && !penum->slow_loop &&
  459.               (penum->masked ||
  460.                (color_is_pure(&penum->icolor0) &&
  461.                 color_is_pure(&penum->icolor1))) &&
  462.               ((dev_width =
  463.                 fixed2long_rounded(mtx + width * penum->fxx) -
  464.                 fixed2long_rounded(mtx)) == width ||
  465.                adjust == 0)
  466.            )
  467.         {    penum->render = image_render_simple;
  468.             if ( dev_width != width )
  469.             {    /* Must buffer a scan line */
  470.                 dev_width = any_abs(dev_width);
  471.                 if ( dev_width + 7 > max_ushort )
  472.                 {    gs_image_cleanup(penum);
  473.                     return_error(gs_error_limitcheck);
  474.                 }
  475.                 penum->line_width = dev_width;
  476.                 penum->line_size = (dev_width + 7) >> 3;
  477.                 penum->line = gs_alloc_bytes(pgs->memory,
  478.                     penum->line_size, "image line");
  479.                 if ( penum->line == 0 )
  480.                 {    gs_image_cleanup(penum);
  481.                     return_error(gs_error_VMerror);
  482.                 }
  483.             }
  484.             /* The image is 1-for-1 with the device: */
  485.             /* we don't want to spread the samples, */
  486.             /* but we have to reset bps to prevent the buffer */
  487.             /* pointer from being incremented by 8 bytes */
  488.             /* per input byte. */
  489.             penum->unpack = image_unpack_8;
  490.             penum->bps = 8;
  491.         }
  492.         else if ( bps > 8 )
  493.             penum->render = image_render_frac;
  494.         else
  495.             penum->render =
  496.               (spp == 1 ? image_render_mono :
  497.                image_render_color);
  498.        }
  499.     penum->adjust = adjust;
  500.     if ( !penum->never_clip )
  501.       {    /* Set up the clipping device. */
  502.         gx_device_clip *cdev =
  503.           gs_alloc_struct(pgs->memory, gx_device_clip,
  504.                   &st_device_clip, "image clipper");
  505.         if ( cdev == 0 )
  506.           {    gs_image_cleanup(penum);
  507.             return_error(gs_error_VMerror);
  508.           }
  509.         gx_make_clip_device(cdev, cdev, &pgs->clip_path->list);
  510.         penum->clip_dev = cdev;
  511.         cdev->target = gs_currentdevice(pgs);
  512.         (*dev_proc(cdev, open_device))((gx_device *)cdev);
  513.       }
  514.     penum->plane_index = 0;
  515.     penum->byte_in_row = 0;
  516.     penum->xcur = mtx;
  517.     penum->ycur = mty;
  518.     penum->y = 0;
  519.     if_debug9('b', "[b]Image: w=%d h=%d %s\n   [%f %f %f %f %f %f]\n",
  520.          width, height,
  521.          (penum->never_clip ? "no clip" : "must clip"),
  522.          mat.xx, mat.xy, mat.yx, mat.yy, mat.tx, mat.ty);
  523.     return 0;
  524. }
  525.