Files correlati : Ricompilazione Demo : [ ] Commento : Riportata la versione 3.1 patch 650 git-svn-id: svn://10.65.10.50/trunk@14148 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			998 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			998 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
/*---------------------------------------------------------------------------*
 | 
						|
 |              PDFlib - A library for generating PDF on the fly             |
 | 
						|
 +---------------------------------------------------------------------------+
 | 
						|
 | Copyright (c) 1997-2005 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.2 2006-07-11 13:10:33 alex Exp $
 | 
						|
 *
 | 
						|
 * PDFlib color routines
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
#define P_COLOR_C
 | 
						|
 | 
						|
#include "p_intern.h"
 | 
						|
#include "p_color.h"
 | 
						|
/*#include "p_font.h"*/
 | 
						|
 | 
						|
 | 
						|
/* ------------------------ 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)
 | 
						|
{
 | 
						|
    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,
 | 
						|
		pdc_errprintf(p->pdc, "%d", cs->type), 0, 0, 0);
 | 
						|
    }
 | 
						|
 | 
						|
    return components;
 | 
						|
} /* pdf_color_components */
 | 
						|
 | 
						|
static void
 | 
						|
pdf_write_color_values(PDF *p, pdf_color *color, pdf_drawmode drawmode)
 | 
						|
{
 | 
						|
    pdf_colorspace *cs = &p->colorspaces[color->cs];
 | 
						|
 | 
						|
    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) {
 | 
						|
		    pdc_printf(p->out, "/C%d cs ", color->cs);
 | 
						|
		    pdf_write_color_values(p,
 | 
						|
			&p->curr_ppt->cstate[p->curr_ppt->sl].fill, pdf_none);
 | 
						|
		}
 | 
						|
		pdc_printf(p->out, "/P%d scn\n", 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) {
 | 
						|
		    pdc_printf(p->out, "/C%d CS ", color->cs);
 | 
						|
		    pdf_write_color_values(p,
 | 
						|
			&p->curr_ppt->cstate[p->curr_ppt->sl].stroke, pdf_none);
 | 
						|
		}
 | 
						|
		pdc_printf(p->out, "/P%d SCN\n", 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,
 | 
						|
		pdc_errprintf(p->pdc, "%d",
 | 
						|
		    p->colorspaces[color->cs].type), 0, 0, 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)
 | 
						|
{
 | 
						|
    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,
 | 
						|
		pdc_errprintf(p->pdc, "%d", cs1->type), 0, 0, 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,
 | 
						|
                pdc_errprintf(p->pdc, "%d", cs_new->type), 0, 0, 0);
 | 
						|
    }
 | 
						|
 | 
						|
    p->colorspaces_number++;
 | 
						|
 | 
						|
    return slot;
 | 
						|
} /* pdf_add_colorspace */
 | 
						|
 | 
						|
 | 
						|
static void
 | 
						|
pdf_set_color_values(PDF *p, pdf_color *c, pdf_drawmode drawmode)
 | 
						|
{
 | 
						|
    pdf_color *current;
 | 
						|
    pdf_colorspace *cs;
 | 
						|
 | 
						|
    cs = &p->colorspaces[c->cs];
 | 
						|
 | 
						|
    if (drawmode == pdf_stroke || drawmode == pdf_fillstroke) {
 | 
						|
	current = &p->curr_ppt->cstate[p->curr_ppt->sl].stroke;
 | 
						|
 | 
						|
	if (!pdf_color_equal(p, current, c) || PDF_FORCE_OUTPUT())
 | 
						|
	{
 | 
						|
	    if (PDF_GET_STATE(p) != pdf_state_document)
 | 
						|
		pdf_write_color_values(p, c, pdf_stroke);
 | 
						|
 | 
						|
	    *current = *c;
 | 
						|
	}
 | 
						|
    }
 | 
						|
    if (drawmode == pdf_fill || drawmode == pdf_fillstroke) {
 | 
						|
	current = &p->curr_ppt->cstate[p->curr_ppt->sl].fill;
 | 
						|
 | 
						|
	if (!pdf_color_equal(p, current, c) || PDF_FORCE_OUTPUT())
 | 
						|
	{
 | 
						|
	    if (PDF_GET_STATE(p) != pdf_state_document)
 | 
						|
		pdf_write_color_values(p, c, pdf_fill);
 | 
						|
 | 
						|
	    *current = *c;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    /* simple colorspaces don't get written */
 | 
						|
    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;
 | 
						|
 | 
						|
    for (i = 0; i < p->colorspaces_number; i++)
 | 
						|
	if (p->colorspaces[i].used_on_current_page)
 | 
						|
	    total++;
 | 
						|
 | 
						|
    if (total > 0
 | 
						|
       ) {
 | 
						|
	pdc_puts(p->out, "/ColorSpace");
 | 
						|
 | 
						|
	pdc_begin_dict(p->out);			/* color space names */
 | 
						|
 | 
						|
	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", i);
 | 
						|
		    pdc_objref(p->out, "", cs->obj_id);
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	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)
 | 
						|
{
 | 
						|
    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,
 | 
						|
	    pdc_errprintf(p->pdc, "%d", cs->type), 0, 0, 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)
 | 
						|
{
 | 
						|
    pdf_colorspace *cs;
 | 
						|
    int base;
 | 
						|
 | 
						|
    if (slot < 0 || slot >= p->colorspaces_number)
 | 
						|
	pdc_error(p->pdc, PDF_E_INT_BADCS,
 | 
						|
	    pdc_errprintf(p->pdc, "%d", slot), 0, 0, 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,
 | 
						|
	    pdc_errprintf(p->pdc, "%d", cs->type), 0, 0, 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)
 | 
						|
{
 | 
						|
    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,
 | 
						|
		    pdc_errprintf(p->pdc, "%d", cs->type), 0, 0, 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);
 | 
						|
	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 c;
 | 
						|
    pdf_colorspace cs;
 | 
						|
 | 
						|
    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_pattern:
 | 
						|
        cs.type = PatternCS;
 | 
						|
        if (p->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);
 | 
						|
	}
 | 
						|
        else
 | 
						|
        {
 | 
						|
	    cs.val.pattern.base = p->curr_ppt->cstate[p->curr_ppt->sl].fill.cs;
 | 
						|
	    c.cs = pdf_add_colorspace(p, &cs, pdc_true);
 | 
						|
	}
 | 
						|
        break;
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
    pdf_set_color_values(p, &c, (pdf_drawmode) drawmode);
 | 
						|
}
 | 
						|
 | 
						|
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);
 | 
						|
}
 | 
						|
 | 
						|
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}
 | 
						|
};
 | 
						|
 | 
						|
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_ET_MAXSTRLEN, optvalue[0]);
 | 
						|
            errcode = PDC_E_OPT_ILLKEYWORD;
 | 
						|
            goto PDF_COLOPT_ERROR;
 | 
						|
        }
 | 
						|
 | 
						|
        n = 1 + pdc_get_keycode_ci(optvalue[0], pdf_colorcomp_keylist);
 | 
						|
        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)
 | 
						|
                    {
 | 
						|
                        if (c->type == (int) color_spotname)
 | 
						|
                        {
 | 
						|
                            strcpy(c->name, optvalue[j]);
 | 
						|
                            continue;
 | 
						|
                        }
 | 
						|
                        else
 | 
						|
                        {
 | 
						|
                            stemp = pdc_errprintf(p->pdc, "%.*s",
 | 
						|
                                               PDC_ET_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_ET_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]);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
pdf_init_coloropt(pdf_coloropt *c)
 | 
						|
{
 | 
						|
    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;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 |