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

  1. /* Copyright (C) 1989, 1992, 1993 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. /* gscolor.c */
  20. /* Color and halftone operators for Ghostscript library */
  21. #include "gx.h"
  22. #include "gserrors.h"
  23. #include "gsstruct.h"
  24. #include "gscspace.h"
  25. #include "gsccolor.h"
  26. #include "gxdcconv.h"
  27. #include "gxdevice.h"            /* for gx_color_index */
  28. #include "gxcmap.h"
  29. #include "gzstate.h"
  30.  
  31. /* Define the standard color space types. */
  32. extern cs_proc_remap_color(gx_remap_DeviceGray);
  33. extern cs_proc_remap_color(gx_remap_DeviceRGB);
  34. const gs_color_space_type
  35.     gs_color_space_type_DeviceGray =
  36.      { gs_color_space_index_DeviceGray, 1,
  37.        gx_init_paint_1, gx_remap_DeviceGray, gx_no_install_cspace,
  38.        gx_no_adjust_cspace_count, gx_no_adjust_color_count,
  39.        gx_no_cspace_enum_ptrs, gx_no_cspace_reloc_ptrs
  40.      },
  41.     gs_color_space_type_DeviceRGB =
  42.      { gs_color_space_index_DeviceRGB, 3,
  43.        gx_init_paint_3, gx_remap_DeviceRGB, gx_no_install_cspace,
  44.        gx_no_adjust_cspace_count, gx_no_adjust_color_count,
  45.        gx_no_cspace_enum_ptrs, gx_no_cspace_reloc_ptrs
  46.      };
  47.  
  48. /* Structure descriptors */
  49. public_st_color_space();
  50. public_st_client_color();
  51.  
  52. /* Initialize colors with 1, 3, or 4 paint components. */
  53. /* (These are only used by setcolorspace.) */
  54. void
  55. gx_init_paint_1(gs_client_color *pcc, const gs_color_space *pcs)
  56. {    pcc->paint.values[0] = 0.0;
  57. }
  58. void
  59. gx_init_paint_3(gs_client_color *pcc, const gs_color_space *pcs)
  60. {    pcc->paint.values[2] = 0.0;
  61.     pcc->paint.values[1] = 0.0;
  62.     pcc->paint.values[0] = 0.0;
  63. }
  64.  
  65. /* Null color space installation procedure. */
  66. int
  67. gx_no_install_cspace(gs_color_space *pcs, gs_state *pgs)
  68. {    return 0;
  69. }
  70.  
  71. /* Null reference count adjustment procedures. */
  72. void
  73. gx_no_adjust_cspace_count(const gs_color_space *pcs, gs_state *pgs, int delta)
  74. {
  75. }
  76. void
  77. gx_no_adjust_color_count(const gs_client_color *pcc, const gs_color_space *pcs, gs_state *pgs, int delta)
  78. {
  79. }
  80.  
  81. /* GC procedures */
  82.  
  83. #define pcs ((gs_color_space *)vptr)
  84.  
  85. private ENUM_PTRS_BEGIN_PROC(color_space_enum_ptrs) {
  86.     return (*pcs->type->enum_ptrs)(pcs, size, index, pep);
  87. ENUM_PTRS_END_PROC }
  88. private RELOC_PTRS_BEGIN(color_space_reloc_ptrs) {
  89.     (*pcs->type->reloc_ptrs)(pcs, size, gcst);
  90. } RELOC_PTRS_END
  91.  
  92. #undef pcs
  93.  
  94. /* Force a parameter into the range [0.0..1.0]. */
  95. #define force_unit(p) (p < 0.0 ? 0.0 : p > 1.0 ? 1.0 : p)
  96. frac gx_color_unit_param(P1(floatp));
  97.  
  98. /* Forward declarations */
  99. void load_transfer_map(P3(gs_state *, gx_transfer_map *, floatp));
  100.  
  101. /* setgray */
  102. int
  103. gs_setgray(gs_state *pgs, floatp gray)
  104. {    if ( pgs->in_cachedevice ) return_error(gs_error_undefined);
  105.     cs_adjust_counts(pgs, -1);
  106.     pgs->ccolor->paint.values[0] = gray;
  107.     pgs->color_space->type = &gs_color_space_type_DeviceGray;
  108.     gx_unset_dev_color(pgs);
  109.     return 0;
  110. }
  111.  
  112. /* currentgray */
  113. float
  114. gs_currentgray(const gs_state *pgs)
  115. {    const gs_client_color *pcc = pgs->ccolor;
  116.     switch ( pgs->color_space->type->index )
  117.     {
  118.     case gs_color_space_index_DeviceGray:
  119.         return pcc->paint.values[0];
  120.     case gs_color_space_index_DeviceRGB:
  121.         return frac2float(color_rgb_to_gray(
  122.             float2frac(pcc->paint.values[0]),
  123.             float2frac(pcc->paint.values[1]),
  124.             float2frac(pcc->paint.values[2]),
  125.             pgs));
  126.     case gs_color_space_index_DeviceCMYK:
  127.         return frac2float(color_cmyk_to_gray(
  128.             float2frac(pcc->paint.values[0]),
  129.             float2frac(pcc->paint.values[1]),
  130.             float2frac(pcc->paint.values[2]),
  131.             float2frac(pcc->paint.values[3]),
  132.             pgs));
  133.     default:
  134.         return 0.0;
  135.     }
  136. }
  137.  
  138. /* sethsbcolor */
  139. int
  140. gs_sethsbcolor(gs_state *pgs, floatp h, floatp s, floatp b)
  141. {    float rgb[3];
  142.     color_hsb_to_rgb(force_unit(h), force_unit(s), force_unit(b), rgb);
  143.     return gs_setrgbcolor(pgs, rgb[0], rgb[1], rgb[2]);
  144. }
  145.  
  146. /* currenthsbcolor */
  147. int
  148. gs_currenthsbcolor(const gs_state *pgs, float pr3[3])
  149. {    float rgb[3];
  150.     gs_currentrgbcolor(pgs, rgb);
  151.     color_rgb_to_hsb(rgb[0], rgb[1], rgb[2], pr3);
  152.     return 0;
  153. }
  154.  
  155. /* setrgbcolor */
  156. int
  157. gs_setrgbcolor(gs_state *pgs, floatp r, floatp g, floatp b)
  158. {    gs_client_color *pcc = pgs->ccolor;
  159.     if ( pgs->in_cachedevice ) return_error(gs_error_undefined);
  160.     cs_adjust_counts(pgs, -1);
  161.     pcc->paint.values[0] = r;
  162.     pcc->paint.values[1] = g;
  163.     pcc->paint.values[2] = b;
  164.     pcc->pattern = 0;            /* for GC */
  165.     pgs->color_space->type = &gs_color_space_type_DeviceRGB;
  166.     gx_unset_dev_color(pgs);
  167.     return 0;
  168. }
  169.  
  170. /* currentrgbcolor */
  171. int
  172. gs_currentrgbcolor(const gs_state *pgs, float pr3[3])
  173. {    const gs_client_color *pcc = pgs->ccolor;
  174.     switch ( pgs->color_space->type->index )
  175.     {
  176.     case gs_color_space_index_DeviceGray:
  177.         pr3[0] = pr3[1] = pr3[2] = pcc->paint.values[0];
  178.         break;
  179.     case gs_color_space_index_DeviceRGB:
  180.         pr3[0] = pcc->paint.values[0];
  181.         pr3[1] = pcc->paint.values[1];
  182.         pr3[2] = pcc->paint.values[2];
  183.         break;
  184.     case gs_color_space_index_DeviceCMYK:
  185.     {    frac frgb[3];
  186.         color_cmyk_to_rgb(
  187.             float2frac(pcc->paint.values[0]),
  188.             float2frac(pcc->paint.values[1]),
  189.             float2frac(pcc->paint.values[2]),
  190.             float2frac(pcc->paint.values[3]),
  191.             pgs, frgb);
  192.         pr3[0] = frac2float(frgb[0]);
  193.         pr3[1] = frac2float(frgb[1]);
  194.         pr3[2] = frac2float(frgb[2]);
  195.     }    break;
  196.     default:
  197.         pr3[0] = pr3[1] = pr3[2] = 0.0;
  198.     }
  199.     return 0;
  200. }
  201.  
  202. /* setalpha */
  203. int
  204. gs_setalpha(gs_state *pgs, floatp alpha)
  205. {    pgs->alpha = (gx_color_value)(force_unit(alpha) * gx_max_color_value);
  206.     gx_unset_dev_color(pgs);
  207.     return 0;
  208. }
  209.  
  210. /* currentalpha */
  211. float
  212. gs_currentalpha(const gs_state *pgs)
  213. {    return (float)pgs->alpha / gx_max_color_value;
  214. }
  215.  
  216. /* settransfer */
  217. /* Remap=0 is used by the interpreter. */
  218. int
  219. gs_settransfer(gs_state *pgs, gs_mapping_proc tproc)
  220. {    return gs_settransfer_remap(pgs, tproc, 1);
  221. }
  222. int
  223. gs_settransfer_remap(gs_state *pgs, gs_mapping_proc tproc, int remap)
  224. {    gx_transfer *ptran = &pgs->transfer;
  225.     /* We can safely decrement the reference counts */
  226.     /* of the non-gray transfer maps, because */
  227.     /* if any of them get freed, the rc_unshare can't fail. */
  228.     rc_decrement(ptran->red, pgs->memory, "gs_settransfer");
  229.     rc_decrement(ptran->green, pgs->memory, "gs_settransfer");
  230.     rc_decrement(ptran->blue, pgs->memory, "gs_settransfer");
  231.     rc_unshare_struct(ptran->gray, gx_transfer_map, &st_transfer_map,
  232.               pgs->memory, goto fail, "gs_settransfer");
  233.     ptran->gray->proc = tproc;
  234.     ptran->red = ptran->gray;
  235.     ptran->green = ptran->gray;
  236.     ptran->blue = ptran->gray;
  237.     ptran->gray->rc.ref_count += 3;
  238.     if ( remap )
  239.     {    load_transfer_map(pgs, ptran->gray, 0.0);
  240.         gx_unset_dev_color(pgs);
  241.     }
  242.     return 0;
  243. fail:    rc_increment(ptran->red);
  244.     rc_increment(ptran->green);
  245.     rc_increment(ptran->blue);
  246.     return_error(gs_error_VMerror);
  247. }
  248.  
  249. /* currenttransfer */
  250. gs_mapping_proc
  251. gs_currenttransfer(const gs_state *pgs)
  252. {    return pgs->transfer.gray->proc;
  253. }
  254.  
  255. /* ------ Non-operator routines ------ */
  256.  
  257. /* Set up black for writing into the character cache. */
  258. void
  259. gx_set_black(gs_state *pgs)
  260. {    gx_device_color *pdc = pgs->dev_color;
  261.     gs_client_color *pcc = pgs->ccolor;
  262.     pcc->paint.values[0] = 0.0;
  263.     pcc->pattern = 0;            /* for GC */
  264.     pgs->color_space->type = &gs_color_space_type_DeviceGray;
  265.     color_set_pure(pdc, 1);
  266. }
  267.  
  268. /* Force a parameter into the range [0..1], */
  269. /* and convert to a frac. */
  270. frac
  271. gx_color_unit_param(floatp fval)
  272. {    if ( fval <= 0.0 )
  273.         return frac_0;
  274.     else if ( fval >= 1.0 )
  275.         return frac_1;
  276.     else
  277.         return float2frac(fval);
  278. }
  279.  
  280. /* ------ Internal routines ------ */
  281.  
  282. /* Load one cached transfer map. */
  283. /* This is exported for gscolor1.c. */
  284. void
  285. load_transfer_map(gs_state *pgs, gx_transfer_map *pmap, floatp min_value)
  286. {    gs_mapping_proc proc = pmap->proc;
  287.     frac *values = pmap->values;
  288.     frac fmin = float2frac(min_value);
  289.     int i;
  290.     for ( i = 0; i < transfer_map_size; i++ )
  291.     {    float fval = (*proc)(pgs, (float)i / (transfer_map_size - 1));
  292.         values[i] =
  293.             (fval < min_value ? fmin :
  294.              fval >= 1.0 ? frac_1 :
  295.              float2frac(fval));
  296.     }
  297. }
  298.