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
		
			
				
	
	
		
			481 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			481 lines
		
	
	
		
			14 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_xgstate.c,v 1.2 2006-07-11 13:10:33 alex Exp $
 | |
|  *
 | |
|  * Extended graphics state handling
 | |
|  *
 | |
|  */
 | |
| 
 | |
| #define P_XGSTATE_C
 | |
| 
 | |
| #include "p_intern.h"
 | |
| 
 | |
| /*  external graphic state  */
 | |
| struct pdf_extgstateresource_s
 | |
| {
 | |
|     pdc_id      obj_id;                 /* object id of this resource */
 | |
|     pdc_bool    used_on_current_page;   /* this resource used on current page */
 | |
| 
 | |
|     pdc_id      font_obj;               /* font to use */
 | |
|     pdc_scalar  font_size;              /* at what size */
 | |
| 
 | |
|     pdc_scalar  line_width;
 | |
|     int         line_cap;
 | |
|     int         line_join;
 | |
|     pdc_scalar  miter_limit;
 | |
|     pdc_scalar* dash_array;
 | |
|     int         dash_count;
 | |
|     pdc_scalar  dash_phase;
 | |
| 
 | |
|     pdf_renderingintent       ri;
 | |
|     pdc_bool    stroke_adjust;
 | |
|     pdc_bool    overprint_stroke;
 | |
|     pdc_bool    overprint_fill;
 | |
|     int         overprint_mode;
 | |
| 
 | |
|     /*
 | |
|         The following entries which take functions are not implemented
 | |
|         since PDFlib has no concept of a function at this time.
 | |
| 
 | |
|         BG      - black generation
 | |
|         BG2     - black generation
 | |
|         UCR     - undercolor-removal
 | |
|         UCR2    - undercolor-removal
 | |
|         TR      - transfer
 | |
|         TR2     - transfer
 | |
|         HT      - halftone
 | |
|     */
 | |
| 
 | |
|     pdc_scalar       flatness;
 | |
|     pdc_scalar       smoothness;
 | |
| 
 | |
|     /* PDF 1.4 additions */
 | |
|     pdf_blendmode blendmode;            /* blend mode */
 | |
|     pdc_scalar  opacity_fill;           /* fill opacity level */
 | |
|     pdc_scalar  opacity_stroke;         /* stroke opacity level */
 | |
|     pdc_bool    alpha_is_shape;
 | |
|     pdc_bool    text_knockout;
 | |
| };
 | |
| 
 | |
| pdc_id
 | |
| pdf_get_gstate_id(PDF *p, int gstate)
 | |
| {
 | |
|     /* TODO: is this required for ExtGStates used in Shadings? */
 | |
|     p->extgstates[gstate].used_on_current_page = pdc_true;
 | |
| 
 | |
|     return (p->extgstates[gstate].obj_id);
 | |
| }
 | |
| 
 | |
| /* Definitions of Explicit Graphics State options */
 | |
| static const pdc_defopt pdf_create_gstate_options[] =
 | |
| {
 | |
|     {"alphaisshape", pdc_booleanlist, PDC_OPT_PDC_1_4, 1, 1, 0.0, 0.0, NULL},
 | |
| 
 | |
|     {"blendmode", pdc_keywordlist, PDC_OPT_BUILDOR | PDC_OPT_PDC_1_4, 1, 20,
 | |
|       0.0, 0.0, pdf_blendmode_pdfkeylist},
 | |
| 
 | |
| /* These features do not work in Acrobat (5.0.1)
 | |
|     {"dasharray", pdc_scalarlist, PDC_OPT_PDC_1_3, 1, 8,
 | |
|       PDF_SMALLREAL, PDC_FLOAT_MAX, NULL},
 | |
| 
 | |
|     {"dashphase", pdc_scalarlist, PDC_OPT_PDC_1_3, 1, 1,
 | |
|       0.0, PDC_FLOAT_MAX, NULL},
 | |
| 
 | |
|     {"fontsize", pdc_scalarlist, PDC_OPT_PDC_1_3, 1, 1,
 | |
|       PDF_SMALLREAL, PDC_FLOAT_MAX, NULL},
 | |
| 
 | |
|     {"font", pdc_fonthandle, PDC_OPT_PDC_1_3 | PDC_OPT_REQUIRIF1, 1, 1,
 | |
|       0, 0, NULL},
 | |
| */
 | |
| 
 | |
|     {"flatness", pdc_scalarlist, PDC_OPT_PDC_1_3, 1, 1,
 | |
|       PDF_SMALLREAL, PDC_FLOAT_MAX, NULL},
 | |
| 
 | |
|     {"linecap", pdc_integerlist, PDC_OPT_PDC_1_3, 1, 1, 0.0, 2.0, NULL},
 | |
| 
 | |
|     {"linejoin", pdc_integerlist, PDC_OPT_PDC_1_3, 1, 1, 0.0, 2.0, NULL},
 | |
| 
 | |
|     {"linewidth", pdc_scalarlist, PDC_OPT_PDC_1_3, 1, 1,
 | |
|       PDF_SMALLREAL, PDC_FLOAT_MAX, NULL},
 | |
| 
 | |
|     {"miterlimit", pdc_scalarlist, PDC_OPT_PDC_1_3, 1, 1, 1.0, PDC_FLOAT_MAX,
 | |
|       NULL},
 | |
| 
 | |
|     {"opacityfill", pdc_scalarlist, PDC_OPT_PDC_1_4 | PDC_OPT_PERCENT,
 | |
|      1, 1, 0.0, 1.0, NULL},
 | |
| 
 | |
|     {"opacitystroke", pdc_scalarlist, PDC_OPT_PDC_1_4 | PDC_OPT_PERCENT,
 | |
|      1, 1, 0.0, 1.0, NULL},
 | |
| 
 | |
|     {"overprintfill", pdc_booleanlist, PDC_OPT_PDC_1_3, 1, 1, 0.0, 0.0, NULL},
 | |
| 
 | |
|     {"overprintmode", pdc_integerlist, PDC_OPT_PDC_1_3, 1, 1, 0.0, 1.0, NULL},
 | |
| 
 | |
|     {"overprintstroke", pdc_booleanlist, PDC_OPT_PDC_1_3, 1, 1, 0.0, 0.0, NULL},
 | |
| 
 | |
|     {"renderingintent", pdc_keywordlist, PDC_OPT_PDC_1_3, 1, 1, 0.0, 0.0,
 | |
|       pdf_renderingintent_pdfkeylist},
 | |
| 
 | |
|     {"smoothness", pdc_scalarlist, PDC_OPT_PDC_1_3 | PDC_OPT_PERCENT,
 | |
|      1, 1, 0.0, 1.0, NULL},
 | |
| 
 | |
|     {"strokeadjust", pdc_booleanlist, PDC_OPT_PDC_1_3, 1, 1, 0.0, 0.0, NULL},
 | |
| 
 | |
|     {"textknockout", pdc_booleanlist, PDC_OPT_PDC_1_4, 1, 1, 0.0, 0.0, NULL},
 | |
| 
 | |
|     PDC_OPT_TERMINATE
 | |
| };
 | |
| 
 | |
| static void
 | |
| pdf_init_extgstateresource(pdf_extgstateresource *egsr)
 | |
| {
 | |
|     egsr->used_on_current_page	= pdc_false;
 | |
| 
 | |
|     /* we need to tell which parms have been set and which haven't,
 | |
|     ** so we initialize to invalid values. even boolean parms are
 | |
|     ** declared as integers, so we can set them to -1 here.
 | |
|     */
 | |
|     egsr->font_obj		= PDC_NEW_ID;
 | |
|     egsr->font_size             = pdc_undef;
 | |
| 
 | |
|     egsr->line_width            = pdc_undef;
 | |
|     egsr->line_cap              = pdc_undef;
 | |
|     egsr->line_join             = pdc_undef;
 | |
|     egsr->miter_limit           = pdc_undef;
 | |
| 
 | |
|     egsr->dash_array		= NULL;
 | |
|     egsr->dash_count		= 0;
 | |
|     egsr->dash_phase		= 0.0;
 | |
| 
 | |
|     egsr->ri                    = AutoIntent;
 | |
|     egsr->stroke_adjust         = pdc_undef;
 | |
|     egsr->overprint_stroke      = pdc_undef;
 | |
|     egsr->overprint_fill        = pdc_undef;
 | |
|     egsr->overprint_mode        = pdc_undef;
 | |
|     egsr->flatness              = pdc_undef;
 | |
|     egsr->smoothness            = pdc_undef;
 | |
| 
 | |
|     egsr->blendmode		= BM_None;
 | |
|     egsr->opacity_stroke        = pdc_undef;
 | |
|     egsr->opacity_fill          = pdc_undef;
 | |
|     egsr->alpha_is_shape        = pdc_undef;
 | |
|     egsr->text_knockout         = pdc_undef;
 | |
| }
 | |
| 
 | |
| static void
 | |
| pdf_grow_extgstates(PDF *p)
 | |
| {
 | |
|     int i;
 | |
| 
 | |
|     p->extgstates = (pdf_extgstateresource *) pdc_realloc(p->pdc, p->extgstates,
 | |
| 	sizeof(pdf_extgstateresource) * 2 * p->extgstates_capacity,
 | |
| 	"pdf_grow_extgstates");
 | |
| 
 | |
|     for (i = p->extgstates_capacity; i < 2 * p->extgstates_capacity; i++) {
 | |
| 	pdf_init_extgstateresource( &p->extgstates[i] );
 | |
|     }
 | |
| 
 | |
|     p->extgstates_capacity *= 2;
 | |
| }
 | |
| 
 | |
| void
 | |
| pdf_init_extgstates(PDF *p)
 | |
| {
 | |
|     static const char fn[] = "pdf_init_extgstates";
 | |
|     int i;
 | |
| 
 | |
|     p->extgstates_number = 0;
 | |
|     p->extgstates_capacity = EXTGSTATE_CHUNKSIZE;
 | |
| 
 | |
|     p->extgstates = (pdf_extgstateresource *)
 | |
|     pdc_malloc(p->pdc,
 | |
|                sizeof(pdf_extgstateresource) * p->extgstates_capacity, fn);
 | |
| 
 | |
|     for (i = 0; i < p->extgstates_capacity; i++) {
 | |
| 	pdf_init_extgstateresource( &p->extgstates[i] );
 | |
|     }
 | |
| }
 | |
| 
 | |
| void
 | |
| pdf_write_page_extgstates(PDF *p)
 | |
| {
 | |
|     int i, total = 0;
 | |
| 
 | |
|     for (i = 0; i < p->extgstates_number; i++)
 | |
| 	if (p->extgstates[i].used_on_current_page)
 | |
| 	    total++;
 | |
| 
 | |
|     if (total > 0) {
 | |
| 	pdc_puts(p->out, "/ExtGState");
 | |
| 
 | |
| 	pdc_begin_dict(p->out);			/* ExtGState names */
 | |
| 
 | |
| 	for (i = 0; i < p->extgstates_number; i++) {
 | |
| 	    if (p->extgstates[i].used_on_current_page) {
 | |
| 		p->extgstates[i].used_on_current_page = pdc_false; /* reset */
 | |
| 		pdc_printf(p->out, "/GS%d", i);
 | |
| 		pdc_objref(p->out, "", p->extgstates[i].obj_id);
 | |
| 	    }
 | |
| 	}
 | |
| 
 | |
| 	pdc_end_dict(p->out);			/* ExtGState names */
 | |
|     }
 | |
| }
 | |
| 
 | |
| void
 | |
| pdf_get_page_extgstates(PDF *p, pdf_reslist *rl)
 | |
| {
 | |
|     int i;
 | |
| 
 | |
|     for (i = 0; i < p->extgstates_number; i++) {
 | |
| 	if (p->extgstates[i].used_on_current_page) {
 | |
| 	    p->extgstates[i].used_on_current_page = pdc_false; /* reset */
 | |
| 	    pdf_add_reslist(p, rl, i);
 | |
| 	}
 | |
|     }
 | |
| }
 | |
| 
 | |
| void
 | |
| pdf_mark_page_extgstate(PDF *p, int n)
 | |
| {
 | |
|     p->extgstates[n].used_on_current_page = pdc_true;
 | |
| }
 | |
| 
 | |
| void
 | |
| pdf_write_doc_extgstates(PDF *p)
 | |
| {
 | |
|     int i, j;
 | |
| 
 | |
|     pdf_extgstateresource *gs;
 | |
| 
 | |
|     for (i = 0; i < p->extgstates_number; i++)
 | |
|     {
 | |
| 	gs = &p->extgstates[i];
 | |
| 
 | |
| 	pdc_begin_obj(p->out, gs->obj_id);		/* ExtGState resource */
 | |
| 	pdc_begin_dict(p->out);
 | |
| 
 | |
| 	pdc_puts(p->out, "/Type/ExtGState\n");
 | |
| 
 | |
| 	if (gs->font_obj != PDC_NEW_ID)
 | |
| 	{
 | |
| 	    pdc_puts(p->out, "/Font");
 | |
| 	    pdc_begin_array(p->out);
 | |
| 	    pdc_objref(p->out, "", gs->font_obj);
 | |
| 	    pdc_printf(p->out, "%f", gs->font_size);
 | |
| 	    pdc_end_array(p->out);
 | |
| 	}
 | |
| 
 | |
|         if (gs->line_width != pdc_undef)
 | |
| 	    pdc_printf(p->out, "/LW %f\n", gs->line_width);
 | |
| 
 | |
|         if (gs->line_cap != pdc_undef)
 | |
| 	    pdc_printf(p->out, "/LC %d\n", gs->line_cap);
 | |
| 
 | |
|         if (gs->line_join != pdc_undef)
 | |
| 	    pdc_printf(p->out, "/LJ %d\n", gs->line_join);
 | |
| 
 | |
|         if (gs->miter_limit != pdc_undef)
 | |
| 	    pdc_printf(p->out, "/ML %f\n", gs->miter_limit);
 | |
| 
 | |
| 	if (gs->dash_count > 0)
 | |
| 	{
 | |
| 	    pdc_printf(p->out, "/D");
 | |
| 	    pdc_begin_array(p->out);
 | |
| 	    pdc_begin_array(p->out);
 | |
| 
 | |
| 	    for (j = 0; j < gs->dash_count; ++j)
 | |
| 		pdc_printf(p->out, "%f ", gs->dash_array[j]);
 | |
| 
 | |
| 	    pdc_end_array_c(p->out);
 | |
|             pdc_printf(p->out, "%f", gs->dash_phase);
 | |
| 	    pdc_end_array(p->out);
 | |
|             /* but see page 157 of PDF Reference: integer */
 | |
| 	}
 | |
| 
 | |
| 	if (gs->ri != AutoIntent)
 | |
|             pdc_printf(p->out, "/RI/%s\n",
 | |
|                 pdc_get_keyword((long) gs->ri, pdf_renderingintent_pdfkeylist));
 | |
| 
 | |
|         if (gs->stroke_adjust != pdc_undef)
 | |
| 	    pdc_printf(p->out, "/SA %s\n", PDC_BOOLSTR(gs->stroke_adjust));
 | |
| 
 | |
|         if (gs->overprint_stroke != pdc_undef)
 | |
|             pdc_printf(p->out, "/OP %s\n", PDC_BOOLSTR(gs->overprint_stroke));
 | |
| 
 | |
|         if (gs->overprint_fill != pdc_undef)
 | |
|             pdc_printf(p->out, "/op %s\n", PDC_BOOLSTR(gs->overprint_fill));
 | |
|         else if (gs->overprint_stroke == pdc_true)
 | |
|             pdc_puts(p->out, "/op false\n");
 | |
| 
 | |
|         if (gs->overprint_mode != pdc_undef)
 | |
| 	    pdc_printf(p->out, "/OPM %d\n", gs->overprint_mode);
 | |
| 
 | |
|         if (gs->flatness != pdc_undef)
 | |
| 	    pdc_printf(p->out, "/FL %f\n", gs->flatness);
 | |
| 
 | |
|         if (gs->smoothness != pdc_undef)
 | |
| 	    pdc_printf(p->out, "/SM %f\n", gs->smoothness);
 | |
| 
 | |
|         if (gs->opacity_fill != pdc_undef)
 | |
| 	    pdc_printf(p->out, "/ca %f\n", gs->opacity_fill);
 | |
| 
 | |
| 	if (gs->blendmode != BM_None) {
 | |
|             const char *modename;
 | |
| 	    int modecount=0;
 | |
| 
 | |
| 	    for (j = 0; ; j++) {
 | |
|                 if (!pdf_blendmode_pdfkeylist[j].word)
 | |
| 		    break;
 | |
|                 if (gs->blendmode & pdf_blendmode_pdfkeylist[j].code)
 | |
|                     modecount++;
 | |
|             }
 | |
| 
 | |
| 	    pdc_printf(p->out, "/BM");
 | |
| 
 | |
| 	    /*
 | |
| 	     * ACROBUG: Acrobat 7 doesn't like Blend mode arrays with a
 | |
| 	     * singly entry under some circumstances (many entries? images
 | |
| 	     * involved?) so we avoid the array if we have only one entry.
 | |
| 	     */
 | |
| 	    if (modecount > 1)
 | |
| 		pdc_begin_array(p->out);
 | |
| 
 | |
| 	    for (j = 0; ; j++) {
 | |
|                 modename = pdf_blendmode_pdfkeylist[j].word;
 | |
|                 if (!modename) break;
 | |
|                 if (gs->blendmode & pdf_blendmode_pdfkeylist[j].code)
 | |
|                     pdc_printf(p->out, "/%s", modename);
 | |
|             }
 | |
| 
 | |
| 	    if (modecount > 1)
 | |
| 		pdc_end_array(p->out);
 | |
| 	}
 | |
| 
 | |
|         if (gs->opacity_stroke != pdc_undef)
 | |
| 	    pdc_printf(p->out, "/CA %f\n", gs->opacity_stroke);
 | |
| 
 | |
|         if (gs->alpha_is_shape != pdc_undef)
 | |
| 	    pdc_printf(p->out, "/AIS %s\n", PDC_BOOLSTR(gs->alpha_is_shape));
 | |
| 
 | |
|         if (gs->text_knockout != pdc_undef)
 | |
| 	    pdc_printf(p->out, "/TK %s\n", PDC_BOOLSTR(gs->text_knockout));
 | |
| 
 | |
| 	pdc_end_dict(p->out);
 | |
| 	pdc_end_obj(p->out);			/* ExtGState resource */
 | |
|     }
 | |
| }
 | |
| 
 | |
| void
 | |
| pdf_cleanup_extgstates(PDF *p)
 | |
| {
 | |
|     int i;
 | |
| 
 | |
|     if (!p->extgstates)
 | |
| 	return;
 | |
| 
 | |
|     for (i = 0; i < p->extgstates_number; i++) {
 | |
|         if (p->extgstates[i].dash_array)
 | |
|             pdc_free(p->pdc, p->extgstates[i].dash_array);
 | |
|     }
 | |
| 
 | |
|     pdc_free(p->pdc, p->extgstates);
 | |
|     p->extgstates = NULL;
 | |
| }
 | |
| 
 | |
| int
 | |
| pdf__create_gstate(PDF *p, const char *optlist)
 | |
| {
 | |
|     pdf_extgstateresource *gs;
 | |
|     int slot = -1;
 | |
|     int font = pdc_undef;
 | |
|     int inum;
 | |
|     pdc_clientdata data;
 | |
|     pdc_resopt *results;
 | |
| 
 | |
|     if (optlist == NULL || !*optlist)
 | |
|         pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "optlist", 0, 0, 0);
 | |
| 
 | |
|     slot = p->extgstates_number;
 | |
|     if (slot == p->extgstates_capacity)
 | |
|         pdf_grow_extgstates(p);
 | |
| 
 | |
|     p->extgstates_number++;
 | |
|     gs = &p->extgstates[slot];
 | |
|     gs->obj_id = pdc_alloc_id(p->out);
 | |
| 
 | |
|     /* parsing optlist */
 | |
|     pdf_set_clientdata(p, &data);
 | |
|     results = pdc_parse_optionlist(p->pdc, optlist, pdf_create_gstate_options,
 | |
|                                    &data, pdc_true);
 | |
| 
 | |
|     pdc_get_optvalues("alphaisshape", results, &gs->alpha_is_shape, NULL);
 | |
| 
 | |
|     if (pdc_get_optvalues("blendmode", results, &inum, NULL))
 | |
|         gs->blendmode = (pdf_blendmode) inum;
 | |
| 
 | |
|     gs->dash_count = pdc_get_optvalues("dasharray", results, NULL, NULL);
 | |
|     gs->dash_array = (pdc_scalar *) pdc_save_lastopt(results, PDC_OPT_SAVEALL);
 | |
| 
 | |
|     pdc_get_optvalues("dashphase", results, &gs->dash_phase, NULL);
 | |
| 
 | |
|     pdc_get_optvalues("flatness", results, &gs->flatness, NULL);
 | |
| 
 | |
|     pdc_get_optvalues("font", results, &font, NULL);
 | |
|     if (font != pdc_undef)
 | |
|         gs->font_obj = p->fonts[font].obj_id;
 | |
| 
 | |
|     pdc_get_optvalues("fontsize", results, &gs->font_size, NULL);
 | |
| 
 | |
|     pdc_get_optvalues("linecap", results, &gs->line_cap, NULL);
 | |
| 
 | |
|     pdc_get_optvalues("linejoin", results, &gs->line_join, NULL);
 | |
| 
 | |
|     pdc_get_optvalues("linewidth", results, &gs->line_width, NULL);
 | |
| 
 | |
|     pdc_get_optvalues("miterlimit", results, &gs->miter_limit, NULL);
 | |
| 
 | |
|     pdc_get_optvalues("opacityfill", results, &gs->opacity_fill, NULL);
 | |
| 
 | |
|     pdc_get_optvalues("opacitystroke", results, &gs->opacity_stroke, NULL);
 | |
| 
 | |
|     pdc_get_optvalues("overprintfill", results, &gs->overprint_fill, NULL);
 | |
| 
 | |
|     pdc_get_optvalues("overprintmode", results, &gs->overprint_mode, NULL);
 | |
| 
 | |
|     pdc_get_optvalues("overprintstroke", results, &gs->overprint_stroke, NULL);
 | |
| 
 | |
|     if (pdc_get_optvalues("renderingintent", results, &inum, NULL))
 | |
|         gs->ri = (pdf_renderingintent) inum;
 | |
| 
 | |
|     pdc_get_optvalues("smoothness", results, &gs->smoothness, NULL);
 | |
| 
 | |
|     pdc_get_optvalues("strokeadjust", results, &gs->stroke_adjust, NULL);
 | |
| 
 | |
|     pdc_get_optvalues("textknockout", results, &gs->text_knockout, NULL);
 | |
| 
 | |
|     pdc_cleanup_optionlist(p->pdc, results);
 | |
| 
 | |
| 
 | |
|     return slot;
 | |
| }
 | |
| 
 | |
| void
 | |
| pdf__set_gstate(PDF *p, int gstate)
 | |
| {
 | |
|     pdf_check_handle(p, gstate, pdc_gstatehandle);
 | |
| 
 | |
|     pdc_printf(p->out, "/GS%d gs\n", gstate);
 | |
|     p->extgstates[gstate].used_on_current_page = pdc_true;
 | |
| }
 |