home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 1992, 1993, 1994 Aladdin Enterprises. All rights reserved.
-
- This file is part of Aladdin Ghostscript.
-
- Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
- or distributor accepts any responsibility for the consequences of using it,
- or for whether it serves any particular purpose or works at all, unless he
- or she says so in writing. Refer to the Aladdin Ghostscript Free Public
- License (the "License") for full details.
-
- Every copy of Aladdin Ghostscript must include a copy of the License,
- normally in a plain ASCII text file named PUBLIC. The License grants you
- the right to copy, modify and redistribute Aladdin Ghostscript, but only
- under certain conditions described in the License. Among other things, the
- License requires that the copyright notice and this notice be preserved on
- all copies.
- */
-
- /* zcolor2.c */
- /* Level 2 color operators */
- #include "ghost.h"
- #include "errors.h"
- #include "oper.h"
- #include "gscolor.h"
- #include "gscspace.h"
- #include "gsmatrix.h"
- #include "gsstruct.h"
- #include "gxfixed.h" /* for gxcolor2.h */
- #include "gxcolor2.h"
- #include "gxdevice.h"
- #include "gxdevmem.h" /* for gxpcolor.h */
- #include "gxpcolor.h"
- #include "estack.h"
- #include "ialloc.h"
- #include "istruct.h"
- #include "idict.h"
- #include "idparam.h"
- #include "igstate.h"
- #include "store.h"
-
- /* Forward references */
- private int store_color_params(P3(os_ptr, const gs_paint_color *, const gs_color_space *));
- private int load_color_params(P3(os_ptr, gs_paint_color *, const gs_color_space *));
- private int zPaintProc(P2(const gs_client_color *, gs_state *));
- private int pattern_paint_prepare(P1(os_ptr));
- private int pattern_paint_finish(P1(os_ptr));
-
- /*
- * Define the structure for remembering the pattern dictionary.
- * This is the "client data" in the template.
- * See zgstate.c (int_gstate) or zfont2.c (font_data) for information
- * as to why we define this as a structure rather than a ref array.
- */
- typedef struct int_pattern_s {
- ref dict;
- } int_pattern;
- gs_private_st_ref_struct(st_int_pattern, int_pattern, "int_pattern");
-
- /* Initialize the Pattern cache. */
- private void
- zcolor2_init(void)
- { gstate_set_pattern_cache(igs,
- gx_pattern_alloc_cache(imemory_system,
- pattern_cache_default_max_tiles,
- pattern_cache_default_max_bits));
- }
-
- /* <pattern> <matrix> .buildpattern <pattern> <instance> */
- int
- zbuildpattern(os_ptr op)
- { os_ptr op1 = op - 1;
- int code;
- gs_matrix mat;
- int PatternType;
- float BBox[4];
- gs_client_pattern template;
- int_pattern *pdata;
- gs_client_color cc_instance;
- ref *pPaintProc;
- check_type(*op1, t_dictionary);
- check_dict_read(*op1);
- if ( (code = read_matrix(op, &mat)) < 0 ||
- (code = dict_uid_param(op1, &template.uid, 1, imemory)) != 1 ||
- (code = dict_int_param(op1, "PatternType", 1, 1, 0, &PatternType)) < 0 ||
- (code = dict_int_param(op1, "PaintType", 1, 2, 0, &template.PaintType)) < 0 ||
- (code = dict_int_param(op1, "TilingType", 1, 3, 0, &template.TilingType)) < 0 ||
- (code = dict_float_array_param(op1, "BBox", 4, BBox, NULL)) != 4 ||
- (code = dict_float_param(op1, "XStep", 0.0, &template.XStep)) != 0 ||
- (code = dict_float_param(op1, "YStep", 0.0, &template.YStep)) != 0 ||
- (code = dict_find_string(op1, "PaintProc", &pPaintProc)) <= 0
- )
- return_error((code < 0 ? code : e_rangecheck));
- check_proc(*pPaintProc);
- template.BBox.p.x = BBox[0];
- template.BBox.p.y = BBox[1];
- template.BBox.q.x = BBox[2];
- template.BBox.q.y = BBox[3];
- template.PaintProc = zPaintProc;
- pdata = ialloc_struct(int_pattern, &st_int_pattern, "int_pattern");
- if ( pdata == 0 )
- return_error(e_VMerror);
- template.client_data = pdata;
- pdata->dict = *op1;
- code = gs_makepattern(&cc_instance, &template, &mat, igs);
- if ( code < 0 )
- { ifree_object(pdata, "int_pattern");
- return code;
- }
- make_istruct(op, a_readonly, cc_instance.pattern);
- return code;
- }
-
- /* - currentcolor <param1> ... <paramN> */
- int
- zcurrentcolor(register os_ptr op)
- { const gs_client_color *pc = gs_currentcolor(igs);
- const gs_color_space *pcs = gs_currentcolorspace(igs);
- int n;
- check_ostack(5); /* Worst case: CMYK + pattern */
- if ( pcs->type->index == gs_color_space_index_Pattern )
- { n = 1;
- if ( pc->pattern->template.PaintType == 2 ) /* uncolored */
- n += store_color_params(op, &pc->paint,
- (const gs_color_space *)&pcs->params.pattern.base_space);
- op[n] = istate->pattern;
- }
- else
- n = store_color_params(op, &pc->paint, pcs);
- push(n);
- return 0;
- }
-
- /* - currentoverprint <bool> */
- int
- zcurrentoverprint(register os_ptr op)
- { push(1);
- make_bool(op, gs_currentoverprint(igs));
- return 0;
- }
-
- /* <param1> ... <paramN> setcolor - */
- int
- zsetcolor(register os_ptr op)
- { gs_client_color c;
- const gs_color_space *pcs = gs_currentcolorspace(igs);
- int n, code;
- gs_pattern_instance *pinst = 0;
- if ( pcs->type->index == gs_color_space_index_Pattern )
- { /* Make sure *op is a real Pattern. */
- ref *pImpl;
- check_type(*op, t_dictionary);
- check_dict_read(*op);
- if ( dict_find_string(op, "Implementation", &pImpl) <= 0 ||
- !r_has_stype(pImpl, imemory, st_pattern_instance)
- )
- return_error(e_rangecheck);
- pinst = r_ptr(pImpl, gs_pattern_instance);
- c.pattern = pinst;
- if ( pinst->template.PaintType == 2 ) /* uncolored */
- { if ( !pcs->params.pattern.has_base_space )
- return_error(e_rangecheck);
- n = load_color_params(op - 1, &c.paint,
- (const gs_color_space *)&pcs->params.pattern.base_space);
- if ( n < 0 ) return n;
- n++;
- }
- else
- n = 1;
- }
- else
- { n = load_color_params(op, &c.paint, pcs);
- c.pattern = 0; /* for GC */
- }
- if ( n < 0 )
- return n;
- code = gs_setcolor(igs, &c);
- if ( code < 0 )
- return code;
- if ( pinst != 0 )
- istate->pattern = *op;
- pop(n);
- return code;
- }
-
- /* <bool> setoverprint - */
- int
- zsetoverprint(register os_ptr op)
- { check_type(*op, t_boolean);
- gs_setoverprint(igs, op->value.boolval);
- pop(1);
- return 0;
- }
-
- /* ------ Initialization procedure ------ */
-
- op_def zcolor2_l2_op_defs[] = {
- op_def_begin_level2(),
- {"2.buildpattern", zbuildpattern},
- {"0currentcolor", zcurrentcolor},
- {"0currentoverprint", zcurrentoverprint},
- {"1setcolor", zsetcolor},
- {"1setoverprint", zsetoverprint},
- /* Internal operators */
- {"0%pattern_paint_prepare", pattern_paint_prepare},
- {"0%pattern_paint_finish", pattern_paint_finish},
- op_def_end(zcolor2_init)
- };
-
- /* ------ Internal procedures ------ */
-
- /* Store non-pattern color values on the operand stack. */
- /* Return the number of values stored. */
- private int
- store_color_params(os_ptr op, const gs_paint_color *pc,
- const gs_color_space *pcs)
- { int n = pcs->type->num_components;
- make_reals(op + 1, pc->values, n);
- return n;
- }
-
- /* Load non-pattern color values from the operand stack. */
- /* Return the number of values stored. */
- private int
- load_color_params(os_ptr op, gs_paint_color *pc,
- const gs_color_space *pcs)
- { int n = pcs->type->num_components;
- int code = num_params(op, n, pc->values);
- if ( code < 0 ) return code;
- return n;
- }
-
- /* Render the pattern by calling the PaintProc. */
- private int pattern_paint_cleanup(P1(os_ptr));
- private int
- zPaintProc(const gs_client_color *pcc, gs_state *pgs)
- { /* Just schedule a call on the real PaintProc. */
- check_estack(2);
- esp++;
- push_op_estack(pattern_paint_prepare);
- return e_InsertProc;
- }
- /* Prepare to run the PaintProc. */
- private int
- pattern_paint_prepare(os_ptr op)
- { gs_state *pgs = igs;
- gs_pattern_instance *pinst = gs_currentcolor(pgs)->pattern;
- ref *pdict = &((int_pattern *)pinst->template.client_data)->dict;
- gx_device_pattern_accum *pdev;
- int code;
- ref *ppp;
- check_estack(5);
- pdev = gx_pattern_accum_alloc(imemory, "pattern_paint_prepare");
- if ( pdev == 0 )
- return_error(e_VMerror);
- pdev->instance = pinst;
- pdev->bitmap_memory = gstate_pattern_cache(pgs)->memory;
- code = (*dev_proc(pdev, open_device))((gx_device *)pdev);
- if ( code < 0 )
- { ifree_object(pdev, "pattern_paint_prepare");
- return code;
- }
- code = gs_gsave(pgs);
- if ( code < 0 )
- return code;
- code = gs_setgstate(pgs, pinst->saved);
- if ( code < 0 )
- { gs_grestore(pgs);
- return code;
- }
- gx_set_device_only(pgs, (gx_device *)pdev);
- push_mark_estack(es_other, pattern_paint_cleanup);
- ++esp;
- make_istruct(esp, 0, pdev);
- push_op_estack(pattern_paint_finish);
- dict_find_string(pdict, "PaintProc", &ppp); /* can't fail */
- *++esp = *ppp;
- *++esp = *pdict; /* (push on ostack) */
- return o_push_estack;
- }
- /* Save the rendered pattern. */
- private int
- pattern_paint_finish(os_ptr op)
- { gx_device_pattern_accum *pdev = r_ptr(esp, gx_device_pattern_accum);
- gx_color_tile *ctile;
- int code = gx_pattern_cache_add_entry(igs, pdev, &ctile);
- if ( code < 0 )
- return code;
- if ( ctile->bits.data != 0 )
- pdev->bits->bitmap_memory = 0; /* don't free the bits */
- if ( ctile->mask.data != 0 )
- pdev->mask->bitmap_memory = 0; /* ditto */
- esp -= 2;
- pattern_paint_cleanup(op);
- return o_pop_estack;
- }
- /* Clean up after rendering a pattern. Note that iff the rendering */
- /* succeeded, closing the accumulator won't free the bits. */
- private int
- pattern_paint_cleanup(os_ptr op)
- { gx_device_pattern_accum *pdev = r_ptr(esp + 2, gx_device_pattern_accum);
- gs_grestore(igs);
- (*dev_proc(pdev, close_device))((gx_device *)pdev);
- ifree_object(pdev, "pattern_paint_cleanup");
- return 0;
- }
-