home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 2 / AACD 2.iso / AACD / Magazine / UsingPDF / GhostScript / source / gs5.10 / gxclist.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-11-24  |  25.6 KB  |  864 lines

  1. /* Copyright (C) 1991, 1996, 1997 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. /* gxclist.c */
  20. /* Command list writing for Ghostscript. */
  21. #include "memory_.h"
  22. #include "string_.h"
  23. #include "gx.h"
  24. #include "gp.h"
  25. #include "gpcheck.h"
  26. #include "gserrors.h"
  27. #include "gxdevice.h"
  28. #include "gxdevmem.h"            /* must precede gxcldev.h */
  29. #include "gxcldev.h"
  30.  
  31. #define cdev cwdev
  32.  
  33. /* Forward declarations of procedures */
  34. private dev_proc_open_device(clist_open);
  35. private dev_proc_output_page(clist_output_page);
  36. private dev_proc_open_device(clist_close);
  37. private dev_proc_get_band(clist_get_band);
  38. /* In gxclrect.c */
  39. extern dev_proc_fill_rectangle(clist_fill_rectangle);
  40. extern dev_proc_copy_mono(clist_copy_mono);
  41. extern dev_proc_copy_color(clist_copy_color);
  42. extern dev_proc_copy_alpha(clist_copy_alpha);
  43. extern dev_proc_strip_tile_rectangle(clist_strip_tile_rectangle);
  44. extern dev_proc_strip_copy_rop(clist_strip_copy_rop);
  45. /* In gxclread.c */
  46. extern dev_proc_get_bits(clist_get_bits);
  47.  
  48. /* The device procedures */
  49. gx_device_procs gs_clist_device_procs =
  50. {    clist_open,
  51.     gx_forward_get_initial_matrix,
  52.     gx_default_sync_output,
  53.     clist_output_page,
  54.     clist_close,
  55.     gx_forward_map_rgb_color,
  56.     gx_forward_map_color_rgb,
  57.     clist_fill_rectangle,
  58.     gx_default_tile_rectangle,
  59.     clist_copy_mono,
  60.     clist_copy_color,
  61.     gx_default_draw_line,
  62.     clist_get_bits,
  63.     gx_forward_get_params,
  64.     gx_forward_put_params,
  65.     gx_forward_map_cmyk_color,
  66.     gx_forward_get_xfont_procs,
  67.     gx_forward_get_xfont_device,
  68.     gx_forward_map_rgb_alpha_color,
  69.     gx_forward_get_page_device,
  70.     gx_forward_get_alpha_bits,
  71.     clist_copy_alpha,
  72.     clist_get_band,
  73.     gx_default_copy_rop,
  74.     gx_default_fill_path,
  75.     gx_default_stroke_path,
  76.     gx_default_fill_mask,
  77.     gx_default_fill_trapezoid,
  78.     gx_default_fill_parallelogram,
  79.     gx_default_fill_triangle,
  80.     gx_default_draw_thin_line,
  81.     gx_default_begin_image,
  82.     gx_default_image_data,
  83.     gx_default_end_image,
  84.     clist_strip_tile_rectangle,
  85.     clist_strip_copy_rop,
  86.     gx_forward_get_clipping_box
  87. };
  88.  
  89. /* ------ Define the command set and syntax ------ */
  90.  
  91. /* Define the clipping enable/disable opcodes. */
  92. /* The path extensions initialize these to their proper values. */
  93. byte cmd_opvar_disable_clip = 0xff;
  94. byte cmd_opvar_enable_clip = 0xff;
  95.  
  96. #ifdef DEBUG
  97. const char *cmd_op_names[16] = { cmd_op_name_strings };
  98. private const char *cmd_misc_op_names[16] = { cmd_misc_op_name_strings };
  99. const char **cmd_sub_op_names[16] =
  100. {    cmd_misc_op_names, 0, 0, 0, 0, 0, 0, 0,
  101.     0, 0, 0, 0, 0, 0, 0, 0
  102. };
  103. private ulong far_data cmd_op_counts[256];
  104. private ulong far_data cmd_op_sizes[256];
  105. private ulong cmd_tile_reset, cmd_tile_found, cmd_tile_added;
  106. extern ulong cmd_diffs[5];        /* in gxclpath.c */
  107. private ulong cmd_same_band, cmd_other_band;
  108. int
  109. cmd_count_op(int op, uint size)
  110. {    cmd_op_counts[op]++;
  111.     cmd_op_sizes[op] += size;
  112.     if ( gs_debug_c('L') )
  113.       { const char **sub = cmd_sub_op_names[op >> 4];
  114.         if ( sub )
  115.           dprintf2(", %s(%u)\n", sub[op & 0xf], size);
  116.         else
  117.           dprintf3(", %s %d(%u)\n", cmd_op_names[op >> 4], op & 0xf, size);
  118.         fflush(dstderr);
  119.       }
  120.     return op;
  121. }
  122. void
  123. cmd_uncount_op(int op, uint size)
  124. {    cmd_op_counts[op]--;
  125.     cmd_op_sizes[op] -= size;
  126. }
  127. #endif
  128.  
  129. /* Initialization for imager state. */
  130. /* The initial scale is arbitrary. */
  131. const gs_imager_state clist_imager_state_initial =
  132.  { gs_imager_state_initial(300.0 / 72.0) };
  133.  
  134. /*
  135.  * The buffer area (data, data_size) holds a bitmap cache when both writing
  136.  * and reading.  The rest of the space is used for the command buffer and
  137.  * band state bookkeeping when writing, and for the rendering buffer (image
  138.  * device) when reading.  For the moment, we divide the space up
  139.  * arbitrarily, except that we allocate less space for the bitmap cache if
  140.  * the device doesn't need halftoning.
  141.  *
  142.  * All the routines for allocating tables in the buffer are idempotent, so
  143.  * they can be used to check whether a given-size buffer is large enough.
  144.  */
  145.  
  146. /*
  147.  * Calculate the desired size for the tile cache.
  148.  */
  149. private uint
  150. clist_tile_cache_size(const gx_device *target, uint data_size)
  151. {    uint bits_size =
  152.       (data_size / 5) & -align_cached_bits_mod;  /* arbitrary */
  153.  
  154.     if ( (gx_device_has_color(target) ? target->color_info.max_color :
  155.           target->color_info.max_gray) >= 31
  156.        )
  157.       { /* No halftones -- cache holds only Patterns & characters. */
  158.         bits_size -= bits_size >> 2;
  159.       }
  160. #define min_bits_size 1024
  161.       if ( bits_size < min_bits_size )
  162.         bits_size = min_bits_size;
  163. #undef min_bits_size
  164.     return bits_size;
  165. }
  166.  
  167. /*
  168.  * Initialize the allocation for the tile cache.  Sets: tile_hash_mask,
  169.  * tile_max_count, tile_table, chunk (structure), bits (structure).
  170.  */
  171. private int
  172. clist_init_tile_cache(gx_device *dev, byte *init_data, ulong data_size)
  173. {    byte *data = init_data;
  174.     uint bits_size = data_size;
  175.     /*
  176.      * Partition the bits area between the hash table and the actual
  177.      * bitmaps.  The per-bitmap overhead is about 24 bytes; if the
  178.      * average character size is 10 points, its bitmap takes about 24 +
  179.      * 0.5 * 10/72 * xdpi * 10/72 * ydpi / 8 bytes (the 0.5 being a
  180.      * fudge factor to account for characters being narrower than they
  181.      * are tall), which gives us a guideline for the size of the hash
  182.      * table.
  183.      */
  184.     uint avg_char_size =
  185.       (uint)(dev->x_pixels_per_inch * dev->y_pixels_per_inch *
  186.          (0.5 * 10/72 * 10/72 / 8)) + 24;
  187.     uint hc = bits_size / avg_char_size;
  188.     uint hsize;
  189.  
  190.     while ( (hc + 1) & hc )
  191.       hc |= hc >> 1;    /* make mask (power of 2 - 1) */
  192.     if ( hc < 0xff )
  193.       hc = 0xff;        /* make allowance for halftone tiles */
  194.     else if ( hc > 0xfff )
  195.       hc = 0xfff;        /* cmd_op_set_tile_index has 12-bit operand */
  196.     /* Make sure the tables will fit. */
  197.     while ( hc >= 3 && (hsize = (hc + 1) * sizeof(tile_hash)) >= bits_size )
  198.       hc >>= 1;
  199.     if ( hc < 3 )
  200.       return_error(gs_error_rangecheck);
  201.     cdev->tile_hash_mask = hc;
  202.     cdev->tile_max_count = hc - (hc >> 2);
  203.     cdev->tile_table = (tile_hash *)data;
  204.     data += hsize;
  205.     bits_size -= hsize;
  206.     gx_bits_cache_chunk_init(&cdev->chunk, data, bits_size);
  207.     gx_bits_cache_init(&cdev->bits, &cdev->chunk);
  208.     return 0;
  209. }
  210.  
  211. /*
  212.  * Initialize the allocation for the bands.  Requires: target.  Sets:
  213.  * page_band_height (=page_info.band_params.BandHeight), nbands.
  214.  */
  215. private int
  216. clist_init_bands(gx_device *dev, uint data_size, int band_width,
  217.   int band_height)
  218. {    gx_device *target = cdev->target;
  219.     int nbands;
  220.  
  221.     if ( gdev_mem_data_size((gx_device_memory *)target, band_width,
  222.                 band_height) > data_size
  223.        )
  224.       return_error(gs_error_rangecheck);
  225.     cdev->page_band_height = band_height;
  226.     nbands = (target->height + band_height - 1) / band_height;
  227.     cdev->nbands = nbands;
  228. #ifdef DEBUG
  229.     if ( gs_debug_c('l') | gs_debug_c(':') )
  230.       dprintf4("[l]width=%d, band_width=%d, band_height=%d, nbands=%d\n",
  231.            target->width, band_width, band_height, nbands);
  232. #endif
  233.     return 0;
  234. }
  235.  
  236. /*
  237.  * Initialize the allocation for the band states, which are used only
  238.  * when writing.  Requires: nbands.  Sets: states, cbuf, cend.
  239.  */
  240. private int
  241. clist_init_states(gx_device *dev, byte *init_data, uint data_size)
  242. {    ulong state_size = cdev->nbands * (ulong)sizeof(gx_clist_state);
  243.  
  244.     /*
  245.      * The +100 in the next line is bogus, but we don't know what the
  246.      * real check should be.
  247.      */
  248.     if ( state_size + sizeof(cmd_prefix) + cmd_largest_size + 100 > data_size )
  249.       return_error(gs_error_rangecheck);
  250.     cdev->states = (gx_clist_state *)init_data;
  251.     cdev->cbuf = init_data + state_size;
  252.     cdev->cend = init_data + data_size;
  253.     return 0;
  254. }
  255.  
  256. /*
  257.  * Initialize all the data allocations.  Requires: target.  Sets:
  258.  * page_tile_cache_size, page_info.band_params.BandWidth,
  259.  * page_info.band_params.BandBufferSpace, + see above.
  260.  */
  261. private int
  262. clist_init_data(gx_device *dev, byte *init_data, uint data_size)
  263. {    gx_device *target = cdev->target;
  264.     const int band_width =
  265.       cdev->page_info.band_params.BandWidth =
  266.         (cdev->band_params.BandWidth ? cdev->band_params.BandWidth :
  267.          target->width);
  268.     int band_height = cdev->band_params.BandHeight;
  269.     const uint band_space =
  270.       cdev->page_info.band_params.BandBufferSpace =
  271.         (cdev->band_params.BandBufferSpace ?
  272.          cdev->band_params.BandBufferSpace : data_size);
  273.     byte *data = init_data;
  274.     uint size = band_space;
  275.     uint bits_size;
  276.     int code;
  277.       
  278.     if ( band_height )
  279.       { /*
  280.          * The band height is fixed, so the band buffer requirement
  281.          * is completely determined.
  282.          */
  283.         uint band_data_size =
  284.           gdev_mem_data_size((gx_device_memory *)target,
  285.                  band_width, band_height);
  286.  
  287.         if ( band_data_size >= band_space )
  288.           return_error(gs_error_rangecheck);
  289.         bits_size = min(band_space - band_data_size, data_size >> 1);
  290.       }
  291.     else
  292.       { /*
  293.          * Choose the largest band height that will fit in the
  294.          * rendering-time buffer.
  295.          */
  296.         bits_size = clist_tile_cache_size(target, band_space);
  297.         bits_size = min(bits_size, data_size >> 1);
  298.         band_height = gdev_mem_max_height((gx_device_memory *)target,
  299.                           band_width,
  300.                           band_space - bits_size);
  301.         if ( band_height == 0 )
  302.           return_error(gs_error_rangecheck);
  303.       }
  304.     code = clist_init_tile_cache(dev, data, bits_size);
  305.     if ( code < 0 )
  306.       return code;
  307.     cdev->page_tile_cache_size = bits_size;
  308.     data += bits_size;
  309.     size -= bits_size;
  310.     code = clist_init_bands(dev, size, band_width, band_height);
  311.     if ( code < 0 )
  312.       return code;
  313.     return clist_init_states(dev, data, data_size - bits_size);
  314. }
  315. /*
  316.  * Initialize the device state (for writing).  This routine requires only
  317.  * data, data_size, and target to be set, and is idempotent.
  318.  */
  319. private int
  320. clist_init(gx_device *dev)
  321. {    int code = clist_init_data(dev, cdev->data, cdev->data_size);
  322.     int nbands = cdev->nbands;
  323.  
  324.     if ( code < 0 )
  325.       return code;
  326.     /* Now initialize the rest of the state. */
  327.     cdev->ymin = cdev->ymax = -1;    /* render_init not done yet */
  328.     memset(cdev->tile_table, 0, (cdev->tile_hash_mask + 1) *
  329.            sizeof(*cdev->tile_table));
  330.     cdev->cnext = cdev->cbuf;
  331.     cdev->ccl = 0;
  332.     cdev->band_range_list.head = cdev->band_range_list.tail = 0;
  333.     cdev->band_range_min = 0;
  334.     cdev->band_range_max = nbands - 1;
  335.     { int band;
  336.       gx_clist_state *states = cdev->states;
  337.  
  338.       for ( band = 0; band < nbands; band++, states++ )
  339.         { static const gx_clist_state cls_initial =
  340.             { cls_initial_values };
  341.           *states = cls_initial;
  342.         }
  343.     }
  344.     /*
  345.      * Round up the size of the per-tile band mask so that the bits,
  346.      * which follow it, stay aligned.
  347.      */
  348.     cdev->tile_band_mask_size =
  349.       ((nbands + (align_bitmap_mod * 8 - 1)) >> 3) &
  350.         ~(align_bitmap_mod - 1);
  351.     /*
  352.      * Initialize the all-band parameters to impossible values,
  353.      * to force them to be written the first time they are used.
  354.      */
  355.     memset(&cdev->tile_params, 0, sizeof(cdev->tile_params));
  356.     cdev->tile_depth = 0;
  357.     cdev->tile_known_min = nbands;
  358.     cdev->tile_known_max = -1;
  359.     cdev->imager_state = clist_imager_state_initial;
  360.     cdev->clip_path = NULL;
  361.     cdev->clip_path_id = gs_no_id;
  362.     cdev->color_space = 0;
  363.     { int i;
  364.       for ( i = 0; i < countof(cdev->transfer_ids); ++i )
  365.         cdev->transfer_ids[i] = gs_no_id;
  366.     }
  367.     cdev->black_generation_id = gs_no_id;
  368.     cdev->undercolor_removal_id = gs_no_id;
  369.     cdev->device_halftone_id = gs_no_id;
  370.     cdev->in_image = false;
  371.     return 0;
  372. }
  373. /* Open the device by initializing the device state and opening the */
  374. /* scratch files. */
  375. private int
  376. clist_open(gx_device *dev)
  377. {    char fmode[4];
  378.     int code;
  379.  
  380.     cdev->page_cfile = 0;    /* in case of failure */
  381.     cdev->page_bfile = 0;    /* ditto */
  382.     code = clist_init(dev);
  383.     if ( code < 0 )
  384.       return code;
  385.     strcpy(fmode, "w+");
  386.     strcat(fmode, gp_fmode_binary_suffix);
  387.     cdev->page_cfname[0] = 0;    /* create a new file */
  388.     cdev->page_bfname[0] = 0;    /* ditto */
  389.     cdev->page_bfile_end_pos = 0;
  390.     if ( (code = clist_fopen(cdev->page_cfname, fmode, &cdev->page_cfile,
  391.                  &gs_memory_default, true)) < 0 ||
  392.          (code = clist_fopen(cdev->page_bfname, fmode, &cdev->page_bfile,
  393.                  &gs_memory_default, true)) < 0
  394.        )
  395.       clist_close(dev);
  396.     return code;
  397. }
  398.  
  399. /* The output_page procedure should never be called! */
  400. private int
  401. clist_output_page(gx_device *dev, int num_copies, int flush)
  402. {    return_error(gs_error_Fatal);
  403. }
  404.  
  405. /* Reset (or prepare to append to) the command list after printing a page. */
  406. int
  407. clist_finish_page(gx_device *dev, bool flush)
  408. {    if ( flush )
  409.       { clist_rewind(cdev->page_cfile, true, cdev->page_cfname);
  410.         clist_rewind(cdev->page_bfile, true, cdev->page_bfname);
  411.         cdev->page_bfile_end_pos = 0;
  412.       }
  413.     else
  414.       { clist_fseek(cdev->page_cfile, 0L, SEEK_END, cdev->page_cfname);
  415.         clist_fseek(cdev->page_bfile, 0L, SEEK_END, cdev->page_bfname);
  416.       }
  417.     return clist_init(dev);        /* reinitialize */
  418. }
  419.  
  420. /* Close the device by freeing the temporary files. */
  421. /* Note that this does not deallocate the buffer. */
  422. private int
  423. clist_close(gx_device *dev)
  424. {    if ( cdev->page_cfile != NULL )
  425.       {    clist_fclose(cdev->page_cfile, cdev->page_cfname, true);
  426.         cdev->page_cfile = NULL;
  427.       }
  428.     if ( cdev->page_bfile != NULL )
  429.       {    clist_fclose(cdev->page_bfile, cdev->page_bfname, true);
  430.         cdev->page_bfile = NULL;
  431.       }
  432.     return 0;
  433. }
  434.  
  435. /* Print statistics. */
  436. #ifdef DEBUG
  437. void
  438. cmd_print_stats(void)
  439. {    int ci, cj;
  440.     dprintf3("[l]counts: reset = %lu, found = %lu, added = %lu\n",
  441.              cmd_tile_reset, cmd_tile_found, cmd_tile_added);
  442.     dprintf5("     diff 2.5 = %lu, 3 = %lu, 4 = %lu, 2 = %lu, >4 = %lu\n",
  443.          cmd_diffs[0], cmd_diffs[1], cmd_diffs[2], cmd_diffs[3],
  444.          cmd_diffs[4]);
  445.     dprintf2("     same_band = %lu, other_band = %lu\n",
  446.          cmd_same_band, cmd_other_band);
  447.     for ( ci = 0; ci < 0x100; ci += 0x10 )
  448.        {    const char **sub = cmd_sub_op_names[ci >> 4];
  449.         if ( sub != 0 )
  450.           { dprintf1("[l]  %s =", cmd_op_names[ci >> 4]);
  451.             for ( cj = ci; cj < ci + 0x10; cj += 2 )
  452.               dprintf6("\n\t%s = %lu(%lu), %s = %lu(%lu)",
  453.                    sub[cj-ci],
  454.                    cmd_op_counts[cj], cmd_op_sizes[cj],
  455.                    sub[cj-ci+1],
  456.                    cmd_op_counts[cj+1], cmd_op_sizes[cj+1]);
  457.           }
  458.         else
  459.           { ulong tcounts = 0, tsizes = 0;
  460.             for ( cj = ci; cj < ci + 0x10; cj++ )
  461.               tcounts += cmd_op_counts[cj],
  462.               tsizes += cmd_op_sizes[cj];
  463.             dprintf3("[l]  %s (%lu,%lu) =\n\t",
  464.                  cmd_op_names[ci >> 4], tcounts, tsizes);
  465.             for ( cj = ci; cj < ci + 0x10; cj++ )
  466.               if ( cmd_op_counts[cj] == 0 )
  467.             dputs(" -");
  468.               else
  469.             dprintf2(" %lu(%lu)", cmd_op_counts[cj],
  470.                  cmd_op_sizes[cj]);
  471.           }
  472.         dputs("\n");
  473.        }
  474. }
  475. #endif                /* DEBUG */
  476.  
  477. /* ------ Writing ------ */
  478.  
  479. /* Utilities */
  480.  
  481. /* Write the commands for one band or band range. */
  482. private int
  483. cmd_write_band(gx_device_clist_writer *cldev, int band_min, int band_max,
  484.   cmd_list *pcl, byte cmd_end)
  485. {    const cmd_prefix *cp = pcl->head;
  486.  
  487.     if ( cp != 0 || cmd_end != cmd_opv_end_run ) {
  488.       clist_file_ptr cfile = cldev->page_cfile;
  489.       clist_file_ptr bfile = cldev->page_bfile;
  490.       cmd_block cb;
  491.       byte end = cmd_count_op(cmd_end, 1);
  492.       int code;
  493.  
  494.       cb.band_min = band_min;
  495.       cb.band_max = band_max;
  496.       cb.pos = clist_ftell(cfile);
  497.       if_debug3('l', "[l]writing for bands (%d,%d) at %ld\n",
  498.             band_min, band_max, cb.pos);
  499.       clist_fwrite_chars(&cb, sizeof(cb), bfile);
  500.       if ( cp != 0 ) {
  501.         pcl->tail->next = 0;    /* terminate the list */
  502.         for ( ; cp != 0; cp = cp->next ) {
  503. #ifdef DEBUG
  504.           if ( (const byte *)cp < cldev->cbuf ||
  505.            (const byte *)cp >= cldev->cend ||
  506.            cp->size > cldev->cend - (const byte *)cp
  507.          ) {
  508.         lprintf1("cmd_write_band error at 0x%lx\n", (ulong)cp);
  509.         return_error(gs_error_Fatal);
  510.           }
  511. #endif
  512.           clist_fwrite_chars(cp + 1, cp->size, cfile);
  513.         }
  514.         pcl->head = pcl->tail = 0;
  515.       }
  516.  
  517.       clist_fwrite_chars(&end, 1, cfile);
  518.       process_interrupts();
  519.       if ( (code = clist_ferror_code(bfile)) < 0 ||
  520.            (code = clist_ferror_code(cfile)) < 0
  521.          )
  522.         return_error(code);
  523.     }
  524.     return 0;
  525. }
  526.  
  527. /* Write out the buffered commands, and reset the buffer. */
  528. private int
  529. cmd_write_buffer(gx_device_clist_writer *cldev, byte cmd_end)
  530. {    int nbands = cldev->nbands;
  531.     gx_clist_state *pcls;
  532.     int band;
  533.     int code = cmd_write_band(cldev, cldev->band_range_min,
  534.                   cldev->band_range_max,
  535.                   &cldev->band_range_list, cmd_opv_end_run);
  536.  
  537.     for ( band = 0, pcls = cldev->states;
  538.           code >= 0 && band < nbands; band++, pcls++
  539.         )
  540.       code = cmd_write_band(cldev, band, band, &pcls->list, cmd_end);
  541.     cldev->cnext = cldev->cbuf;
  542.     cldev->ccl = 0;
  543.     cldev->band_range_list.head = cldev->band_range_list.tail = 0;
  544. #ifdef DEBUG
  545.     if ( gs_debug_c('l') )
  546.       cmd_print_stats();
  547. #endif
  548.     return_check_interrupt(code);
  549. }
  550. /* End a page by flushing the buffer and terminating the command list. */
  551. int
  552. clist_end_page(gx_device_clist_writer *cldev)
  553. {    int code = cmd_write_buffer(cldev, cmd_opv_end_page);
  554.     cmd_block cb;
  555.  
  556.     if ( code < 0 )
  557.       return code;
  558.     /* Write the terminating entry in the block file. */
  559.     /* Note that because of copypage, there may be many such entries. */
  560.     cb.band_min = cb.band_max = cmd_band_end;
  561.     cb.pos = clist_ftell(cldev->page_cfile);
  562.     clist_fwrite_chars(&cb, sizeof(cb), cldev->page_bfile);
  563.     cldev->page_bfile_end_pos = clist_ftell(cldev->page_bfile);
  564. #ifdef DEBUG
  565.     if ( gs_debug_c('l') | gs_debug_c(':') )
  566.       dprintf2("[l]clist_render_init at cfile=%ld, bfile=%ld\n",
  567.            cb.pos, cldev->page_bfile_end_pos);
  568. #endif
  569.     return 0;
  570. }
  571.  
  572. /* Add a command to the appropriate band list, */
  573. /* and allocate space for its data. */
  574. /* Return the pointer to the data area. */
  575. /* If an error occurs, set cldev->error_code and return 0. */
  576. #define cmd_headroom (sizeof(cmd_prefix) + arch_align_ptr_mod)
  577. byte *
  578. cmd_put_list_op(gx_device_clist_writer *cldev, cmd_list *pcl, uint size)
  579. {    byte *dp = cldev->cnext;
  580.     if ( size + cmd_headroom > cldev->cend - dp )
  581.       { int code = cldev->error_code =
  582.           cmd_write_buffer(cldev, cmd_opv_end_run);
  583.         if ( code < 0 )
  584.           return 0;
  585.         return cmd_put_list_op(cldev, pcl, size);
  586.       }
  587.     if ( cldev->ccl == pcl )
  588.       { /* We're adding another command for the same band. */
  589.         /* Tack it onto the end of the previous one. */
  590.         cmd_count_add1(cmd_same_band);
  591. #ifdef DEBUG
  592.         if ( pcl->tail->size > dp - (byte *)(pcl->tail + 1) )
  593.           { lprintf1("cmd_put_list_op error at 0x%lx\n", (ulong)pcl->tail);
  594.           }
  595. #endif
  596.         pcl->tail->size += size;
  597.       }
  598.     else
  599.       { /* Skip to an appropriate alignment boundary. */
  600.         /* (We assume the command buffer itself is aligned.) */
  601.         cmd_prefix *cp =
  602.           (cmd_prefix *)(dp +
  603.                  ((cldev->cbuf - dp) & (arch_align_ptr_mod - 1)));
  604.         cmd_count_add1(cmd_other_band);
  605.         dp = (byte *)(cp + 1);
  606.         if ( pcl->tail != 0 )
  607.           {
  608. #ifdef DEBUG
  609.         if ( pcl->tail < pcl->head ||
  610.              pcl->tail->size > dp - (byte *)(pcl->tail + 1)
  611.            )
  612.           { lprintf1("cmd_put_list_op error at 0x%lx\n",
  613.                  (ulong)pcl->tail);
  614.           }
  615. #endif
  616.         pcl->tail->next = cp;
  617.           }
  618.         else
  619.           pcl->head = cp;
  620.         pcl->tail = cp;
  621.         cldev->ccl = pcl;
  622.         cp->size = size;
  623.       }
  624.     cldev->cnext = dp + size;
  625.     return dp;
  626. }
  627. #ifdef DEBUG
  628. byte *
  629. cmd_put_op(gx_device_clist_writer *cldev, gx_clist_state *pcls, uint size)
  630. {    if_debug3('L', "[L]band %d: size=%u, left=%u",
  631.           (int)(pcls - cldev->states),
  632.           size, (uint)(cldev->cend - cldev->cnext));
  633.     return cmd_put_list_op(cldev, &pcls->list, size);
  634. }
  635. #endif
  636.  
  637. /* Add a command for a range of bands. */
  638. byte *
  639. cmd_put_range_op(gx_device_clist_writer *cldev, int band_min, int band_max,
  640.   uint size)
  641. {    cmd_prefix *tail;
  642.     if_debug4('L', "[L]band range(%d,%d): size=%u, left=%u",
  643.           band_min, band_max, size,
  644.           (uint)(cldev->cend - cldev->cnext));
  645.     if ( cldev->band_range_list.head == 0 ||
  646.          band_min != cldev->band_range_min ||
  647.          band_max != cldev->band_range_max ||
  648.          (tail = cldev->band_range_list.tail,
  649.           cldev->cnext != (byte *)(tail + 1) + tail->size)
  650.        )
  651.       { if ( (cldev->error_code = cmd_write_buffer(cldev, cmd_opv_end_run)) < 0 )
  652.           return 0;
  653.         cldev->band_range_min = band_min;
  654.         cldev->band_range_max = band_max;
  655.       }
  656.     return cmd_put_list_op(cldev, &cldev->band_range_list, size);
  657. }
  658.  
  659. /* Write a variable-size positive integer. */
  660. int
  661. cmd_size_w(register uint w)
  662. {    register int size = 1;
  663.     while ( w > 0x7f ) w >>= 7, size++;
  664.     return size;
  665. }
  666. byte *
  667. cmd_put_w(register uint w, register byte *dp)
  668. {    while ( w > 0x7f ) *dp++ = w | 0x80, w >>= 7;
  669.     *dp = w;
  670.     return dp + 1;
  671. }
  672.  
  673. /* Define the encodings of the different settable colors. */
  674. const clist_select_color_t
  675.   clist_select_color0 = {cmd_op_set_color0, cmd_opv_delta2_color0, 0},
  676.   clist_select_color1 = {cmd_op_set_color1, cmd_opv_delta2_color1, 0},
  677.   clist_select_tile_color0 = {cmd_op_set_color0, cmd_opv_delta2_color0, 1},
  678.   clist_select_tile_color1 = {cmd_op_set_color1, cmd_opv_delta2_color1, 1};
  679. int
  680. cmd_put_color(gx_device_clist_writer *cldev, gx_clist_state *pcls,
  681.   const clist_select_color_t *select,
  682.   gx_color_index color, gx_color_index *pcolor)
  683. {    byte *dp;
  684.     long diff = (long)color - (long)(*pcolor);
  685.     byte op, op_delta2;
  686.  
  687.     if ( diff == 0 )
  688.       return 0;
  689.     if ( select->tile_color )
  690.       set_cmd_put_op(dp, cldev, pcls, cmd_opv_set_tile_color, 1);
  691.     op = select->set_op;
  692.     op_delta2 = select->delta2_op;
  693.     if ( color == gx_no_color_index )
  694.       {    /*
  695.          * We must handle this specially, because it may take more
  696.          * bytes than the color depth.
  697.          */
  698.         set_cmd_put_op(dp, cldev, pcls, op + 15, 1);
  699.       }
  700.     else
  701.        {    long delta;
  702.         byte operand;
  703.  
  704.         switch ( (cldev->color_info.depth + 15) >> 3 )
  705.           {
  706.           case 5:
  707.             if ( !((delta = diff + cmd_delta1_32_bias) &
  708.                   ~cmd_delta1_32_mask) &&
  709.                  (operand =
  710.                   (byte)((delta >> 23) + ((delta >> 18) & 1))) != 0 &&
  711.                  operand != 15
  712.                )
  713.               { set_cmd_put_op(dp, cldev, pcls,
  714.                        (byte)(op + operand), 2);
  715.                 dp[1] = (byte)(((delta >> 10) & 0300) +
  716.                        (delta >> 5) + delta);
  717.                 break;
  718.               }
  719.               if ( !((delta = diff + cmd_delta2_32_bias) &
  720.                    ~cmd_delta2_32_mask)
  721.                )
  722.               { set_cmd_put_op(dp, cldev, pcls, op_delta2, 3);
  723.                 dp[1] = (byte)((delta >> 20) + (delta >> 16));
  724.                 dp[2] = (byte)((delta >> 4) + delta);
  725.                 break;
  726.               }
  727.             set_cmd_put_op(dp, cldev, pcls, op, 5);
  728.             *++dp = (byte)(color >> 24);
  729.             goto b3;
  730.           case 4:
  731.             if ( !((delta = diff + cmd_delta1_24_bias) &
  732.                    ~cmd_delta1_24_mask) &&
  733.                  (operand = (byte)(delta >> 16)) != 0 &&
  734.                  operand != 15
  735.                )
  736.               { set_cmd_put_op(dp, cldev, pcls,
  737.                        (byte)(op + operand), 2);
  738.                 dp[1] = (byte)((delta >> 4) + delta);
  739.                 break;
  740.               }
  741.               if ( !((delta = diff + cmd_delta2_24_bias) &
  742.                    ~cmd_delta2_24_mask)
  743.                )
  744.               { set_cmd_put_op(dp, cldev, pcls, op_delta2, 3);
  745.                 dp[1] = ((byte)(delta >> 13) & 0xf8) +
  746.                   ((byte)(delta >> 11) & 7);
  747.                 dp[2] = (byte)(((delta >> 3) & 0xe0) + delta);
  748.                 break;
  749.               }
  750.             set_cmd_put_op(dp, cldev, pcls, op, 4);
  751. b3:            *++dp = (byte)(color >> 16);
  752.             goto b2;
  753.           case 3:
  754.             set_cmd_put_op(dp, cldev, pcls, op, 3);
  755. b2:            *++dp = (byte)(color >> 8);
  756.             goto b1;
  757.           case 2:
  758.             if ( diff >= -7 && diff < 7 )
  759.               { set_cmd_put_op(dp, cldev, pcls,
  760.                        op + (int)diff + 8, 1);
  761.                 break;
  762.               }
  763.             set_cmd_put_op(dp, cldev, pcls, op, 2);
  764. b1:            dp[1] = (byte)color;
  765.           }
  766.        }
  767.     *pcolor = color;
  768.     return 0;
  769. }
  770.  
  771. /* Put out a command to set the tile colors. */
  772. int
  773. cmd_set_tile_colors(gx_device_clist_writer *cldev, gx_clist_state *pcls,
  774.   gx_color_index color0, gx_color_index color1)
  775. {    if ( color0 != pcls->tile_colors[0] )
  776.        {    int code = cmd_put_color(cldev, pcls,
  777.                      &clist_select_tile_color0,
  778.                      color0, &pcls->tile_colors[0]);
  779.         if ( code < 0 )
  780.           return code;
  781.        }
  782.     if ( color1 != pcls->tile_colors[1] )
  783.        {    int code = cmd_put_color(cldev, pcls,
  784.                      &clist_select_tile_color1,
  785.                      color1, &pcls->tile_colors[1]);
  786.         if ( code < 0 )
  787.           return code;
  788.        }
  789.     return 0;
  790. }
  791.  
  792. /* Put out a command to set the tile phase. */
  793. int
  794. cmd_set_tile_phase(gx_device_clist_writer *cldev, gx_clist_state *pcls,
  795.   int px, int py)
  796. {    int pcsize;
  797.     byte *dp;
  798.  
  799.     pcls->tile_phase.x = px;
  800.     pcls->tile_phase.y = py;
  801.     pcsize = 1 + cmd_sizexy(pcls->tile_phase);
  802.     set_cmd_put_op(dp, cldev, pcls, (byte)cmd_opv_set_tile_phase, pcsize);
  803.     ++dp;
  804.     cmd_putxy(pcls->tile_phase, dp);
  805.     return 0;
  806. }
  807.  
  808. /* Write a command to enable or disable the logical operation. */
  809. int
  810. cmd_put_enable_lop(gx_device_clist_writer *cldev, gx_clist_state *pcls,
  811.   int enable)
  812. {    byte *dp;
  813.     set_cmd_put_op(dp, cldev, pcls,
  814.                (byte)(enable ? cmd_opv_enable_lop :
  815.                   cmd_opv_disable_lop),
  816.                1);
  817.     pcls->lop_enabled = enable;
  818.     return 0;
  819. }
  820.  
  821. /* Write a command to enable or disable clipping. */
  822. /* This routine is only called if the path extensions are included. */
  823. int
  824. cmd_put_enable_clip(gx_device_clist_writer *cldev, gx_clist_state *pcls,
  825.   int enable)
  826. {    byte *dp;
  827.     set_cmd_put_op(dp, cldev, pcls,
  828.                (byte)(enable ? cmd_opvar_enable_clip :
  829.                   cmd_opvar_disable_clip),
  830.                1);
  831.     pcls->clip_enabled = enable;
  832.     return 0;
  833. }
  834.  
  835. /* Write a command to set the logical operation. */
  836. int
  837. cmd_set_lop(gx_device_clist_writer *cldev, gx_clist_state *pcls,
  838.   gs_logical_operation_t lop)
  839. {    byte *dp;
  840.     uint lop_msb = lop >> 6;
  841.  
  842.     set_cmd_put_op(dp, cldev, pcls,
  843.                cmd_opv_set_misc, 2 + cmd_size_w(lop_msb));
  844.     dp[1] = cmd_set_misc_lop + (lop & 0x3f);
  845.     cmd_put_w(lop_msb, dp + 2);
  846.     pcls->lop = lop;
  847.     return 0;
  848. }
  849.  
  850. /* ---------------- Driver interface ---------------- */
  851.  
  852. private int
  853. clist_get_band(gx_device *dev, int y, int *band_start)
  854. {    int band_height = cdev->page_band_height;
  855.     int start;
  856.  
  857.     if ( y < 0 )
  858.       y = 0;
  859.     else if ( y >= dev->height )
  860.       y = dev->height;
  861.     *band_start = start = y - y % band_height;
  862.     return min(dev->height - start, band_height);
  863. }
  864.