Files correlati : pdflib Ricompilazione Demo : [ ] Commento : Aggiornata PDFlib git-svn-id: svn://10.65.10.50/trunk@17433 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			1179 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1179 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
/*---------------------------------------------------------------------------*
 | 
						|
 |              PDFlib - A library for generating PDF on the fly             |
 | 
						|
 +---------------------------------------------------------------------------+
 | 
						|
 | Copyright (c) 1997-2007 Thomas Merz and PDFlib GmbH. All rights reserved. |
 | 
						|
 +---------------------------------------------------------------------------+
 | 
						|
 |                                                                           |
 | 
						|
 |    This software is subject to the PDFlib license. It is NOT in the       |
 | 
						|
 |    public domain. Extended versions and commercial licenses are           |
 | 
						|
 |    available, please check http://www.pdflib.com.                         |
 | 
						|
 |                                                                           |
 | 
						|
 *---------------------------------------------------------------------------*/
 | 
						|
 | 
						|
/* $Id: p_color.c,v 1.3 2008-10-20 14:34:15 guy Exp $
 | 
						|
 *
 | 
						|
 * PDFlib color routines
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
#define P_COLOR_C
 | 
						|
 | 
						|
#include "p_intern.h"
 | 
						|
#include "p_color.h"
 | 
						|
 | 
						|
 | 
						|
static const pdc_keyconn pdf_colortype_keylist[] =
 | 
						|
{
 | 
						|
    {"none",         color_none},
 | 
						|
    {"gray",         color_gray},
 | 
						|
    {"rgb",          color_rgb},
 | 
						|
    {"cmyk",         color_cmyk},
 | 
						|
    {"spotname",     color_spotname},
 | 
						|
    {"spot",         color_spot},
 | 
						|
    {"pattern",      color_pattern},
 | 
						|
    {"iccbasedgray", color_iccbasedgray},
 | 
						|
    {"iccbasedrgb",  color_iccbasedrgb},
 | 
						|
    {"iccbasedcmyk", color_iccbasedcmyk},
 | 
						|
    {"lab",          color_lab},
 | 
						|
    {NULL, 0}
 | 
						|
};
 | 
						|
 | 
						|
static const pdc_keyconn pdf_colorcomp_keylist[] =
 | 
						|
{
 | 
						|
    {"none",         0},
 | 
						|
    {"gray",         1},
 | 
						|
    {"rgb",          3},
 | 
						|
    {"cmyk",         4},
 | 
						|
    {"spotname",     2},
 | 
						|
    {"spot",         2},
 | 
						|
    {"pattern",      1},
 | 
						|
    {"iccbasedgray", 1},
 | 
						|
    {"iccbasedrgb",  3},
 | 
						|
    {"iccbasedcmyk", 4},
 | 
						|
    {"lab",          3},
 | 
						|
    {NULL, 0}
 | 
						|
};
 | 
						|
 | 
						|
/* ------------------------ color state ----------------------- */
 | 
						|
 | 
						|
struct pdf_cstate_s
 | 
						|
{
 | 
						|
    pdf_color   fill;
 | 
						|
    pdf_color   stroke;
 | 
						|
};
 | 
						|
 | 
						|
void
 | 
						|
pdf_init_cstate(PDF *p)
 | 
						|
{
 | 
						|
    static const char fn[] = "pdf_init_cstate";
 | 
						|
    pdf_cstate *cstate;
 | 
						|
 | 
						|
    if (!p->curr_ppt->cstate)
 | 
						|
    {
 | 
						|
	p->curr_ppt->cstate = (pdf_cstate *) pdc_malloc(p->pdc,
 | 
						|
                                   PDF_MAX_SAVE_LEVEL * sizeof(pdf_cstate), fn);
 | 
						|
    }
 | 
						|
 | 
						|
    cstate = &p->curr_ppt->cstate[p->curr_ppt->sl];
 | 
						|
 | 
						|
    cstate->fill.cs             = DeviceGray;
 | 
						|
    cstate->fill.val.gray       = 0.0;
 | 
						|
 | 
						|
    cstate->stroke.cs           = DeviceGray;
 | 
						|
    cstate->stroke.val.gray     = 0.0;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
pdf_save_cstate(PDF *p)
 | 
						|
{
 | 
						|
    pdf_ppt *ppt = p->curr_ppt;
 | 
						|
    int sl = ppt->sl;
 | 
						|
 | 
						|
    memcpy(&ppt->cstate[sl + 1], &ppt->cstate[sl], sizeof(pdf_cstate));
 | 
						|
}
 | 
						|
 | 
						|
pdf_color *
 | 
						|
pdf_get_cstate(PDF *p, pdf_drawmode mode)
 | 
						|
{
 | 
						|
    if (mode == pdf_fill)
 | 
						|
        return &p->curr_ppt->cstate[p->curr_ppt->sl].fill;
 | 
						|
    else
 | 
						|
        return &p->curr_ppt->cstate[p->curr_ppt->sl].stroke;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
pdf_cleanup_page_cstate(PDF *p, pdf_ppt *ppt)
 | 
						|
{
 | 
						|
    if (ppt->cstate != NULL)
 | 
						|
        pdc_free(p->pdc, ppt->cstate);
 | 
						|
 | 
						|
    ppt->cstate = NULL;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* Avoid wrong error messages due to rounding artifacts.
 | 
						|
 * This doesn't do any harm since we truncate to 5 decimal places anyway
 | 
						|
 * when producing PDF output.
 | 
						|
 */
 | 
						|
#define EPSILON	((1.0 + PDF_SMALLREAL))
 | 
						|
 | 
						|
static void pdf_check_color_values(PDF *p, pdf_colorspacetype type,
 | 
						|
    pdc_scalar c1, pdc_scalar c2, pdc_scalar c3, pdc_scalar c4);
 | 
						|
 | 
						|
static int
 | 
						|
pdf_color_components(PDF *p, int slot)
 | 
						|
{
 | 
						|
    static const char *fn = "pdf_color_components";
 | 
						|
    pdf_colorspace *cs;
 | 
						|
    int components = 0;
 | 
						|
 | 
						|
    cs = &p->colorspaces[slot];
 | 
						|
 | 
						|
    switch (cs->type) {
 | 
						|
	case DeviceGray:
 | 
						|
	case Indexed:
 | 
						|
	components = 1;
 | 
						|
	break;
 | 
						|
 | 
						|
	case DeviceRGB:
 | 
						|
	components = 3;
 | 
						|
	break;
 | 
						|
 | 
						|
	case DeviceCMYK:
 | 
						|
	components = 4;
 | 
						|
	break;
 | 
						|
 | 
						|
	case PatternCS:
 | 
						|
	if (cs->val.pattern.base == pdc_undef)
 | 
						|
	    components = 0;	/* PaintType 1: colored pattern */
 | 
						|
	else
 | 
						|
	    components = pdf_color_components(p, cs->val.pattern.base);
 | 
						|
 | 
						|
	default:
 | 
						|
	    pdc_error(p->pdc, PDF_E_INT_BADCS, fn,
 | 
						|
		pdc_errprintf(p->pdc, "%d", slot),
 | 
						|
		pdc_errprintf(p->pdc, "%d", cs->type), 0);
 | 
						|
    }
 | 
						|
 | 
						|
    return components;
 | 
						|
} /* pdf_color_components */
 | 
						|
 | 
						|
static void
 | 
						|
pdf_write_color_values(PDF *p, pdf_color *color, pdf_drawmode drawmode)
 | 
						|
{
 | 
						|
    static const char *fn = "pdf_write_color_values";
 | 
						|
    pdf_colorspace *	cs = &p->colorspaces[color->cs];
 | 
						|
    int			cs_bias = p->curr_ppt->cs_bias;
 | 
						|
    int			pt_bias = p->curr_ppt->pt_bias;
 | 
						|
 | 
						|
    switch (cs->type)
 | 
						|
    {
 | 
						|
	case DeviceGray:
 | 
						|
	{
 | 
						|
	    pdc_printf(p->out, "%f", color->val.gray);
 | 
						|
 | 
						|
	    if (drawmode == pdf_fill)
 | 
						|
		pdc_puts(p->out, " g\n");
 | 
						|
	    else if (drawmode == pdf_stroke)
 | 
						|
		pdc_puts(p->out, " G\n");
 | 
						|
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
 | 
						|
	case DeviceRGB:
 | 
						|
	{
 | 
						|
	    pdc_printf(p->out, "%f %f %f",
 | 
						|
		    color->val.rgb.r, color->val.rgb.g, color->val.rgb.b);
 | 
						|
 | 
						|
	    if (drawmode == pdf_fill)
 | 
						|
		pdc_puts(p->out, " rg\n");
 | 
						|
	    else if (drawmode == pdf_stroke)
 | 
						|
		pdc_puts(p->out, " RG\n");
 | 
						|
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
 | 
						|
	case DeviceCMYK:
 | 
						|
	{
 | 
						|
	    pdc_printf(p->out, "%f %f %f %f",
 | 
						|
		    color->val.cmyk.c, color->val.cmyk.m,
 | 
						|
		    color->val.cmyk.y, color->val.cmyk.k);
 | 
						|
 | 
						|
	    if (drawmode == pdf_fill)
 | 
						|
		pdc_puts(p->out, " k\n");
 | 
						|
	    else if (drawmode == pdf_stroke)
 | 
						|
		pdc_puts(p->out, " K\n");
 | 
						|
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	case PatternCS:
 | 
						|
	{
 | 
						|
	    if (drawmode == pdf_fill)
 | 
						|
	    {
 | 
						|
		if (p->pattern[color->val.pattern].painttype == 1)
 | 
						|
		{
 | 
						|
		    pdc_puts(p->out, "/Pattern cs");
 | 
						|
		}
 | 
						|
		else if (p->pattern[color->val.pattern].painttype == 2)
 | 
						|
		{
 | 
						|
                    pdf_color *fillcolor = pdf_get_cstate(p, pdf_fill);
 | 
						|
 | 
						|
		    pdc_printf(p->out, "/C%d cs ", cs_bias + color->cs);
 | 
						|
                    pdf_write_color_values(p, fillcolor, pdf_none);
 | 
						|
		}
 | 
						|
 | 
						|
		pdc_printf(p->out, "/P%d scn\n", pt_bias + color->val.pattern);
 | 
						|
	    }
 | 
						|
	    else if (drawmode == pdf_stroke)
 | 
						|
	    {
 | 
						|
		if (p->pattern[color->val.pattern].painttype == 1)
 | 
						|
		{
 | 
						|
		    pdc_puts(p->out, "/Pattern CS");
 | 
						|
		}
 | 
						|
		else if (p->pattern[color->val.pattern].painttype == 2)
 | 
						|
		{
 | 
						|
                    pdf_color *strokecolor = pdf_get_cstate(p, pdf_stroke);
 | 
						|
 | 
						|
		    pdc_printf(p->out, "/C%d CS ", cs_bias + color->cs);
 | 
						|
                    pdf_write_color_values(p, strokecolor, pdf_none);
 | 
						|
		}
 | 
						|
 | 
						|
		pdc_printf(p->out, "/P%d SCN\n", pt_bias + color->val.pattern);
 | 
						|
	    }
 | 
						|
 | 
						|
	    p->pattern[color->val.pattern].used_on_current_page = pdc_true;
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	case Indexed: /* LATER */
 | 
						|
	default:
 | 
						|
	    pdc_error(p->pdc, PDF_E_INT_BADCS, fn,
 | 
						|
		pdc_errprintf(p->pdc, "%d", color->cs),
 | 
						|
		pdc_errprintf(p->pdc, "%d", cs->type), 0);
 | 
						|
    }
 | 
						|
} /* pdf_write_color_values */
 | 
						|
 | 
						|
static pdc_bool
 | 
						|
pdf_color_equal(PDF *p, pdf_color *c1, pdf_color *c2)
 | 
						|
{
 | 
						|
    pdf_colorspace *cs1;
 | 
						|
 | 
						|
    cs1 = &p->colorspaces[c1->cs];
 | 
						|
 | 
						|
    if (c1->cs != c2->cs)
 | 
						|
	return pdc_false;
 | 
						|
 | 
						|
    switch (cs1->type) {
 | 
						|
	case DeviceGray:
 | 
						|
	    return (c1->val.gray == c2->val.gray);
 | 
						|
	    break;
 | 
						|
 | 
						|
	case DeviceRGB:
 | 
						|
	    return (c1->val.rgb.r == c2->val.rgb.r &&
 | 
						|
		    c1->val.rgb.g == c2->val.rgb.g &&
 | 
						|
		    c1->val.rgb.b == c2->val.rgb.b);
 | 
						|
	    break;
 | 
						|
 | 
						|
	case DeviceCMYK:
 | 
						|
	    return (c1->val.cmyk.c == c2->val.cmyk.c &&
 | 
						|
		    c1->val.cmyk.m == c2->val.cmyk.m &&
 | 
						|
		    c1->val.cmyk.y == c2->val.cmyk.y &&
 | 
						|
		    c1->val.cmyk.k == c2->val.cmyk.k);
 | 
						|
	    break;
 | 
						|
 | 
						|
	case Indexed:
 | 
						|
	    return (c1->val.idx == c2->val.idx);
 | 
						|
	    break;
 | 
						|
 | 
						|
	case PatternCS:
 | 
						|
	    return (c1->val.pattern == c2->val.pattern);
 | 
						|
	    break;
 | 
						|
 | 
						|
 | 
						|
	default:
 | 
						|
	    break;
 | 
						|
    }
 | 
						|
 | 
						|
    return pdc_true;
 | 
						|
} /* pdf_color_equal */
 | 
						|
 | 
						|
static pdc_bool
 | 
						|
pdf_colorspace_equal(PDF *p, pdf_colorspace *cs1, pdf_colorspace *cs2)
 | 
						|
{
 | 
						|
    static const char *fn = "pdf_colorspace_equal";
 | 
						|
 | 
						|
    if (cs1->type != cs2->type)
 | 
						|
	return pdc_false;
 | 
						|
 | 
						|
    switch (cs1->type) {
 | 
						|
	case DeviceGray:
 | 
						|
	case DeviceRGB:
 | 
						|
	case DeviceCMYK:
 | 
						|
	return pdc_true;
 | 
						|
	break;
 | 
						|
 | 
						|
 | 
						|
	case Indexed:
 | 
						|
	return ((cs1->val.indexed.base == cs2->val.indexed.base) &&
 | 
						|
		(cs1->val.indexed.palette_size==cs2->val.indexed.palette_size)&&
 | 
						|
		(cs1->val.indexed.colormap_id != PDC_BAD_ID &&
 | 
						|
		 cs1->val.indexed.colormap_id == cs2->val.indexed.colormap_id));
 | 
						|
	break;
 | 
						|
 | 
						|
	case PatternCS:
 | 
						|
	return (cs1->val.pattern.base == cs2->val.pattern.base);
 | 
						|
	break;
 | 
						|
 | 
						|
 | 
						|
	default:
 | 
						|
	    pdc_error(p->pdc, PDF_E_INT_BADCS, fn, "(unknown)",
 | 
						|
		pdc_errprintf(p->pdc, "%d", cs1->type), 0);
 | 
						|
    }
 | 
						|
 | 
						|
    return pdc_false;
 | 
						|
} /* pdf_colorspace_equal */
 | 
						|
 | 
						|
static void
 | 
						|
pdf_grow_colorspaces(PDF *p)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
 | 
						|
    p->colorspaces = (pdf_colorspace *) pdc_realloc(p->pdc, p->colorspaces,
 | 
						|
	sizeof(pdf_colorspace) * 2 * p->colorspaces_capacity,
 | 
						|
	"pdf_grow_colorspaces");
 | 
						|
 | 
						|
    for (i = p->colorspaces_capacity; i < 2 * p->colorspaces_capacity; i++) {
 | 
						|
	p->colorspaces[i].used_on_current_page = pdc_false;
 | 
						|
    }
 | 
						|
 | 
						|
    p->colorspaces_capacity *= 2;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
pdf_add_colorspace(PDF *p, pdf_colorspace *cs, pdc_bool inuse)
 | 
						|
{
 | 
						|
    pdf_colorspace *cs_new;
 | 
						|
    static const char fn[] = "pdf_add_colorspace";
 | 
						|
    int slot;
 | 
						|
 | 
						|
    for (slot = 0; slot < p->colorspaces_number; slot++)
 | 
						|
    {
 | 
						|
	if (pdf_colorspace_equal(p, &p->colorspaces[slot], cs))
 | 
						|
	{
 | 
						|
	    if (inuse)
 | 
						|
		p->colorspaces[slot].used_on_current_page = pdc_true;
 | 
						|
	    return slot;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    slot = p->colorspaces_number;
 | 
						|
 | 
						|
    if (p->colorspaces_number >= p->colorspaces_capacity)
 | 
						|
	pdf_grow_colorspaces(p);
 | 
						|
 | 
						|
    cs_new = &p->colorspaces[slot];
 | 
						|
 | 
						|
    cs_new->type = cs->type;
 | 
						|
 | 
						|
    /* don't allocate id for simple color spaces, since we don't write these */
 | 
						|
    if (PDF_SIMPLE_COLORSPACE(cs)) {
 | 
						|
	cs_new->obj_id = PDC_BAD_ID;
 | 
						|
	cs_new->used_on_current_page = pdc_false;
 | 
						|
 | 
						|
    } else {
 | 
						|
	cs_new->obj_id = pdc_alloc_id(p->out);
 | 
						|
	cs_new->used_on_current_page = inuse;
 | 
						|
    }
 | 
						|
 | 
						|
    switch (cs_new->type) {
 | 
						|
	case DeviceGray:
 | 
						|
	case DeviceRGB:
 | 
						|
	case DeviceCMYK:
 | 
						|
	break;
 | 
						|
 | 
						|
 | 
						|
	case Indexed:
 | 
						|
	{
 | 
						|
	size_t palsize; 	/* palette size in bytes */
 | 
						|
 | 
						|
	palsize = cs->val.indexed.palette_size *
 | 
						|
			    pdf_color_components(p, cs->val.indexed.base);
 | 
						|
 | 
						|
        cs_new->val.indexed.base = cs->val.indexed.base;
 | 
						|
        cs_new->val.indexed.palette_size = cs->val.indexed.palette_size;
 | 
						|
        cs_new->val.indexed.colormap_id = pdc_alloc_id(p->out);
 | 
						|
        cs_new->val.indexed.colormap =
 | 
						|
	    (pdf_colormap *) pdc_malloc(p->pdc, palsize, fn);
 | 
						|
        memcpy(cs_new->val.indexed.colormap, cs->val.indexed.colormap, palsize);
 | 
						|
        cs_new->val.indexed.colormap_done = pdc_false;
 | 
						|
	break;
 | 
						|
 | 
						|
	case PatternCS:
 | 
						|
        cs_new->val.pattern.base = cs->val.pattern.base;
 | 
						|
	break;
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	default:
 | 
						|
	    pdc_error(p->pdc, PDF_E_INT_BADCS, fn,
 | 
						|
		pdc_errprintf(p->pdc, "%d", slot),
 | 
						|
		pdc_errprintf(p->pdc, "%d", cs_new->type), 0);
 | 
						|
    }
 | 
						|
 | 
						|
    p->colorspaces_number++;
 | 
						|
 | 
						|
    return slot;
 | 
						|
} /* pdf_add_colorspace */
 | 
						|
 | 
						|
 | 
						|
static void
 | 
						|
pdf_set_color_values(PDF *p, pdf_color *cfill, pdf_color *cstroke,
 | 
						|
                     pdf_drawmode drawmode)
 | 
						|
{
 | 
						|
    pdf_colorspace *cs;
 | 
						|
 | 
						|
    if (drawmode == pdf_stroke || drawmode == pdf_fillstroke)
 | 
						|
    {
 | 
						|
        pdf_color *strokecolor = pdf_get_cstate(p, pdf_stroke);
 | 
						|
 | 
						|
        if (!pdf_color_equal(p, strokecolor, cstroke) || PDF_FORCE_OUTPUT())
 | 
						|
        {
 | 
						|
            if (PDF_GET_STATE(p) != pdf_state_document)
 | 
						|
                pdf_write_color_values(p, cstroke, pdf_stroke);
 | 
						|
 | 
						|
            *strokecolor = *cstroke;
 | 
						|
        }
 | 
						|
 | 
						|
        cs = &p->colorspaces[cstroke->cs];
 | 
						|
        if (!PDF_SIMPLE_COLORSPACE(cs))
 | 
						|
            cs->used_on_current_page = pdc_true;
 | 
						|
    }
 | 
						|
 | 
						|
    if (drawmode == pdf_fill || drawmode == pdf_fillstroke)
 | 
						|
    {
 | 
						|
        pdf_color *fillcolor = pdf_get_cstate(p, pdf_fill);
 | 
						|
 | 
						|
        if (!pdf_color_equal(p, fillcolor, cfill) || PDF_FORCE_OUTPUT())
 | 
						|
        {
 | 
						|
            if (PDF_GET_STATE(p) != pdf_state_document)
 | 
						|
                pdf_write_color_values(p, cfill, pdf_fill);
 | 
						|
 | 
						|
            *fillcolor = *cfill;
 | 
						|
        }
 | 
						|
 | 
						|
        cs = &p->colorspaces[cfill->cs];
 | 
						|
        if (!PDF_SIMPLE_COLORSPACE(cs))
 | 
						|
            cs->used_on_current_page = pdc_true;
 | 
						|
    }
 | 
						|
 | 
						|
} /* pdf_set_color_values */
 | 
						|
 | 
						|
void
 | 
						|
pdf_init_colorspaces(PDF *p)
 | 
						|
{
 | 
						|
    int i, slot;
 | 
						|
    pdf_colorspace cs;
 | 
						|
 | 
						|
 | 
						|
    p->colorspaces_number = 0;
 | 
						|
    p->colorspaces_capacity = COLORSPACES_CHUNKSIZE;
 | 
						|
 | 
						|
    p->colorspaces = (pdf_colorspace *)
 | 
						|
	pdc_malloc(p->pdc, sizeof(pdf_colorspace) * p->colorspaces_capacity,
 | 
						|
	    "pdf_init_colorspaces");
 | 
						|
 | 
						|
    for (i = 0; i < p->colorspaces_capacity; i++) {
 | 
						|
	p->colorspaces[i].used_on_current_page = pdc_false;
 | 
						|
    }
 | 
						|
 | 
						|
    /*
 | 
						|
     * Initialize a few slots with simple color spaces for easier use.
 | 
						|
     * These can be used without further ado: the slot number is identical
 | 
						|
     * to the enum value due to the ordering below.
 | 
						|
     */
 | 
						|
 | 
						|
    cs.type = DeviceGray;
 | 
						|
    slot = pdf_add_colorspace(p, &cs, pdc_false);
 | 
						|
    cs.type = DeviceRGB;
 | 
						|
    slot = pdf_add_colorspace(p, &cs, pdc_false);
 | 
						|
    cs.type = DeviceCMYK;
 | 
						|
    slot = pdf_add_colorspace(p, &cs, pdc_false);
 | 
						|
 | 
						|
} /* pdf_init_colorspaces */
 | 
						|
 | 
						|
void
 | 
						|
pdf_write_page_colorspaces(PDF *p)
 | 
						|
{
 | 
						|
    int i, total = 0;
 | 
						|
    int bias = p->curr_ppt->cs_bias;
 | 
						|
 | 
						|
    for (i = 0; i < p->colorspaces_number; i++)
 | 
						|
	if (p->colorspaces[i].used_on_current_page)
 | 
						|
	    total++;
 | 
						|
 | 
						|
    if (total > 0 || bias
 | 
						|
       )
 | 
						|
    {
 | 
						|
	pdc_puts(p->out, "/ColorSpace");
 | 
						|
	pdc_begin_dict(p->out);
 | 
						|
 | 
						|
	if (total > 0)
 | 
						|
	{
 | 
						|
	    for (i = 0; i < p->colorspaces_number; i++)
 | 
						|
	    {
 | 
						|
		pdf_colorspace *cs = &p->colorspaces[i];
 | 
						|
 | 
						|
		if (cs->used_on_current_page)
 | 
						|
		{
 | 
						|
		    cs->used_on_current_page = pdc_false; /* reset */
 | 
						|
 | 
						|
		    /* don't write simple color spaces as resource */
 | 
						|
		    if (!PDF_SIMPLE_COLORSPACE(cs))
 | 
						|
		    {
 | 
						|
			pdc_printf(p->out, "/C%d", bias + i);
 | 
						|
			pdc_objref(p->out, "", cs->obj_id);
 | 
						|
		    }
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	if (!bias)
 | 
						|
	    pdc_end_dict(p->out);		/* color space names */
 | 
						|
    }
 | 
						|
} /* pdf_write_page_colorspaces */
 | 
						|
 | 
						|
void
 | 
						|
pdf_get_page_colorspaces(PDF *p, pdf_reslist *rl)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
 | 
						|
    for (i = 0; i < p->colorspaces_number; i++)
 | 
						|
    {
 | 
						|
	pdf_colorspace *cs = &p->colorspaces[i];
 | 
						|
 | 
						|
	if (cs->used_on_current_page)
 | 
						|
	{
 | 
						|
	    cs->used_on_current_page = pdc_false;
 | 
						|
 | 
						|
	    if (!PDF_SIMPLE_COLORSPACE(cs))
 | 
						|
		pdf_add_reslist(p, rl, i);
 | 
						|
	}
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
pdf_mark_page_colorspace(PDF *p, int n)
 | 
						|
{
 | 
						|
    p->colorspaces[n].used_on_current_page = pdc_true;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
pdf_write_function_dict(PDF *p, pdf_color *c0, pdf_color *c1, pdc_scalar N)
 | 
						|
{
 | 
						|
    static const char *fn = "pdf_write_function_dict";
 | 
						|
 | 
						|
    pdf_colorspace *cs;
 | 
						|
 | 
						|
    cs = &p->colorspaces[c1->cs];
 | 
						|
 | 
						|
    pdc_begin_dict(p->out);			/* function dict */
 | 
						|
 | 
						|
    pdc_puts(p->out, "/FunctionType 2\n");
 | 
						|
    pdc_puts(p->out, "/Domain[0 1]\n");
 | 
						|
    pdc_printf(p->out, "/N %f\n", N);
 | 
						|
 | 
						|
    switch (cs->type) {
 | 
						|
 | 
						|
	case DeviceGray:
 | 
						|
	pdc_puts(p->out, "/Range[0 1]\n");
 | 
						|
	if (c0->val.gray != 0) pdc_printf(p->out, "/C0[%f]\n", c0->val.gray);
 | 
						|
	if (c1->val.gray != 1) pdc_printf(p->out, "/C1[%f]", c1->val.gray);
 | 
						|
	break;
 | 
						|
 | 
						|
	case DeviceRGB:
 | 
						|
	pdc_puts(p->out, "/Range[0 1 0 1 0 1]\n");
 | 
						|
	pdc_printf(p->out, "/C0[%f %f %f]\n",
 | 
						|
		c0->val.rgb.r, c0->val.rgb.g, c0->val.rgb.b);
 | 
						|
	pdc_printf(p->out, "/C1[%f %f %f]",
 | 
						|
		c1->val.rgb.r, c1->val.rgb.g, c1->val.rgb.b);
 | 
						|
	break;
 | 
						|
 | 
						|
	case DeviceCMYK:
 | 
						|
	pdc_puts(p->out, "/Range[0 1 0 1 0 1 0 1]\n");
 | 
						|
	pdc_printf(p->out, "/C0[%f %f %f %f]\n",
 | 
						|
		c0->val.cmyk.c, c0->val.cmyk.m, c0->val.cmyk.y, c0->val.cmyk.k);
 | 
						|
	pdc_printf(p->out, "/C1[%f %f %f %f]",
 | 
						|
		c1->val.cmyk.c, c1->val.cmyk.m, c1->val.cmyk.y, c1->val.cmyk.k);
 | 
						|
	break;
 | 
						|
 | 
						|
 | 
						|
	default:
 | 
						|
	pdc_error(p->pdc, PDF_E_INT_BADCS, fn, "(unknown)",
 | 
						|
	    pdc_errprintf(p->pdc, "%d", cs->type), 0);
 | 
						|
    }
 | 
						|
 | 
						|
    pdc_end_dict_c(p->out);		/* function dict */
 | 
						|
} /* pdf_write_function_dict */
 | 
						|
 | 
						|
void
 | 
						|
pdf_write_colormap(PDF *p, int slot)
 | 
						|
{
 | 
						|
    PDF_data_source src;
 | 
						|
    pdf_colorspace *cs, *base;
 | 
						|
    pdc_id length_id;
 | 
						|
 | 
						|
    cs   = &p->colorspaces[slot];
 | 
						|
 | 
						|
    if (cs->type != Indexed || cs->val.indexed.colormap_done == pdc_true)
 | 
						|
	return;
 | 
						|
 | 
						|
    base = &p->colorspaces[cs->val.indexed.base];
 | 
						|
 | 
						|
    pdc_begin_obj(p->out, cs->val.indexed.colormap_id);	/* colormap object */
 | 
						|
    pdc_begin_dict(p->out);
 | 
						|
 | 
						|
    if (pdc_get_compresslevel(p->out))
 | 
						|
	pdc_puts(p->out, "/Filter/FlateDecode\n");
 | 
						|
 | 
						|
    /* Length of colormap object */
 | 
						|
    length_id = pdc_alloc_id(p->out);
 | 
						|
    pdc_objref(p->out, "/Length", length_id);
 | 
						|
    pdc_end_dict(p->out);
 | 
						|
 | 
						|
    src.init		= NULL;
 | 
						|
    src.fill		= pdf_data_source_buf_fill;
 | 
						|
    src.terminate	= NULL;
 | 
						|
 | 
						|
    src.buffer_start	= (unsigned char *) cs->val.indexed.colormap;
 | 
						|
 | 
						|
    src.buffer_length = (size_t) (cs->val.indexed.palette_size *
 | 
						|
				pdf_color_components(p, cs->val.indexed.base));
 | 
						|
 | 
						|
    src.bytes_available = 0;
 | 
						|
    src.next_byte	= NULL;
 | 
						|
 | 
						|
    /* Write colormap data */
 | 
						|
    pdf_copy_stream(p, &src, pdc_true);	/* colormap data */
 | 
						|
 | 
						|
    pdc_end_obj(p->out);				/* colormap object */
 | 
						|
 | 
						|
    pdc_put_pdfstreamlength(p->out, length_id);
 | 
						|
 | 
						|
    /* free the colormap now that it's written */
 | 
						|
    pdc_free(p->pdc, cs->val.indexed.colormap);
 | 
						|
    cs->val.indexed.colormap = NULL;
 | 
						|
    cs->val.indexed.colormap_done = pdc_true;
 | 
						|
} /* pdf_write_colormap */
 | 
						|
 | 
						|
void
 | 
						|
pdf_write_colorspace(PDF *p, int slot, pdc_bool direct)
 | 
						|
{
 | 
						|
    static const char *fn = "pdf_write_colorspace";
 | 
						|
 | 
						|
    pdf_colorspace *cs;
 | 
						|
    int base;
 | 
						|
 | 
						|
    if (slot < 0 || slot >= p->colorspaces_number)
 | 
						|
	pdc_error(p->pdc, PDF_E_INT_BADCS, fn,
 | 
						|
            pdc_errprintf(p->pdc, "%d", slot),
 | 
						|
            "(unknown)", 0);
 | 
						|
 | 
						|
    cs = &p->colorspaces[slot];
 | 
						|
 | 
						|
    /* we always write simple colorspaces directly */
 | 
						|
    if (PDF_SIMPLE_COLORSPACE(cs))
 | 
						|
	direct = pdc_true;
 | 
						|
 | 
						|
    if (!direct) {
 | 
						|
	pdc_objref_c(p->out, cs->obj_id);
 | 
						|
	return;
 | 
						|
    }
 | 
						|
 | 
						|
    switch (cs->type) {
 | 
						|
	case DeviceGray:
 | 
						|
	pdc_printf(p->out, "/DeviceGray");
 | 
						|
	break;
 | 
						|
 | 
						|
	case DeviceRGB:
 | 
						|
	pdc_printf(p->out, "/DeviceRGB");
 | 
						|
	break;
 | 
						|
 | 
						|
	case DeviceCMYK:
 | 
						|
	pdc_printf(p->out, "/DeviceCMYK");
 | 
						|
	break;
 | 
						|
 | 
						|
 | 
						|
	case Indexed:
 | 
						|
	base = cs->val.indexed.base;
 | 
						|
 | 
						|
	pdc_begin_array(p->out);
 | 
						|
	pdc_puts(p->out, "/Indexed");
 | 
						|
 | 
						|
	pdf_write_colorspace(p, base, pdc_false);
 | 
						|
 | 
						|
	pdc_printf(p->out, " %d", cs->val.indexed.palette_size - 1);
 | 
						|
	pdc_objref_c(p->out, cs->val.indexed.colormap_id);
 | 
						|
	pdc_end_array_c(p->out);
 | 
						|
	break;
 | 
						|
 | 
						|
	case PatternCS:
 | 
						|
	pdc_begin_array(p->out);
 | 
						|
	pdc_printf(p->out, "/Pattern");
 | 
						|
	pdf_write_colorspace(p, cs->val.pattern.base, pdc_false);
 | 
						|
	pdc_end_array(p->out);
 | 
						|
	break;
 | 
						|
 | 
						|
	default:
 | 
						|
	pdc_error(p->pdc, PDF_E_INT_BADCS, fn,
 | 
						|
	    pdc_errprintf(p->pdc, "%d", slot),
 | 
						|
	    pdc_errprintf(p->pdc, "%d", cs->type), 0);
 | 
						|
    }
 | 
						|
} /* pdf_write_colorspace */
 | 
						|
 | 
						|
void
 | 
						|
pdf_write_doc_colorspaces(PDF *p)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
 | 
						|
    for (i = 0; i < p->colorspaces_number; i++) {
 | 
						|
	pdf_colorspace *cs = &p->colorspaces[i];
 | 
						|
 | 
						|
	/* don't write simple color spaces as resource */
 | 
						|
	if (PDF_SIMPLE_COLORSPACE(cs))
 | 
						|
	    continue;
 | 
						|
 | 
						|
	pdc_begin_obj(p->out, cs->obj_id);
 | 
						|
	pdf_write_colorspace(p, i, pdc_true);
 | 
						|
	pdc_puts(p->out, "\n");
 | 
						|
	pdc_end_obj(p->out);			/* color space resource */
 | 
						|
 | 
						|
	pdf_write_colormap(p, i);		/* write pending colormaps */
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
pdf_cleanup_colorspaces(PDF *p)
 | 
						|
{
 | 
						|
    static const char *fn = "pdf_cleanup_colorspaces";
 | 
						|
 | 
						|
    int i;
 | 
						|
 | 
						|
    if (!p->colorspaces)
 | 
						|
	return;
 | 
						|
 | 
						|
    for (i = 0; i < p->colorspaces_number; i++) {
 | 
						|
	pdf_colorspace *cs = &p->colorspaces[i];;
 | 
						|
 | 
						|
	switch (cs->type) {
 | 
						|
	    case DeviceGray:
 | 
						|
	    case DeviceRGB:
 | 
						|
	    case DeviceCMYK:
 | 
						|
	    case PatternCS:
 | 
						|
	    break;
 | 
						|
 | 
						|
	    case Indexed:
 | 
						|
	    if (cs->val.indexed.colormap)
 | 
						|
		pdc_free(p->pdc, cs->val.indexed.colormap);
 | 
						|
	    break;
 | 
						|
 | 
						|
 | 
						|
	    default:
 | 
						|
		pdc_error(p->pdc, PDF_E_INT_BADCS, fn,
 | 
						|
		    pdc_errprintf(p->pdc, "%d", i),
 | 
						|
		    pdc_errprintf(p->pdc, "%d", cs->type), 0);
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    pdc_free(p->pdc, p->colorspaces);
 | 
						|
    p->colorspaces = NULL;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
static void
 | 
						|
pdf_check_color_values(
 | 
						|
    PDF *p,
 | 
						|
    pdf_colorspacetype type,
 | 
						|
    pdc_scalar c1, pdc_scalar c2, pdc_scalar c3, pdc_scalar c4)
 | 
						|
{
 | 
						|
    switch (type) {
 | 
						|
        case DeviceGray:
 | 
						|
        pdc_check_number_limits(p->pdc, "c1", c1, 0.0, EPSILON);
 | 
						|
        break;
 | 
						|
 | 
						|
        case DeviceRGB:
 | 
						|
        pdc_check_number_limits(p->pdc, "c1", c1, 0.0, EPSILON);
 | 
						|
        pdc_check_number_limits(p->pdc, "c2", c2, 0.0, EPSILON);
 | 
						|
        pdc_check_number_limits(p->pdc, "c3", c3, 0.0, EPSILON);
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
        case DeviceCMYK:
 | 
						|
        pdc_check_number_limits(p->pdc, "c1", c1, 0.0, EPSILON);
 | 
						|
        pdc_check_number_limits(p->pdc, "c2", c2, 0.0, EPSILON);
 | 
						|
        pdc_check_number_limits(p->pdc, "c3", c3, 0.0, EPSILON);
 | 
						|
        pdc_check_number_limits(p->pdc, "c4", c4, 0.0, EPSILON);
 | 
						|
        break;
 | 
						|
 | 
						|
 | 
						|
 | 
						|
	case PatternCS:
 | 
						|
        pdf_check_handle(p, (int) c1, pdc_patternhandle);
 | 
						|
        if (c1 == p->pattern_number - 1 && PDF_GET_STATE(p) & pdf_state_pattern)
 | 
						|
        {
 | 
						|
            pdc_error(p->pdc, PDF_E_PATTERN_SELF, 0, 0, 0, 0);
 | 
						|
        }
 | 
						|
	break;
 | 
						|
 | 
						|
	case Separation:
 | 
						|
        pdf_check_handle(p, (int) c1, pdc_colorhandle);
 | 
						|
        pdc_check_number_limits(p->pdc, "c2", c2, 0.0, EPSILON);
 | 
						|
	break;
 | 
						|
 | 
						|
	case Indexed:
 | 
						|
	default:
 | 
						|
	    break;
 | 
						|
    }
 | 
						|
} /* pdf_check_color_values */
 | 
						|
 | 
						|
static void
 | 
						|
pdf_setcolor_internal(PDF *p, int drawmode, int colortype,
 | 
						|
    pdc_scalar c1, pdc_scalar c2, pdc_scalar c3, pdc_scalar c4,
 | 
						|
    pdf_color *fcolor)
 | 
						|
{
 | 
						|
    pdf_color c, cstroke;
 | 
						|
    pdf_colorspace cs;
 | 
						|
 | 
						|
    if (PDF_GET_STATE(p) == pdf_state_pattern &&
 | 
						|
        pdf_get_shading_painttype(p) == 2)
 | 
						|
    {
 | 
						|
        pdc_error(p->pdc, PDF_E_COLOR_INVALSPEC, 0, 0, 0, 0);
 | 
						|
    }
 | 
						|
 | 
						|
    /* TODO: synchronize the PDF/X checks below with pdf_check_pdfx_colorspaces
 | 
						|
    */
 | 
						|
    switch (colortype)
 | 
						|
    {
 | 
						|
        case color_gray:
 | 
						|
        cs.type = DeviceGray;
 | 
						|
	c.cs = cs.type;
 | 
						|
	c.val.gray = c1;
 | 
						|
	pdf_check_color_values(p, cs.type, c1, c2, c3, c4);
 | 
						|
        break;
 | 
						|
 | 
						|
        case color_rgb:
 | 
						|
        cs.type = DeviceRGB;
 | 
						|
	c.cs = cs.type;
 | 
						|
	c.val.rgb.r = c1;
 | 
						|
	c.val.rgb.g = c2;
 | 
						|
	c.val.rgb.b = c3;
 | 
						|
	pdf_check_color_values(p, cs.type, c1, c2, c3, c4);
 | 
						|
        break;
 | 
						|
 | 
						|
        case color_cmyk:
 | 
						|
        cs.type = DeviceCMYK;
 | 
						|
	c.cs = cs.type;
 | 
						|
	c.val.cmyk.c = c1;
 | 
						|
	c.val.cmyk.m = c2;
 | 
						|
	c.val.cmyk.y = c3;
 | 
						|
	c.val.cmyk.k = c4;
 | 
						|
	pdf_check_color_values(p, cs.type, c1, c2, c3, c4);
 | 
						|
        break;
 | 
						|
 | 
						|
        case color_spotname:
 | 
						|
        case color_spot:
 | 
						|
        pdc_error(p->pdc, PDF_E_UNSUPP_SPOTCOLOR, 0, 0, 0, 0);
 | 
						|
        break;
 | 
						|
 | 
						|
        case color_pattern:
 | 
						|
        cs.type = PatternCS;
 | 
						|
        if (p->pdc->hastobepos) c1 -= 1;
 | 
						|
        c.val.pattern = (int) c1;
 | 
						|
        pdf_check_color_values(p, cs.type, c1, c2, c3, c4);
 | 
						|
 | 
						|
        if (p->pattern[c.val.pattern].painttype == 1)
 | 
						|
        {
 | 
						|
	    cs.val.pattern.base = pdc_undef;
 | 
						|
	    c.cs = pdf_add_colorspace(p, &cs, pdc_false);
 | 
						|
            cstroke = c;
 | 
						|
	}
 | 
						|
        else if (p->pattern[c.val.pattern].painttype == 2)
 | 
						|
        {
 | 
						|
            if (drawmode == pdf_stroke || drawmode == pdf_fillstroke)
 | 
						|
            {
 | 
						|
                pdf_color *strokecolor = pdf_get_cstate(p, pdf_stroke);
 | 
						|
 | 
						|
                if (p->colorspaces[strokecolor->cs].type == PatternCS)
 | 
						|
                    pdc_error(p->pdc, PDF_E_COLOR_INVALPATT, 0, 0, 0, 0);
 | 
						|
 | 
						|
                cstroke.val.pattern = (int) c1;
 | 
						|
                cs.val.pattern.base = strokecolor->cs;
 | 
						|
                cstroke.cs = pdf_add_colorspace(p, &cs, pdc_true);
 | 
						|
            }
 | 
						|
 | 
						|
            if (drawmode == pdf_fill || drawmode == pdf_fillstroke)
 | 
						|
            {
 | 
						|
                pdf_color *fillcolor = pdf_get_cstate(p, pdf_fill);
 | 
						|
 | 
						|
                if (p->colorspaces[fillcolor->cs].type == PatternCS)
 | 
						|
                    pdc_error(p->pdc, PDF_E_COLOR_INVALPATT, 0, 0, 0, 0);
 | 
						|
 | 
						|
                cs.val.pattern.base = fillcolor->cs;
 | 
						|
                c.cs = pdf_add_colorspace(p, &cs, pdc_true);
 | 
						|
            }
 | 
						|
	}
 | 
						|
        break;
 | 
						|
 | 
						|
        case color_iccbasedgray:
 | 
						|
        case color_iccbasedrgb:
 | 
						|
        case color_iccbasedcmyk:
 | 
						|
        case color_lab:
 | 
						|
        pdc_error(p->pdc, PDF_E_UNSUPP_ICCBASEDCOLOR, 0, 0, 0, 0);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
 | 
						|
    if (fcolor == NULL)
 | 
						|
    {
 | 
						|
        if (colortype != color_pattern)
 | 
						|
            cstroke = c;
 | 
						|
        pdf_set_color_values(p, &c, &cstroke, (pdf_drawmode) drawmode);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        *fcolor = c;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static const pdc_keyconn pdf_fstype_keylist[] =
 | 
						|
{
 | 
						|
    {"stroke",     pdf_stroke},
 | 
						|
    {"fill",       pdf_fill},
 | 
						|
    {"fillstroke", pdf_stroke | pdf_fill},
 | 
						|
    {"both",       pdf_stroke | pdf_fill},
 | 
						|
    {NULL, 0}
 | 
						|
};
 | 
						|
 | 
						|
void
 | 
						|
pdf__setcolor(
 | 
						|
    PDF *p,
 | 
						|
    const char *fstype,
 | 
						|
    const char *colorspace,
 | 
						|
    pdc_scalar c1, pdc_scalar c2, pdc_scalar c3, pdc_scalar c4)
 | 
						|
{
 | 
						|
    int drawmode = (int) pdf_none;
 | 
						|
    int colortype;
 | 
						|
 | 
						|
    if (!fstype || !*fstype)
 | 
						|
        pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "fstype", 0, 0, 0);
 | 
						|
 | 
						|
    if (!colorspace || !*colorspace)
 | 
						|
        pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "colorspace", 0, 0, 0);
 | 
						|
 | 
						|
    drawmode = pdc_get_keycode_ci(fstype, pdf_fstype_keylist);
 | 
						|
    if (drawmode == PDC_KEY_NOTFOUND)
 | 
						|
        pdc_error(p->pdc, PDC_E_ILLARG_STRING, "fstype", fstype, 0, 0);
 | 
						|
 | 
						|
    colortype = pdc_get_keycode_ci(colorspace, pdf_colortype_keylist);
 | 
						|
    if (colortype == PDC_KEY_NOTFOUND)
 | 
						|
        pdc_error(p->pdc, PDC_E_ILLARG_STRING, "colorspace", colorspace, 0, 0);
 | 
						|
 | 
						|
    pdf_setcolor_internal(p, drawmode, colortype, c1, c2, c3, c4, NULL);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
pdf_set_default_color(PDF *p, pdc_bool reset)
 | 
						|
{
 | 
						|
 | 
						|
 | 
						|
 | 
						|
    if (reset)
 | 
						|
        pdf__setcolor(p, "fillstroke", "gray", 0, 0, 0, 0);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void
 | 
						|
pdf_parse_coloropt(PDF *p, const char *optname, char **optvalue, int ns,
 | 
						|
                   int maxtype, pdf_coloropt *c)
 | 
						|
{
 | 
						|
    int errcode = 0;
 | 
						|
    const char *stemp = NULL;
 | 
						|
 | 
						|
    if (ns)
 | 
						|
    {
 | 
						|
        int i, j, n, iz = 0;
 | 
						|
        double dz;
 | 
						|
 | 
						|
        c->type = pdc_get_keycode_ci(optvalue[0], pdf_colortype_keylist);
 | 
						|
        if (c->type == PDC_KEY_NOTFOUND || c->type > maxtype)
 | 
						|
        {
 | 
						|
            stemp = pdc_errprintf(p->pdc,
 | 
						|
                        "%.*s", PDC_ERR_MAXSTRLEN, optvalue[0]);
 | 
						|
            errcode = PDC_E_OPT_ILLKEYWORD;
 | 
						|
            goto PDF_COLOPT_ERROR;
 | 
						|
        }
 | 
						|
 | 
						|
        if (c->type == (int) color_spotname || c->type == (int) color_spot)
 | 
						|
        {
 | 
						|
            errcode = PDF_E_UNSUPP_SPOTCOLOR;
 | 
						|
            goto PDF_COLOPT_ERROR;
 | 
						|
        }
 | 
						|
 | 
						|
        n = 1 + pdc_get_keycode_ci(optvalue[0], pdf_colorcomp_keylist);
 | 
						|
        if (n != ns)
 | 
						|
        {
 | 
						|
            if (c->type == (int) color_spotname)
 | 
						|
                n++;
 | 
						|
            if (n != ns)
 | 
						|
            {
 | 
						|
                stemp = pdc_errprintf(p->pdc, "%d", n);
 | 
						|
                errcode = n < ns ? PDC_E_OPT_TOOMANYVALUES :
 | 
						|
                                   PDC_E_OPT_TOOFEWVALUES;
 | 
						|
                goto PDF_COLOPT_ERROR;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        for (i = 0; i < 4; i++)
 | 
						|
        {
 | 
						|
            j = i + 1;
 | 
						|
            if (i >= ns - 1)
 | 
						|
            {
 | 
						|
                if (!i || c->type != (int) color_gray)
 | 
						|
                    c->value[i] = 0.0;
 | 
						|
                else
 | 
						|
                    c->value[i] = c->value[0];
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                if (!i && (c->type >= (int) color_spotname &&
 | 
						|
                           c->type <= (int) color_pattern))
 | 
						|
                {
 | 
						|
                    c->name[0] =0;
 | 
						|
                    if (pdc_str2integer(optvalue[j], 0, (pdc_sint32 *) &iz) ==
 | 
						|
                        pdc_false)
 | 
						|
                    {
 | 
						|
                        {
 | 
						|
                            stemp = pdc_errprintf(p->pdc, "%.*s",
 | 
						|
                                               PDC_ERR_MAXSTRLEN, optvalue[j]);
 | 
						|
                            errcode = PDC_E_OPT_ILLNUMBER;
 | 
						|
                            goto PDF_COLOPT_ERROR;
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                    c->value[i] = iz;
 | 
						|
                }
 | 
						|
                else
 | 
						|
                {
 | 
						|
                    if (pdc_str2double(optvalue[j], &dz) == pdc_false)
 | 
						|
                    {
 | 
						|
                        stemp = pdc_errprintf(p->pdc, "%.*s",
 | 
						|
                                              PDC_ERR_MAXSTRLEN, optvalue[j]);
 | 
						|
                        errcode = PDC_E_OPT_ILLNUMBER;
 | 
						|
                        goto PDF_COLOPT_ERROR;
 | 
						|
                    }
 | 
						|
                    else
 | 
						|
                        c->value[i] = dz;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        if (c->type <= (int) color_cmyk)
 | 
						|
        {
 | 
						|
            for (i = 0; i < ns - 1; i++)
 | 
						|
            {
 | 
						|
                if (c->value[i] < 0 || c->value[i] > EPSILON)
 | 
						|
                {
 | 
						|
                    stemp = pdc_errprintf(p->pdc, "%f", c->value[i]);
 | 
						|
                    errcode = PDC_E_OPT_ILLNUMBER;
 | 
						|
                    goto PDF_COLOPT_ERROR;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    PDF_COLOPT_ERROR:
 | 
						|
 | 
						|
    if (errcode)
 | 
						|
        pdc_error(p->pdc, errcode, optname, stemp, 0, 0);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void
 | 
						|
pdf_set_coloropt(PDF *p, int drawmode, pdf_coloropt *c)
 | 
						|
{
 | 
						|
    if (c->type == (int) color_none)
 | 
						|
        return;
 | 
						|
    if (c->type == (int) color_spotname)
 | 
						|
    {
 | 
						|
        pdc_error(p->pdc, PDF_E_UNSUPP_SPOTCOLOR, 0, 0, 0, 0);
 | 
						|
    }
 | 
						|
 | 
						|
    pdf_setcolor_internal(p, drawmode, c->type,
 | 
						|
                          c->value[0], c->value[1], c->value[2], c->value[3],
 | 
						|
                          NULL);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
pdf_init_coloropt(PDF *p, pdf_coloropt *c)
 | 
						|
{
 | 
						|
    (void) p;
 | 
						|
 | 
						|
    {
 | 
						|
	c->name[0] = 0;
 | 
						|
	c->type = (int) color_gray;
 | 
						|
	c->value[0] = 0;
 | 
						|
	c->value[1] = 0;
 | 
						|
	c->value[2] = 0;
 | 
						|
	c->value[3] = 0;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
pdf_logg_coloropt(PDF *p, pdf_coloropt *c, pdc_bool newline)
 | 
						|
{
 | 
						|
    const char *keyword =
 | 
						|
    pdc_get_keyword((int) c->type, pdf_colortype_keylist);
 | 
						|
 | 
						|
    pdc_logg(p->pdc, "{%s ", keyword);
 | 
						|
 | 
						|
    switch (c->type)
 | 
						|
    {
 | 
						|
        case color_gray:
 | 
						|
        case color_iccbasedgray:
 | 
						|
        case color_pattern:
 | 
						|
        case color_spot:
 | 
						|
        pdc_logg(p->pdc, "%g}", c->value[0]);
 | 
						|
        break;
 | 
						|
 | 
						|
        case color_rgb:
 | 
						|
        case color_iccbasedrgb:
 | 
						|
        case color_lab:
 | 
						|
        pdc_logg(p->pdc, "%g %g %g}", c->value[0], c->value[1], c->value[2]);
 | 
						|
        break;
 | 
						|
 | 
						|
        case color_cmyk:
 | 
						|
        case color_iccbasedcmyk:
 | 
						|
        pdc_logg(p->pdc, "%g %g %g %g}", c->value[0], c->value[1],
 | 
						|
                                     c->value[2], c->value[3]);
 | 
						|
        break;
 | 
						|
 | 
						|
        case color_spotname:
 | 
						|
        pdc_logg(p->pdc, "{%s} %g}", c->name, c->value[0]);
 | 
						|
        break;
 | 
						|
 | 
						|
        default:
 | 
						|
        pdc_logg(p->pdc, "}");
 | 
						|
        break;
 | 
						|
    }
 | 
						|
 | 
						|
    if (newline)
 | 
						|
        pdc_logg(p->pdc, "\n");
 | 
						|
}
 |