diff options
Diffstat (limited to 'src/pdflib/pdflib/p_xgstate.c')
-rw-r--r-- | src/pdflib/pdflib/p_xgstate.c | 514 |
1 files changed, 514 insertions, 0 deletions
diff --git a/src/pdflib/pdflib/p_xgstate.c b/src/pdflib/pdflib/p_xgstate.c new file mode 100644 index 0000000..0e62df9 --- /dev/null +++ b/src/pdflib/pdflib/p_xgstate.c @@ -0,0 +1,514 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 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.1 2008/10/17 06:11:49 scuri Exp $ + * + * Extended graphics state handling + * + */ + +#define P_XGSTATE_C + +#include "p_intern.h" +#include "p_font.h" + +static const pdc_keyconn pdf_blendmode_pdfkeylist[] = +{ + {"Normal", BM_Normal}, + {"Multiply", BM_Multiply}, + {"Screen", BM_Screen}, + {"Overlay", BM_Overlay}, + {"Darken", BM_Darken}, + {"Lighten", BM_Lighten}, + {"ColorDodge", BM_ColorDodge}, + {"ColorBurn", BM_ColorBurn}, + {"HardLight", BM_HardLight}, + {"SoftLight", BM_SoftLight}, + {"Difference", BM_Difference}, + {"Exclusion", BM_Exclusion}, + {"Hue", BM_Hue}, + {"Saturation", BM_Saturation}, + {"Color", BM_Color}, + {"Luminosity", BM_Luminosity}, + {NULL, 0} +}; + +/* 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, + pdf_linecap_keylist}, + + {"linejoin", pdc_integerlist, PDC_OPT_PDC_1_3, 1, 1, 0.0, 2.0, + pdf_linejoin_keylist}, + + {"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; + int bias = p->curr_ppt->eg_bias; + + for (i = 0; i < p->extgstates_number; i++) + if (p->extgstates[i].used_on_current_page) + total++; + + if (total > 0 || bias) + { + pdc_puts(p->out, "/ExtGState"); + pdc_begin_dict(p->out); + } + + if (total > 0) + { + 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", bias + i); + pdc_objref(p->out, "", p->extgstates[i].obj_id); + } + } + + if (!bias) + pdc_end_dict(p->out); + } +} + +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) +{ + int bias = p->curr_ppt->eg_bias; + + pdf_check_handle(p, gstate, pdc_gstatehandle); + + pdc_printf(p->out, "/GS%d gs\n", bias + gstate); + p->extgstates[gstate].used_on_current_page = pdc_true; +} |