|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T g
Length: 9260 (0x242c) Types: TextFile Names: »gscolor.c«
└─⟦a05ed705a⟧ Bits:30007078 DKUUG GNU 2/12/89 └─⟦ff23ba0e6⟧ »./ghostscript-1.3.tar.Z« └─⟦a24a58cd3⟧ └─⟦this⟧ »gscolor.c«
/* Copyright (C) 1989 Aladdin Enterprises. All rights reserved. Distributed by Free Software Foundation, Inc. This file is part of Ghostscript. Ghostscript is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the Ghostscript General Public License for full details. Everyone is granted permission to copy, modify and redistribute Ghostscript, but only under the conditions described in the Ghostscript General Public License. A copy of this license is supposed to have been given to you along with Ghostscript so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ /* gscolor.c */ /* Color and halftone operators for GhostScript library */ #include "gx.h" #include "malloc_.h" #include "gserrors.h" #include "gxfixed.h" /* ditto */ #include "gxmatrix.h" /* for gzstate.h */ #include "gxdevice.h" /* for gx_color_index */ #include "gzstate.h" #include "gzcolor.h" #include "gzhalfto.h" /* Exported values */ int gs_screen_enum_sizeof = sizeof(gs_screen_enum); int gs_color_sizeof = sizeof(gs_color); /* Forward declarations */ private int check_unit(P2(floatp, float *)); private int tri_param(P4(floatp, floatp, floatp, color_param3 *)); private void tri_return(P2(color_param3 *, float [3])); /* Imported from gxcolor.c */ void gx_color_from_hsb(P1(gs_color *)), gx_color_from_rgb(P1(gs_color *)), gx_sort_ht_order(P2(ht_bit *, uint)); /* setgray */ int gs_setgray(gs_state *pgs, floatp gray) { float fgray; int code; gs_color *pcolor = pgs->color; if ( pgs->in_show ) return_error(gs_error_undefined); code = check_unit(gray, &fgray); if ( !code ) { pcolor->red = pcolor->green = pcolor->blue = pcolor->brightness = max_color_param * fgray; pcolor->saturation = 0; } return code; } /* currentgray */ float gs_currentgray(gs_state *pgs) { return (float)(pgs->color->brightness / (float)max_color_param); } /* setcolor */ int gs_setcolor(gs_state *pgs, gs_color *pcolor) { if ( pgs->in_show ) return_error(gs_error_undefined); *pgs->color = *pcolor; return 0; } /* currentcolor */ int gs_currentcolor(gs_state *pgs, gs_color *pcolor) { *pcolor = *pgs->color; return 0; } /* sethsbcolor */ int gs_sethsbcolor(gs_state *pgs, floatp h, floatp s, floatp b) { if ( pgs->in_show ) return_error(gs_error_undefined); return gs_hsbcolor(h, s, b, pgs->color); } /* currenthsbcolor */ int gs_currenthsbcolor(gs_state *pgs, float pr3[3]) { tri_return(&pgs->color->hsb, pr3); return 0; } /* setrgbcolor */ int gs_setrgbcolor(gs_state *pgs, floatp r, floatp g, floatp b) { if ( pgs->in_show ) return_error(gs_error_undefined); return gs_rgbcolor(r, g, b, pgs->color); } /* currentrgbcolor */ int gs_currentrgbcolor(gs_state *pgs, float pr3[3]) { tri_return(&pgs->color->rgb, pr3); return 0; } /* colorhsb */ int gs_colorhsb(gs_color *pcolor, float pr3[3]) { tri_return(&pcolor->hsb, pr3); } /* colorrgb */ int gs_colorrgb(gs_color *pcolor, float pr3[3]) { tri_return(&pcolor->rgb, pr3); return 0; } /* hsbcolor */ int gs_hsbcolor(floatp h, floatp s, floatp b, gs_color *pcolor) { int code = tri_param(h, s, b, &pcolor->hsb); if ( !code ) gx_color_from_hsb(pcolor); return code; } /* rgbcolor */ int gs_rgbcolor(floatp h, floatp s, floatp b, gs_color *pcolor) { int code = tri_param(h, s, b, &pcolor->rgb); if ( !code ) gx_color_from_rgb(pcolor); return code; } /* setscreen */ int gs_setscreen(gs_state *pgs, floatp freq, floatp angle, float (*proc)(P2(floatp, floatp))) { gs_screen_enum senum; gs_point pt; int code = gs_screen_init(&senum, pgs, freq, angle); if ( code < 0 ) return code; while ( (code = gs_screen_currentpoint(&senum, &pt)) == 0 ) if ( (code = gs_screen_next(&senum, (*proc)(pt.x, pt.y))) < 0 ) return code; if ( code < 0 ) return code; pgs->ht_proc = proc; return 0; } /* currentscreen */ int gs_currentscreen(gs_state *pgs, float *pfreq, float *pangle, float (**pproc)(P2(floatp, floatp))) { halftone *pht = pgs->halftone; *pfreq = pht->frequency; *pangle = pht->angle; *pproc = pgs->ht_proc; return 0; } /* ------ Halftone sampling ------ */ /* Set up for halftone sampling */ int gs_screen_init(gs_screen_enum *penum, gs_state *pgs, floatp freq, floatp angle) { int cwidth, cheight; int code; ht_bit *order; if ( freq < 0 ) return_error(gs_error_rangecheck); /* Convert the frequency to cell width and height */ { float cell_size = 72.0 / freq; gs_point pcwh; gs_matrix imat; int dev_w, dev_h; gs_deviceparams(gs_currentdevice(pgs), &imat, &dev_w, &dev_h); if ( (code = gs_distance_transform(cell_size, cell_size, &imat, &pcwh)) < 0 ) return code; cwidth = pcwh.x, cheight = pcwh.y; } if ( cwidth < 0 ) cwidth = -cwidth; if ( cwidth == 0 ) cwidth = 1; if ( cheight < 0 ) cheight = -cheight; if ( cheight == 0 ) cheight = 1; if ( cwidth > (unsigned short)(-1) / cheight ) return_error(gs_error_rangecheck); order = (ht_bit *)malloc(cwidth * cheight * sizeof(ht_bit)); if ( order == 0 ) return_error(gs_error_VMerror); penum->freq = freq; penum->angle = angle; penum->order = order; penum->width = cwidth; penum->height = cheight; penum->x = penum->y = 0; penum->pgs = pgs; /* The transformation matrix must include normalization to the */ /* interval (-1..1), and rotation by the negative of the angle. */ { float xscale = 2.0 / cwidth; float yscale = 2.0 / cheight; gs_matrix mat; gs_make_identity(&mat); mat.xx = xscale; mat.yy = yscale; mat.tx = xscale * 0.5 - 1.0; mat.ty = yscale * 0.5 - 1.0; if ( (code = gs_matrix_rotate(&mat, -angle, &penum->mat)) < 0 ) return code; #ifdef DEBUG if ( gs_debug['h'] ) printf("[h]Screen: w=%d h=%d [%f %f %f %f %f %f]\n", cwidth, cheight, penum->mat.xx, penum->mat.xy, penum->mat.yx, penum->mat.yy, penum->mat.tx, penum->mat.ty); #endif } return 0; } /* Report current point for sampling */ private int gx_screen_finish(P1(gs_screen_enum *)); int gs_screen_currentpoint(gs_screen_enum *penum, gs_point *ppt) { gs_point pt; int code; if ( penum->y >= penum->height ) /* all done */ return gx_screen_finish(penum); if ( (code = gs_point_transform((floatp)penum->x, (floatp)penum->y, &penum->mat, &pt)) < 0 ) return code; if ( pt.x < -1.0 ) pt.x += 2.0; else if ( pt.x > 1.0 ) pt.x -= 2.0; if ( pt.y < -1.0 ) pt.y += 2.0; else if ( pt.y > 1.0 ) pt.y -= 2.0; *ppt = pt; return 0; } /* Record next halftone sample */ int gs_screen_next(gs_screen_enum *penum, floatp value) { ushort sample; ht_bit *order = penum->order; if ( value < -1.0 || value > 1.0 ) return_error(gs_error_rangecheck); sample = (ushort)((value + 1.0) / 2.0 * (ushort)(-1)); #ifdef DEBUG if ( gs_debug['h'] ) { gs_point pt; gs_screen_currentpoint(penum, &pt); printf("[h]sample x=%d y=%d (%f,%f): %f -> %u\n", penum->x, penum->y, pt.x, pt.y, value, sample); } #endif order[penum->y * penum->width + penum->x].mask = sample; if ( ++(penum->x) >= penum->width ) penum->x = 0, ++(penum->y); return 0; } /* All points have been sampled. */ /* Finish constructing the halftone. */ private int gx_screen_finish(gs_screen_enum *penum) { ht_bit *order = penum->order; uint size = penum->width * penum->height; uint i; int code; halftone *pht; /* Label each element with its ordinal position. */ for ( i = 0; i < size; i++ ) order[i].offset = i; /* Sort the samples in increasing order by value. */ gx_sort_ht_order(order, size); /* Set up the actual halftone description. */ code = gx_ht_construct_order(penum->order, penum->width, penum->height); if ( code < 0 ) return code; pht = penum->pgs->halftone; pht->frequency = penum->freq; pht->angle = penum->angle; pht->width = penum->width; pht->height = penum->height; pht->order = penum->order; pht->order_size = pht->width * pht->height; return 1; /* all done */ } /* ------ Internal routines ------ */ /* Check a parameter for being in the range [0..1], */ /* within reasonable rounding error. */ private int check_unit(floatp fval, float *pp) { if ( fval < 0.0 ) { if ( fval < -0.00001 ) return_error(gs_error_rangecheck); *pp = 0.0; } else if ( fval > 1.0 ) { if ( fval > 1.00001 ) return_error(gs_error_rangecheck); *pp = 1.0; } else *pp = fval; return 0; } /* Get 3 real parameters in the range [0..1], */ /* and convert them to color_params. */ /* If any of them are invalid, none of the return values are set. */ private int tri_param(floatp p1, floatp p2, floatp p3, color_param3 *pq3) { int code; float f1, f2, f3; if ( (code = check_unit(p1, &f1)) < 0 || (code = check_unit(p2, &f2)) < 0 || (code = check_unit(p3, &f3)) < 0 ) return code; pq3->q1 = p1 * max_color_param; pq3->q2 = p2 * max_color_param; pq3->q3 = p3 * max_color_param; return 0; } /* Convert 3 color_params to reals */ private void tri_return(color_param3 *pq3, float pr3[3]) { pr3[0] = pq3->q1 / (float)max_color_param; pr3[1] = pq3->q2 / (float)max_color_param; pr3[2] = pq3->q3 / (float)max_color_param; }