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

  1. /* Copyright (C) 1989, 1990, 1991, 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. /* zpaint.c */
  20. /* Painting operators */
  21. #include "ghost.h"
  22. #include "errors.h"
  23. #include "oper.h"
  24. #include "estack.h"            /* for image[mask] */
  25. #include "gsstruct.h"
  26. #include "ialloc.h"
  27. #include "igstate.h"
  28. #include "ilevel.h"
  29. #include "store.h"
  30. #include "gscspace.h"
  31. #include "gsmatrix.h"
  32. #include "gsimage.h"
  33. #include "gspaint.h"
  34. #include "stream.h"
  35. #include "ifilter.h"        /* for stream exception handling */
  36.  
  37. /* Forward references */
  38. /* zimage_setup is used by zimage2.c */
  39. int zimage_setup(P10(int width, int height, gs_matrix *pmat,
  40.   ref *sources, int bits_per_component,
  41.   bool multi, const gs_color_space *pcs, int masked,
  42.   const float *decode, int npop));
  43. /* zimage_opaque_setup is used by zcolor1.c */
  44. int zimage_opaque_setup(P4(os_ptr, bool, const gs_color_space_type _ds *, int));
  45. private int image_setup(P7(os_ptr, int, bool, const gs_color_space_type _ds *, int, const float *, int));
  46. private int image_process(P2(os_ptr, ref *));
  47. private int image_continue(P1(os_ptr));
  48. private int image_process_continue(P1(os_ptr));
  49. private int image_cleanup(P1(os_ptr));
  50.  
  51. /* - fill - */
  52. int
  53. zfill(register os_ptr op)
  54. {    return gs_fill(igs);
  55. }
  56.  
  57. /* - .fillpage - */
  58. int
  59. zfillpage(register os_ptr op)
  60. {    return gs_fillpage(igs);
  61. }
  62.  
  63. /* - eofill - */
  64. int
  65. zeofill(register os_ptr op)
  66. {    return gs_eofill(igs);
  67. }
  68.  
  69. /* - stroke - */
  70. int
  71. zstroke(register os_ptr op)
  72. {    return gs_stroke(igs);
  73. }
  74.  
  75. /* Standard decoding maps for images. */
  76. static const float decode_01[8] = { 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0 };
  77. static const float decode_10[8] = { 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0 };
  78.  
  79. /* <width> <height> <bits/sample> <matrix> <datasrc> image - */
  80. int
  81. zimage(register os_ptr op)
  82. {    return zimage_opaque_setup(op, false, &gs_color_space_type_DeviceGray, 5);
  83. }
  84.  
  85. /* <width> <height> <paint_1s> <matrix> <datasrc> imagemask - */
  86. int
  87. zimagemask(register os_ptr op)
  88. {    check_type(op[-2], t_boolean);
  89.     return image_setup(op, 1, false, &gs_color_space_type_DeviceGray, 1,
  90.                (op[-2].value.boolval ? decode_10 : decode_01), 5);
  91. }
  92.  
  93. /* Common setup for image and colorimage. */
  94. int
  95. zimage_opaque_setup(register os_ptr op, bool multi,
  96.   const gs_color_space_type _ds *pcst, int npop)
  97. {    check_int_leu(op[-2], 8);    /* bits/sample */
  98.     return image_setup(op, (int)op[-2].value.intval, multi, pcst, 0, decode_01, npop);
  99. }
  100.  
  101. /* Common setup for [color]image and imagemask. */
  102. private int
  103. image_setup(register os_ptr op, int bps, bool multi,
  104.   const gs_color_space_type _ds *pcst, int masked, const float *decode,
  105.   int npop)
  106. {    gs_matrix mat;
  107.     int code;
  108.     gs_color_space cs;
  109.     check_type(op[-4], t_integer);    /* width */
  110.     check_type(op[-3], t_integer);    /* height */
  111.     if ( op[-4].value.intval <= 0 || op[-3].value.intval < 0 )
  112.         return_error(e_rangecheck);
  113.     if ( (code = read_matrix(op - 1, &mat)) < 0 )
  114.         return code;
  115.     cs.type = pcst;
  116.     return zimage_setup((int)op[-4].value.intval,
  117.                 (int)op[-3].value.intval,
  118.                 &mat, op, bps, multi, &cs, masked, decode, npop);
  119. }
  120.  
  121. /* Common setup for Level 1 image/imagemask/colorimage and */
  122. /* the Level 2 dictionary form of image/imagemask. */
  123. int
  124. zimage_setup(int width, int height, gs_matrix *pmat,
  125.   ref *sources, int bits_per_component,
  126.   bool multi, const gs_color_space *pcs,
  127.   int masked, const float *decode, int npop)
  128. {    int code;
  129.     gs_image_enum *penum;
  130.     int px;
  131.     ref *pp;
  132.     int num_sources = (multi ? pcs->type->num_components : 1);
  133.     /* We push on the estack: */
  134.     /*    Control mark, 4 procs, last plane index, */
  135.     /*    enumeration structure. */
  136. #define inumpush 7
  137.     check_estack(inumpush + 2);    /* stuff above, + continuation + proc */
  138.     /* Note that the "procedures" might not be procedures, */
  139.     /* but might be strings or files (Level 2 only). */
  140.     for ( px = 0, pp = sources; px < num_sources; px++, pp++ )
  141.     {    switch ( r_type(pp) )
  142.         {
  143.         case t_file:
  144.             if ( !level2_enabled )
  145.                 return_error(e_typecheck);
  146.             /* falls through */
  147.         case t_string:
  148.             check_read(*pp);
  149.             break;
  150.         default:
  151.             check_proc(*pp);
  152.         }
  153.     }
  154.     if ( height == 0 )
  155.         return 0;    /* empty image */
  156.     if ( masked != 0 && decode != 0 )
  157.     {    /* Make sure decode is 0..1 or 1..0 */
  158.         if ( decode[0] == 0.0 && decode[1] == 1.0 )
  159.             masked = -1;
  160.         else if ( decode[0] == 1.0 && decode[1] == 0.0 )
  161.             masked = 1;
  162.         else
  163.             return_error(e_rangecheck);
  164.     }
  165.     if ( (penum = gs_image_enum_alloc(imemory, "image_setup")) == 0 )
  166.         return_error(e_VMerror);
  167.     code = (masked != 0 ?
  168.         gs_imagemask_init(penum, igs, width, height,
  169.                   masked < 0, pmat, 1) :
  170.         gs_image_init(penum, igs, width, height, bits_per_component,
  171.                   multi, pcs, decode, pmat) );
  172.     if ( code < 0 )
  173.     {    ifree_object(penum, "image_setup");
  174.         return code;
  175.     }
  176.     push_mark_estack(es_other, image_cleanup);
  177.     ++esp;
  178.     for ( px = 0, pp = sources; px < 4; esp++, px++, pp++ )
  179.       if ( px < num_sources )
  180.         *esp = *pp;
  181.       else
  182.         make_null(esp);
  183.     make_int(esp, 0);        /* current plane */
  184.     ++esp;
  185.     make_istruct(esp, 0, penum);
  186.     pop(npop);
  187.     push_op_estack(image_process_continue);
  188.     return o_push_estack;
  189. }
  190. /* Continuation procedure.  Hand the string to the enumerator. */
  191. private int
  192. image_continue(register os_ptr op)
  193. {    ref sref;
  194.     if ( !r_has_type_attrs(op, t_string, a_read) )
  195.     {    /* Procedure didn't return a (readable) string.  Quit. */
  196.         esp -= inumpush;
  197.         image_cleanup(op);
  198.         return_error(!r_has_type(op, t_string) ? e_typecheck : e_invalidaccess);
  199.     }
  200.     sref = *op;
  201.     pop(1);
  202.     return image_process(osp, &sref); /* osp because we did a pop */
  203. }
  204. /* Continue after an interrupt or a callout. */
  205. private int
  206. image_process_continue(os_ptr op)
  207. {    return image_process(op, NULL);
  208. }
  209. /* Process data from an image data source. */
  210. private int
  211. image_process(os_ptr op, ref *psrc)
  212. {    gs_image_enum *penum = r_ptr(esp, gs_image_enum);
  213.     ref *psref = psrc;
  214.     uint size, used;
  215.     int code;
  216.     int px;
  217.     es_ptr pproc;
  218.     if ( psref != NULL )
  219.       goto sw;
  220. rd:    px = (int)(esp[-1].value.intval);
  221.     pproc = esp - 5;
  222.     if ( px == 4 || r_has_type(pproc + px, t_null) )
  223.         esp[-1].value.intval = px = 0;
  224.     psref = pproc + px;
  225. sw:    switch ( r_type(psref) )
  226.     {
  227.     case t_string:
  228.         size = r_size(psref);
  229.         code = gs_image_next(penum, psref->value.bytes, size, &used);
  230.         break;
  231.     case t_file:
  232.     {    stream *s = psref->value.pfile;
  233.         while ( (size = sbufavailable(s)) == 0 )
  234.         {    int next = sgetc(s);
  235.             if ( next >= 0 )
  236.             {    sputback(s);
  237.                 continue;
  238.             }
  239.             switch ( next )
  240.             {
  241.             case EOFC:
  242.                 break;        /* with size = 0 */
  243.             case INTC:
  244.                 return s_handle_intc(NULL, image_process_continue);
  245.             case CALLC:
  246.                 return s_proc_read_call(s, psref, NULL,
  247.                             image_process_continue);
  248.             default:
  249.             /* case ERRC: */
  250.                 return_error(e_ioerror);
  251.             }
  252.             break;            /* for EOFC */
  253.         }
  254.         used = 0;        /* in case of failure */
  255.         code = gs_image_next(penum, sbufptr(s), size, &used);
  256.         sskip(s, used);
  257.     }    break;
  258.     default:            /* procedure */
  259.         push_op_estack(image_continue);
  260.         *++esp = *psref;
  261.         return o_push_estack;
  262.     }
  263.     if ( size == 0 || code != 0 )    /* stop now */
  264.     {    esp -= inumpush;
  265.         image_cleanup(op);
  266.         if ( code < 0 ) return code;
  267.         return o_pop_estack;
  268.     }
  269.     ++(esp[-1].value.intval);
  270.     goto rd;
  271. }
  272. /* Clean up after enumerating an image */
  273. private int
  274. image_cleanup(os_ptr op)
  275. {    gs_image_enum *penum = r_ptr(esp + inumpush, gs_image_enum);
  276.     gs_image_cleanup(penum);
  277.     ifree_object(penum, "image_cleanup");
  278.     return 0;
  279. }
  280.  
  281. /* ------ Non-standard operators ------ */
  282.  
  283. /* <width> <height> <data> .imagepath - */
  284. int
  285. zimagepath(register os_ptr op)
  286. {    int code;
  287.     check_type(op[-2], t_integer);
  288.     check_type(op[-1], t_integer);
  289.     check_read_type(*op, t_string);
  290.     if ( r_size(op) < ((op[-2].value.intval + 7) >> 3) * op[-1].value.intval )
  291.         return_error(e_rangecheck);
  292.     code = gs_imagepath(igs,
  293.         (int)op[-2].value.intval, (int)op[-1].value.intval,
  294.         op->value.const_bytes);
  295.     if ( code == 0 ) pop(3);
  296.     return code;
  297. }
  298.  
  299. /* ------ Initialization procedure ------ */
  300.  
  301. op_def zpaint_op_defs[] = {
  302.     {"0eofill", zeofill},
  303.     {"0fill", zfill},
  304.     {"0.fillpage", zfillpage},
  305.     {"5image", zimage},
  306.     {"5imagemask", zimagemask},
  307.     {"3.imagepath", zimagepath},
  308.     {"0stroke", zstroke},
  309.         /* Internal operators */
  310.     {"1%image_continue", image_continue},
  311.     {"0%image_process_continue", image_process_continue},
  312.     op_def_end(0)
  313. };
  314.