/* Copyright (C) 2017-2021, Dirk Krause SPDX-License-Identifier: BSD-3-Clause */ /* WARNING: This file was generated by the dkct program (see http://dktools.sourceforge.net/ for details). Changes you make here will be lost if dkct is run again! You should modify the original source and run dkct on it. Original source: dk4grpdf.ctr */ /** @file dk4grpdf.c The dk4grpdf module. */ #ifdef DK4GRA_PDF_FORCE_UNCOMPRESSED #undef DK4GRA_PDF_FORCE_UNCOMPRESSED #endif /** Use for debugging purposes only to produce an uncompresse page contents data stream. Normally this should be defined to 0. */ #define DK4GRA_PDF_FORCE_UNCOMPRESSED 0 #include "dk4conf.h" #if DK4_HAVE_MATH_H #ifndef MATH_H_INCLUDED #if DK4_ON_WINDOWS #ifndef _USE_MATH_DEFINES #define _USE_MATH_DEFINES 1 #endif #endif #include #define MATH_H_INCLUDED 1 #endif #endif #ifndef DK4GRA_H_INCLUDED #include #endif #ifndef GRA_H_INCLUDED #include #endif #ifndef DK4MAO8D_H_INCLUDED #include #endif #ifndef DK4MAO8DNS_H_INCLUDED #include #endif #ifndef DK4UFIC_H_INCLUDED #include #endif #ifndef DK4STRD_H_INCLUDED #include #endif #ifndef DK4STRM_H_INCLUDED #include #endif #ifndef DK4STRMF_H_INCLUDED #include #endif #ifndef DK4STRMCO_H_INCLUDED #include #endif #ifndef DK4MEM_H_INCLUDED #include #endif #if DK4_HAVE_ASSERT_H #ifndef ASSERT_H_INCLUDED #include #define ASSERT_H_INCLUDED 1 #endif #endif /** PDF object position. */ typedef struct { size_t num; /**< Object number. */ dk4_um_t pos; /**< Start position in output stream. */ } dk4_gra_pdf_objpos_t; /** Constant text fragments used by module. */ static const char * const dk4_gra_pdf_c8_kw[] = { /* 0 */ "\n", /* 1 */ " ", /* 2 */ "q\n", /* 3 */ "Q\n", /* 4 */ " m\n", /* 5 */ " l\n", /* 6 */ " c\n", /* 7 */ "h\n", /* 8 */ "S\n", /* 9 */ "f\n", /* 10 */ "f*\n", /* 11 */ "B\n", /* 12 */ "B*\n", /* 13 */ "W n\n", /* 14 */ "W* n\n", /* 15 */ "1 g\n", /* 16 */ "0 ", /* 17 */ "0", /* 18 */ " 0", /* 19 */ " g\n", /* 20 */ " G\n", /* 21 */ " k\n", /* 22 */ " K\n", /* 23 */ " rg\n", /* 24 */ " RG\n", /* 25 */ " w\n", /* 26 */ "0 J\n", /* 27 */ "1 J\n", /* 28 */ "2 J\n", /* 29 */ "0 j\n", /* 30 */ "1 j\n", /* 31 */ "2 j\n", /* 32 */ "[] 0 d\n", /* 33 */ "[", /* 34 */ "] ", /* 35 */ " d\n", /* 36 */ "%PDF-1.4\n", /* 37 */ " 0 obj\n", /* 38 */ "endobj\n", /* 39 */ "<<\n", /* 40 */ ">>\n", /* 41 */ "/Producer (libdk4gra, see http://sourceforge.net/p/dktools/wiki/Home/)\n", /* 42 */ "/CreationDate (D:", /* 43 */ "/ModDate (D:", /* 44 */ ")\n", /* 45 */ "xref 0 ", /* 46 */ "0000000000 65535 f\n", /* 47 */ " 00000 n\n", /* 48 */ "trailer\n<< /Size ", /* 49 */ " /Info 1 0 R /Root 2 0 R >>\nstartxref\n", /* 50 */ "\n%%EOF\n", /* 51 */ "/Type /Catalog\n", /* 52 */ "/Pages 3 0 R\n", /* 53 */ "/Type /Pages\n", /* 54 */ "/Count ", /* 55 */ "/Kids [\n", /* 56 */ "]\n", /* 57 */ " 0 R\n", /* 58 */ "/Type /Page\n", /* 59 */ "/Parent 3 0 R\n", /* 60 */ "/MediaBox [0 0 ", /* 61 */ "/CropBox [0 0 ", /* 62 */ "/Resources <<\n", /* 63 */ "/ProcSet [/PDF /ImageB /ImageC]\n", /* 64 */ "/XObject <<\n", /* 65 */ "/Contents ", /* 66 */ "/Length ", /* 67 */ "/Filter /FlateDecode\n", /* 68 */ "stream\n", /* 69 */ "\nendstream\n", /* 70 */ " cm\n", /* 71 */ "/X", /* 72 */ " Do\n", /* 73 */ "/Type /XObject\n", /* 74 */ "/Subtype /Image\n", /* 75 */ "/Width ", /* 76 */ "/Height ", /* 77 */ "/BitsPerComponent ", /* 78 */ "/ColorSpace /DeviceRGB\n", /* 79 */ "/ColorSpace /DeviceGray\n", /* 80 */ "/ColorSpace /DeviceCMYK\n", /* 81 */ "/SMask ", /* 82 */ "/Interpolate true\n", /* 83 */ "/Filter /DCTDecode\n", /* 84 */ " M\n", /* 85 */ "/Decode [1 0 1 0 1 0 1 0]\n", /* 86 */ "/Decode [1 0 1 0 1 0] \n", /* 87 */ "/Decode [1 0 1 0] \n", /* 88 */ "/Decode [1 0]\n", NULL }; void dk4gra_pdf_i_outstream_kw( dk4_stream_t *os, size_t kwi, int *backptr, dk4_er_t *erp ) { #if DK4_USE_ASSERT assert(NULL != os); #endif dk4gratool_stream_string(os, dk4_gra_pdf_c8_kw[kwi], backptr, erp); } void dk4gra_pdf_i_values_and_kw( dk4_stream_t *os, double *da, size_t szda, size_t kwi, int *backptr, dk4_er_t *erp ) { size_t i; #if DK4_USE_ASSERT assert(NULL != os); assert(NULL != da); assert(0 < szda); #endif for (i = 0; i < szda; i++) { if (0 < i) { dk4gratool_stream_string(os, dk4_gra_pdf_c8_kw[1], backptr, erp); } if (0 == dk4ma_write_c8_double_no_sci_to_stream( os, da[i], DK4_GRA_EPSILON_COORDINATES, 0, 1, erp ) ) { if (NULL != backptr) { *backptr = 0; } } } dk4gratool_stream_string(os, dk4_gra_pdf_c8_kw[kwi], backptr, erp); } /** Compare page structures by number or a page against a number. @param l Left page object. @param r Right page object or page number. @param cr Comparison criteria (0=page/page, 1=page/number). @return Comparison result. */ static int dk4gra_pdf_compare_pages_by_number(const void *l, const void *r, int cr) { const dk4_gra_pdf_page_t *pl; const dk4_gra_pdf_page_t *pr; const size_t *ppno; int back = 0; if (NULL != l) { if (NULL != r) { pl = (const dk4_gra_pdf_page_t *)l; switch (cr) { case 1: { ppno = (const size_t *)r; if (pl->pageno > *ppno) { back = 1; } else { if (pl->pageno < *ppno) { back = -1; } } } break; default : { pr = (const dk4_gra_pdf_page_t *)r; if (pl->pageno > pr->pageno) { back = 1; } else { if (pl->pageno < pr->pageno) { back = -1; } } } break; } } else { back = 1; } } else { if (NULL != r) { back = -1; } } return back; } int dk4gra_pdf_compare_used_xo( const void *l, const void *r, int cr #if DK4_HAVE_ATTRIBUTE_UNUSED __attribute__((unused)) #endif ) { const dk4_gra_pdf_img_xo_t *pl; const dk4_gra_pdf_img_xo_t *pr; int back = 0; #if !DK4_HAVE_ATTRIBUTE_UNUSED (void)cr; #endif if (NULL != l) { if (NULL != r) { pl = (const dk4_gra_pdf_img_xo_t *)l; pr = (const dk4_gra_pdf_img_xo_t *)r; if (pl->objno > pr->objno) { back = 1; } else { if (pl->objno < pr->objno) { back = -1; } } } else { back = 1; } } else { if (NULL != r) { back = -1; } } return back; } /** Compare two object positions by number. @param l Left object. @param r Right object. @param cr Comparison criteria (0=objpos/objpos, 1=objpos/number). @return Comparison result. */ static int dk4gra_pdf_compare_objpos( const void *l, const void *r, int cr ) { const dk4_gra_pdf_objpos_t *pl; const dk4_gra_pdf_objpos_t *pr; const size_t *psz; int back = 0; if (NULL != l) { if (NULL != r) { pl = (const dk4_gra_pdf_objpos_t *)l; switch (cr) { case 1 : { psz = (const size_t *)r; if (pl->num > *psz) { back = 1; } else { if (pl->num < *psz) { back = -1; } } } break; default : { pr = (const dk4_gra_pdf_objpos_t *)r; if (pl->num > pr->num) { back = 1; } else { if (pl->num < pr->num) { back = -1; } } } break; } } else { back = 1; } } else { if (NULL != r) { back = -1; } } return back; } /** Check whether two XObjects are generated from the same file. @param pl Left object. @param pr Right object. @return Comparison result (0 for equality). */ static int dk4gra_pdf_xo_check_same_file( const dk4_gra_pdf_img_xo_t *pl, const dk4_gra_pdf_img_xo_t *pr ) { int back = 0; if (0 != pl->hufi) { if (0 != pr->hufi) { back = dk4ufi_compare(&(pl->ufi), &(pr->ufi)); } else { back = 1; } } else { if (0 != pr->hufi) { back = -1; } else { if (NULL != pl->fn) { if (NULL != pr->fn) { back = dk4str_pathcmp(pl->fn, pr->fn); } else { back = 1; } } else { if (NULL != pr->fn) { back = -1; } else { if (pl->objno > pr->objno) { back = 1; } else { if (pl->objno < pr->objno) { back = -1; } } } } } } return back; } /** Compare two integer values. @param l Left value. @param r Right value. @return Comparison result. */ static int dk4gra_pdf_compare_int(int l, int r) { int back = 0; if (l > r) { back = 1; } else { if (l < r) { back = -1; } } return back; } /** Compare two XObjects whether or not they contain the same file and frame number using same conversion settings. @param l Left object. @param r Right object. @param cr Comparison criteria (ignored). @return Comparison result. */ static int dk4gra_pdf_compare_xo( const void *l, const void *r, int cr #if DK4_HAVE_ATTRIBUTE_UNUSED __attribute__((unused)) #endif ) { const dk4_gra_pdf_img_xo_t *pl; const dk4_gra_pdf_img_xo_t *pr; int back = 0; #if !DK4_HAVE_ATTRIBUTE_UNUSED (void)cr; #endif if (NULL != l) { if (NULL != r) { pl = (const dk4_gra_pdf_img_xo_t *)l; pr = (const dk4_gra_pdf_img_xo_t *)r; /* Check whether or not both XObjects use the same file */ back = dk4gra_pdf_xo_check_same_file(pl, pr); /* If the same file is used for both XObjects, check whether the same settings are used */ if (0 == back) { if (pl->fno > pr->fno) { back = 1; } else { if (pl->fno < pr->fno) { back = -1; } } } if (0 == back) { back = dk4gra_pdf_compare_int(pl->dct, pr->dct); } if (0 == back) { back = dk4gra_pdf_compare_int(pl->ipol, pr->ipol); } if (0 == back) { back = dk4gra_pdf_compare_int(pl->cs, pr->cs); } if (0 == back) { back = dk4gra_pdf_compare_int(pl->bpc, pr->bpc); } if (0 == back) { back = dk4gra_pdf_compare_int(pl->deci, pr->deci); } } else { back = 1; } } else { if (NULL != r) { back = -1; } } return back; } /** Destroy XObject structure, release resources. @param puxo XObject structure to destroy. */ void dk4gra_pdf_xo_delete( dk4_gra_pdf_img_xo_t *puxo ) { #if DK4_USE_ASSERT assert(NULL != puxo); #endif if (NULL != puxo) { if (NULL != puxo->i_mb) { dk4membuf_close(puxo->i_mb); } puxo->i_mb = NULL; if (NULL != puxo->m_mb) { dk4membuf_close(puxo->m_mb); } puxo->m_mb = NULL; if (NULL != puxo->fn) { dk4mem_free((void *)(puxo->fn)); } puxo->fn = NULL; dk4mem_free(puxo); } } /** Destroy page structure, release resources. @param pptr Page to destroy. */ static void dk4gra_pgf_page_delete( dk4_gra_pdf_page_t *pptr ) { #if DK4_USE_ASSERT assert(NULL != pptr); #endif if (NULL != pptr) { if (NULL != pptr->s_uxo) { if (NULL != pptr->i_uxo) { dk4sto_it_close(pptr->i_uxo); } dk4sto_close(pptr->s_uxo); } pptr->s_uxo = NULL; pptr->i_uxo = NULL; if (NULL != pptr->costrm) { dk4stream_close(pptr->costrm, NULL); } pptr->costrm = NULL; if (NULL != pptr->memstrm) { dk4stream_close(pptr->memstrm, NULL); } pptr->memstrm = NULL; if (NULL != pptr->membuf) { dk4membuf_close(pptr->membuf); } pptr->membuf = NULL; pptr->outstrm = NULL; dk4mem_free(pptr); } } /** Write path construction commands to output stream. @param os Output stream. @param gra Output structure. @param backptr Address of success variable to reset on errors. @param erp Error report, may be NULL. */ static void dk4gra_pdf_page_box_path( dk4_stream_t *os, dk4_gra_t *gra, int *backptr, dk4_er_t *erp ) { #if DK4_USE_ASSERT assert(NULL != gra); assert(NULL != os); #endif /* 0 0 newpathmoveto */ dk4gra_pdf_i_outstream_kw(os, 16, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 17, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 4, backptr, erp); /* w 0 lineto */ dk4gratool_stream_uint(os, gra->w, 0, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 18, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 5, backptr, erp); /* w h lineto */ dk4gratool_stream_uint(os, gra->w, 0, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 1, backptr, erp); dk4gratool_stream_uint(os, gra->h, 0, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 5, backptr, erp); /* 0 h lineto */ dk4gra_pdf_i_outstream_kw(os, 16, backptr, erp); dk4gratool_stream_uint(os, gra->h, 0, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 5, backptr, erp); /* closepath */ dk4gra_pdf_i_outstream_kw(os, 7, backptr, erp); } /** Create new page, allocate resources. @param pageno Page number of new page. @param flags Flags to open new page. @param erp Error report, may be NULL. @return Valid pointer on success, NULL on error. */ static dk4_gra_pdf_page_t * dk4gra_pdf_page_new( size_t pageno, dk4_gra_t *gra, int flags, dk4_er_t *erp ) { dk4_gra_pdf_page_t *back = NULL; int ok = 0; #if DK4_USE_ASSERT assert(NULL != gra); #endif #if DK4GRA_PDF_FORCE_UNCOMPRESSED flags |= DK4_GRA_PAGE_FLAG_NOT_COMPRESSED; #endif back = dk4mem_new(dk4_gra_pdf_page_t,1,erp); if (NULL == back) { goto finished; } back->membuf = NULL; back->memstrm = NULL; back->costrm = NULL; back->outstrm = NULL; back->s_uxo = NULL; back->i_uxo = NULL; back->pageno = pageno; back->objno = 0; back->flags = flags; dk4gratool_initialize_attributes(&(back->attr)); back->membuf = dk4membuf_open(erp); if (NULL == back->membuf) { goto finished; } back->memstrm = dk4stream_open_membuf_writer(back->membuf, erp); if (NULL == back->membuf) { goto finished; } if (0 != (flags & DK4_GRA_PAGE_FLAG_NOT_COMPRESSED)) { back->outstrm = back->memstrm; ok = 1; } else { back->costrm = dk4strmco_open( back->memstrm, DK4_STRMCO_PP_NONE, DK4_STRMCO_CO_FLATE, DK4_STRMCO_OE_NONE, 0, erp ); if (NULL != back->costrm) { back->outstrm = back->costrm; ok = 1; } } if (1 == ok) { /* TODO: gsave */ dk4gra_pdf_i_outstream_kw(back->outstrm, 2, &ok, erp); /* clip */ if (0 == (flags & DK4_GRA_PAGE_FLAG_NO_CLIP)) { dk4gra_pdf_page_box_path(back->outstrm, gra, &ok, erp); dk4gra_pdf_i_outstream_kw(back->outstrm, 13, &ok, erp); } /* fill */ if (0 == (flags & DK4_GRA_PAGE_FLAG_NO_BG)) { dk4gra_pdf_i_outstream_kw(back->outstrm, 15, &ok, erp); dk4gra_pdf_page_box_path(back->outstrm, gra, &ok, erp); dk4gra_pdf_i_outstream_kw(back->outstrm, 9, &ok, erp); } } finished: if ((NULL != back) && (0 == ok)) { dk4gra_pgf_page_delete(back); back = NULL; } return back; } /** Change current fill or stroke color if necessary. @param os Output stream. @param cpactive Active color. @param cprequested Requested color. @param fill Flag: Fill color (0=stroke color). @param backptr Address of success variable to reset on errors. @param erp Error report, may be NULL. */ static void dk4gra_pdf_set_color_if_necessary( dk4_stream_t *os, dk4gra_col_t *cpactive, dk4gra_col_t *cprequested, int fill, int *backptr, dk4_er_t *erp ) { #if DK4_USE_ASSERT assert(NULL != os); assert(NULL != cpactive); assert(NULL != cprequested); #endif if (dk4gratool_colors_differ(cpactive, cprequested)) { switch (cprequested->what) { case DK4_GRA_COL_SPEC_GRAY : { dk4gratool_stream_double( os, cprequested->data.gray, backptr, erp ); dk4gra_pdf_i_outstream_kw( os, ((0 != fill) ? (19) : (20)), backptr, erp ); } break; case DK4_GRA_COL_SPEC_CMYK : { dk4gratool_stream_double( os, cprequested->data.cmyk.c, backptr, erp ); dk4gra_pdf_i_outstream_kw(os, 1, backptr, erp); dk4gratool_stream_double( os, cprequested->data.cmyk.m, backptr, erp ); dk4gra_pdf_i_outstream_kw(os, 1, backptr, erp); dk4gratool_stream_double( os, cprequested->data.cmyk.y, backptr, erp ); dk4gra_pdf_i_outstream_kw(os, 1, backptr, erp); dk4gratool_stream_double( os, cprequested->data.cmyk.k, backptr, erp ); dk4gra_pdf_i_outstream_kw( os, ((0 != fill) ? (21) : (22)), backptr, erp ); } break; default : { /* RGB */ dk4gratool_stream_double( os, cprequested->data.rgb.r, backptr, erp ); dk4gra_pdf_i_outstream_kw(os, 1, backptr, erp); dk4gratool_stream_double( os, cprequested->data.rgb.g, backptr, erp ); dk4gra_pdf_i_outstream_kw(os, 1, backptr, erp); dk4gratool_stream_double( os, cprequested->data.rgb.b, backptr, erp ); dk4gra_pdf_i_outstream_kw( os, ((0 != fill) ? (23) : (24)), backptr, erp ); } break; } dk4mem_cpy(cpactive, cprequested, sizeof(dk4gra_col_t), erp); } } /** Write dash setup to output stream. @param os Output stream. @param da Dash length array. @param szda Size of dash length array (number of elements). @param phase Phase for dash pattern. @param backptr Address of success variable to reset on errors. @param erp Error report, may be NULL. */ static void dk4gra_pdf_dash_out( dk4_stream_t *os, double *da, size_t szda, double phase, int *backptr, dk4_er_t *erp ) { size_t i; #if DK4_USE_ASSERT assert(NULL != os); assert(NULL != da); assert(0 < szda); #endif dk4gra_pdf_i_outstream_kw(os, 33, backptr, erp); for (i = 0; i < szda; i++) { if (0 < i) { dk4gra_pdf_i_outstream_kw(os, 1, backptr, erp); } dk4gratool_stream_double(os, da[i], backptr, erp); } dk4gra_pdf_i_outstream_kw(os, 34, backptr, erp); dk4gratool_stream_double(os, phase, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 35, backptr, erp); } /** Begin a new object, save start position. @param os Output stream. @param gra Output structure. @param objno Number of new object. @param backptr Address of success variable to reset on errors. @param erp Error report, may be NULL. */ static void dk4gra_pdf_begin_object( dk4_stream_t *os, dk4_gra_t *gra, size_t objno, int *backptr, dk4_er_t *erp ) { dk4_gra_pdf_objpos_t *ppos = NULL; dk4_um_t position; #if DK4_USE_ASSERT assert(NULL != gra); assert(NULL != os); #endif position = dk4stream_bytes_written(os); dk4gratool_stream_uint(os, objno, 0, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 37, backptr, erp); ppos = dk4mem_new(dk4_gra_pdf_objpos_t,1,erp); if (NULL != ppos) { ppos->pos = position; ppos->num = objno; if (0 == dk4sto_add(gra->out.pdf.s_objpos, ppos, erp)) { dk4mem_free(ppos); if (NULL != backptr) { *backptr = 0; } } } else { if (NULL != backptr) { *backptr = 0; } } } /** End current object. @param os Output stream. @param backptr Address of success variable to reset on errors. @param erp Error report, may be NULL. */ static void dk4gra_pdf_end_object( dk4_stream_t *os, int *backptr, dk4_er_t *erp ) { #if DK4_USE_ASSERT assert(NULL != os); #endif dk4gra_pdf_i_outstream_kw(os, 38, backptr, erp); } /** Enumerate pages (assign object numbers to pages). @param gra Output structure. @param erp Error report, may be NULL. @return 1 on success, 0 on error. */ static int dk4gra_pdf_enumerate_pages( dk4_gra_t *gra, dk4_er_t *erp ) { dk4_gra_pdf_page_t *bptr; int back = 1; #if DK4_USE_ASSERT assert(NULL != gra); #endif dk4sto_it_reset(gra->i_pages); do { bptr = (dk4_gra_pdf_page_t *)dk4sto_it_next(gra->i_pages); if (NULL != bptr) { /* If gsave was issued at start of stream, issue grestore now */ if (0 == ((bptr->flags) & DK4_GRA_PAGE_FLAG_NO_CLIP)) { if (NULL != bptr->outstrm) { dk4gra_pdf_i_outstream_kw(bptr->outstrm, 3, &back, erp); } } bptr->outstrm = NULL; /* Close compressed stream */ if (NULL != bptr->costrm) { if (0 == dk4stream_close(bptr->costrm, erp)) { back = 0; } } bptr->costrm = NULL; /* Close memory stream */ if (NULL != bptr->memstrm) { if (0 == dk4stream_close(bptr->memstrm, erp)) { back = 0; } } bptr->memstrm = NULL; /* Assign object number */ if ((SIZE_MAX - 1) > gra->out.pdf.nextobj) { bptr->objno = gra->out.pdf.nextobj; gra->out.pdf.nextobj += 2; } else { dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW); back = 0; } } } while ((1 == back) && (NULL != bptr)); if (SIZE_MAX <= gra->out.pdf.nextobj) { dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW); back = 0; } return back; } static void dk4gra_pdf_one_xobject( dk4_stream_t *os, dk4_gra_t *gra, dk4_gra_pdf_img_xo_t *puxo, int *backptr, dk4_er_t *erp ) { size_t szmb; #if DK4_USE_ASSERT assert(NULL != gra); assert(NULL != os); assert(NULL != puxo); #endif /* Image object */ dk4gra_pdf_begin_object(os, gra, puxo->objno, backptr, erp); /* << */ dk4gra_pdf_i_outstream_kw(os, 39, backptr, erp); /* /Type /XObject */ dk4gra_pdf_i_outstream_kw(os, 73, backptr, erp); /* /Subtype /Image */ dk4gra_pdf_i_outstream_kw(os, 74, backptr, erp); /* /Width ... */ dk4gra_pdf_i_outstream_kw(os, 75, backptr, erp); dk4gratool_stream_uint(os, (dk4_um_t)(puxo->width), 0, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 0, backptr, erp); /* /Height ... */ dk4gra_pdf_i_outstream_kw(os, 76, backptr, erp); dk4gratool_stream_uint(os, (dk4_um_t)(puxo->height), 0, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 0, backptr, erp); /* /BitsPerComponent ... */ dk4gra_pdf_i_outstream_kw(os, 77, backptr, erp); dk4gratool_stream_uint(os, puxo->bpc, 0, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 0, backptr, erp); /* /ColorSpace ... */ switch (puxo->cs) { case DK4_CS_CMYK : { dk4gra_pdf_i_outstream_kw(os, 80, backptr, erp); } break; case DK4_CS_GRAY : case DK4_CS_GRAY_ALPHA : { dk4gra_pdf_i_outstream_kw(os, 79, backptr, erp); } break; default : { dk4gra_pdf_i_outstream_kw(os, 78, backptr, erp); } break; } if ((0 != puxo->mobjno) && (NULL != puxo->m_mb)) { /* /SMask ... */ dk4gra_pdf_i_outstream_kw(os, 81, backptr, erp); dk4gratool_stream_uint(os, puxo->mobjno, 0, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 57, backptr, erp); } /* /Interpolate ... */ if (0 != puxo->ipol) { dk4gra_pdf_i_outstream_kw(os, 82, backptr, erp); } /* /Filter ... */ dk4gra_pdf_i_outstream_kw(os,((0 != puxo->dct) ? (83) : (67)),backptr,erp); /* /Length ... */ dk4gra_pdf_i_outstream_kw(os, 66, backptr, erp); if (0 == dk4membuf_size(&szmb, puxo->i_mb, erp)) { szmb = 0; } dk4gratool_stream_uint(os, szmb, 0, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 0, backptr, erp); if (0 != puxo->deci) { switch (puxo->cs) { case DK4_CS_CMYK : { dk4gra_pdf_i_outstream_kw(os, 85, backptr, erp); } break; case DK4_CS_RGB_ALPHA : { dk4gra_pdf_i_outstream_kw(os, 85, backptr, erp); } break; case DK4_CS_RGB : { dk4gra_pdf_i_outstream_kw(os, 86, backptr, erp); } break; case DK4_CS_GRAY_ALPHA : { dk4gra_pdf_i_outstream_kw(os, 87, backptr, erp); } break; case DK4_CS_GRAY : { dk4gra_pdf_i_outstream_kw(os, 88, backptr, erp); } break; } } /* >> */ dk4gra_pdf_i_outstream_kw(os, 40, backptr, erp); /* stream */ dk4gra_pdf_i_outstream_kw(os, 68, backptr, erp); /* Memory buffer contents */ if (0 == dk4membuf_to_stream(os, puxo->i_mb, erp)) { if (NULL != backptr) { *backptr = 0; } } /* endstream */ dk4gra_pdf_i_outstream_kw(os, 69, backptr, erp); dk4gra_pdf_end_object(os, backptr, erp); /* Mask object, if available */ if ((0 != puxo->mobjno) && (NULL != puxo->m_mb)) { dk4gra_pdf_begin_object(os, gra, puxo->mobjno, backptr, erp); /* << */ dk4gra_pdf_i_outstream_kw(os, 39, backptr, erp); /* /Type /XObject */ dk4gra_pdf_i_outstream_kw(os, 73, backptr, erp); /* /Subtype /Image */ dk4gra_pdf_i_outstream_kw(os, 74, backptr, erp); /* /Width ... */ dk4gra_pdf_i_outstream_kw(os, 75, backptr, erp); dk4gratool_stream_uint(os, (dk4_um_t)(puxo->width), 0, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 0, backptr, erp); /* /Height ... */ dk4gra_pdf_i_outstream_kw(os, 76, backptr, erp); dk4gratool_stream_uint(os, (dk4_um_t)(puxo->height), 0, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 0, backptr, erp); /* /BitsPerComponent ... */ dk4gra_pdf_i_outstream_kw(os, 77, backptr, erp); dk4gratool_stream_uint(os, puxo->bpc, 0, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 0, backptr, erp); /* /ColorSpace /DeviceGray */ dk4gra_pdf_i_outstream_kw(os, 79, backptr, erp); /* /Filter /FlateDecode */ dk4gra_pdf_i_outstream_kw(os, 67, backptr, erp); /* /Length ... */ if (0 == dk4membuf_size(&szmb, puxo->m_mb, erp)) { szmb = 0; } dk4gra_pdf_i_outstream_kw(os, 66, backptr, erp); dk4gratool_stream_uint(os, szmb, 0, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 0, backptr, erp); /* >> */ dk4gra_pdf_i_outstream_kw(os, 40, backptr, erp); /* stream */ dk4gra_pdf_i_outstream_kw(os, 68, backptr, erp); /* Memory buffer contents */ if (0 == dk4membuf_to_stream(os, puxo->m_mb, erp)) { if (NULL != backptr) { *backptr = 0; } } /* endstream */ dk4gra_pdf_i_outstream_kw(os, 69, backptr, erp); dk4gra_pdf_end_object(os, backptr, erp); } } static void dk4gra_pdf_one_page( dk4_stream_t *os, dk4_gra_t *gra, dk4_gra_pdf_page_t *bptr, int *backptr, dk4_er_t *erp ) { dk4_gra_pdf_img_xo_t *xo; size_t mbs = 0; #if DK4_USE_ASSERT assert(NULL != gra); assert(NULL != os); #endif dk4gra_pdf_begin_object(os, gra, bptr->objno, backptr, erp); /* << */ dk4gra_pdf_i_outstream_kw(os, 39, backptr, erp); /* /Type /Page */ dk4gra_pdf_i_outstream_kw(os, 58, backptr, erp); /* /Parent 3 0 R */ dk4gra_pdf_i_outstream_kw(os, 59, backptr, erp); /* /MediaBox [ 0 0 595 842 ] */ dk4gra_pdf_i_outstream_kw(os, 60, backptr, erp); dk4gratool_stream_uint(os, gra->w, 0, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 1, backptr, erp); dk4gratool_stream_uint(os, gra->h, 0, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 56, backptr, erp); /* /CropBox [ 0 0 595 842 ] */ dk4gra_pdf_i_outstream_kw(os, 61, backptr, erp); dk4gratool_stream_uint(os, gra->w, 0, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 1, backptr, erp); dk4gratool_stream_uint(os, gra->h, 0, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 56, backptr, erp); /* /Resources << */ dk4gra_pdf_i_outstream_kw(os, 62, backptr, erp); /* /ProcSet [ /PDF /ImageB /ImageC ] */ dk4gra_pdf_i_outstream_kw(os, 63, backptr, erp); if ((NULL != bptr->s_uxo) && (NULL != bptr->i_uxo)) { dk4gra_pdf_i_outstream_kw(os, 64, backptr, erp); dk4sto_it_reset(bptr->i_uxo); do { xo = (dk4_gra_pdf_img_xo_t *)dk4sto_it_next(bptr->i_uxo); if (NULL != xo) { dk4gra_pdf_i_outstream_kw(os, 71, backptr, erp); dk4gratool_stream_uint(os, xo->objno, 0, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 1, backptr, erp); dk4gratool_stream_uint(os, xo->objno, 0, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 57, backptr, erp); } } while (NULL != xo); dk4gra_pdf_i_outstream_kw(os, 40, backptr, erp); } /* >> */ dk4gra_pdf_i_outstream_kw(os, 40, backptr, erp); /* /Contents 12 0 R */ dk4gra_pdf_i_outstream_kw(os, 65, backptr, erp); dk4gratool_stream_uint(os, (bptr->objno + 1), 0, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 57, backptr, erp); /* >> */ dk4gra_pdf_i_outstream_kw(os, 40, backptr, erp); dk4gra_pdf_end_object(os, backptr, erp); dk4gra_pdf_begin_object(os, gra, (bptr->objno + 1), backptr, erp); /* << */ dk4gra_pdf_i_outstream_kw(os, 39, backptr, erp); /* /Length ... */ if (0 == dk4membuf_size(&mbs, bptr->membuf, erp)) { if (NULL != backptr) { *backptr = 0; } } dk4gra_pdf_i_outstream_kw(os, 66, backptr, erp); dk4gratool_stream_uint(os, mbs, 0, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 0, backptr, erp); /* /Filter ... */ if (0 == ((bptr->flags) & DK4_GRA_PAGE_FLAG_NOT_COMPRESSED)) { dk4gra_pdf_i_outstream_kw(os, 67, backptr, erp); } /* >> */ dk4gra_pdf_i_outstream_kw(os, 40, backptr, erp); /* stream */ dk4gra_pdf_i_outstream_kw(os, 68, backptr, erp); /* data */ if (0 == dk4membuf_to_stream(os, bptr->membuf, erp)) { if (NULL != backptr) { *backptr = 0; } } /* endstream */ dk4gra_pdf_i_outstream_kw(os, 69, backptr, erp); dk4gra_pdf_end_object(os, backptr, erp); } static void dk4gra_pdf_xref_section( dk4_stream_t *os, dk4_gra_t *gra, int *backptr, dk4_er_t *erp ) { dk4_gra_pdf_objpos_t *objpos; dk4_um_t startxrefpos; #if DK4_USE_ASSERT assert(NULL != gra); assert(NULL != os); #endif startxrefpos = dk4stream_bytes_written(os); dk4gra_pdf_i_outstream_kw(os, 45, backptr, erp); dk4gratool_stream_uint(os, gra->out.pdf.nextobj, 0, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 0, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 46, backptr, erp); dk4sto_it_reset(gra->out.pdf.i_objpos); do { objpos = (dk4_gra_pdf_objpos_t *)dk4sto_it_next(gra->out.pdf.i_objpos); if (NULL != objpos) { dk4gratool_stream_uint(os, objpos->pos, 10, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 47, backptr, erp); } } while (NULL != objpos); dk4gra_pdf_i_outstream_kw(os, 48, backptr, erp); dk4gratool_stream_uint(os, gra->out.pdf.nextobj, 0, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 49, backptr, erp); dk4gratool_stream_uint(os, startxrefpos, 0, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 50, backptr, erp); } /** Write PDF file. @param fout Output file, opened for binary write operations. @param gra Output structure. @param erp Error report, may be NULL. @return 1 on success, 0 on error. */ static int dk4gra_pdf_file( FILE *fout, dk4_gra_t *gra, dk4_er_t *erp ) { char timestamp[64]; dk4_gra_pdf_img_xo_t *puxo; dk4_gra_pdf_page_t *bptr; dk4_stream_t *os = NULL; int back = 0; #if DK4_USE_ASSERT assert(NULL != gra); assert(NULL != fout); #endif if (0 == dk4gra_pdf_timestamp(timestamp, sizeof(timestamp), erp)) { goto finished; } os = dk4stream_open_for_file(fout, DK4_STREAM_WRITE, 4096, 4096, erp); if (NULL == os) { goto finished; } back = dk4gra_pdf_enumerate_pages(gra, erp); /* PDF line at start of file */ dk4gra_pdf_i_outstream_kw(os, 36, &back, erp); /* Object 1 is Info object. */ dk4gra_pdf_begin_object(os, gra, 1, &back, erp); /* << */ dk4gra_pdf_i_outstream_kw(os, 39, &back, erp); /* /Producer (http://sourceforge.net/p/dktools/wiki/Home/) */ dk4gra_pdf_i_outstream_kw(os, 41, &back, erp); /* /CreationDate (D:20170324235818) */ dk4gra_pdf_i_outstream_kw(os, 42, &back, erp); if (0 == dk4stream_write_char_string(os, timestamp, erp)) { back = 0; } dk4gra_pdf_i_outstream_kw(os, 44, &back, erp); /* /ModDate (D:20170324235818) */ dk4gra_pdf_i_outstream_kw(os, 43, &back, erp); if (0 == dk4stream_write_char_string(os, timestamp, erp)) { back = 0; } dk4gra_pdf_i_outstream_kw(os, 44, &back, erp); /* >> */ dk4gra_pdf_i_outstream_kw(os, 40, &back, erp); dk4gra_pdf_end_object(os, &back, erp); /* Object 2 is Root object. */ dk4gra_pdf_begin_object(os, gra, 2, &back, erp); /* << */ dk4gra_pdf_i_outstream_kw(os, 39, &back, erp); /* /Type /Catalog */ dk4gra_pdf_i_outstream_kw(os, 51, &back, erp); /* /Pages 3 0 R */ dk4gra_pdf_i_outstream_kw(os, 52, &back, erp); /* >> */ dk4gra_pdf_i_outstream_kw(os, 40, &back, erp); dk4gra_pdf_end_object(os, &back, erp); /* Object 3 is Pages object. */ dk4gra_pdf_begin_object(os, gra, 3, &back, erp); /* << */ dk4gra_pdf_i_outstream_kw(os, 39, &back, erp); /* /Type /Pages */ dk4gra_pdf_i_outstream_kw(os, 53, &back, erp); /* /Count ... */ dk4gra_pdf_i_outstream_kw(os, 54, &back, erp); dk4gratool_stream_uint(os, gra->pages, 0, &back, erp); dk4gra_pdf_i_outstream_kw(os, 0, &back, erp); /* /Kids [ */ dk4gra_pdf_i_outstream_kw(os, 55, &back, erp); dk4sto_it_reset(gra->i_pages); do { bptr = (dk4_gra_pdf_page_t *)dk4sto_it_next(gra->i_pages); if (NULL != bptr) { dk4gratool_stream_uint(os, bptr->objno, 0, &back, erp); dk4gra_pdf_i_outstream_kw(os, 57, &back, erp); } } while (NULL != bptr); /* ] */ dk4gra_pdf_i_outstream_kw(os, 56, &back, erp); /* >> */ dk4gra_pdf_i_outstream_kw(os, 40, &back, erp); dk4gra_pdf_end_object(os, &back, erp); /* XOjects for images */ dk4sto_it_reset(gra->out.pdf.i_imagno); do { puxo = (dk4_gra_pdf_img_xo_t *)dk4sto_it_next(gra->out.pdf.i_imagno); if (NULL != puxo) { dk4gra_pdf_one_xobject(os, gra, puxo, &back, erp); } } while (NULL != puxo); /* Pages and content streams */ dk4sto_it_reset(gra->i_pages); do { bptr = (dk4_gra_pdf_page_t *)dk4sto_it_next(gra->i_pages); if (NULL != bptr) { dk4gra_pdf_one_page(os, gra, bptr, &back, erp); } } while (NULL != bptr); /* Finishing section (xref) */ dk4gra_pdf_xref_section(os, gra, &back, erp); finished: if (NULL != os) { if (0 == dk4stream_close(os, erp)) { back = 0; } } return back; } void dk4gra_pdf_close( dk4_gra_t *gra ) { dk4_gra_pdf_page_t *bptr; dk4_gra_pdf_img_xo_t *puxo; void *vptr; #if DK4_USE_ASSERT assert(NULL != gra); #endif if (NULL == gra) { goto finished; } /* Release object positions */ if (NULL != gra->out.pdf.s_objpos) { if (NULL != gra->out.pdf.i_objpos) { dk4sto_it_reset(gra->out.pdf.i_objpos); do { vptr = dk4sto_it_next(gra->out.pdf.i_objpos); if (NULL != vptr) { dk4mem_free(vptr); } } while (NULL != vptr); dk4sto_it_close(gra->out.pdf.i_objpos); } dk4sto_close(gra->out.pdf.s_objpos); } gra->out.pdf.s_objpos = NULL; gra->out.pdf.i_objpos = NULL; /* Release storage and iterator sorted by XObject object number */ if (NULL != gra->out.pdf.s_imagno) { if (NULL != gra->out.pdf.i_imagno) { dk4sto_it_close(gra->out.pdf.i_imagno); } dk4sto_close(gra->out.pdf.s_imagno); } gra->out.pdf.s_imagno = NULL; gra->out.pdf.i_imagno = NULL; /* Release pages */ if (NULL != gra->s_pages) { if (NULL != gra->i_pages) { dk4sto_it_reset(gra->i_pages); do { bptr = (dk4_gra_pdf_page_t *)dk4sto_it_next(gra->i_pages); if (NULL != bptr) { dk4gra_pgf_page_delete(bptr); } } while(NULL != bptr); dk4sto_it_close(gra->i_pages); } dk4sto_close(gra->s_pages); } gra->s_pages = NULL; gra->i_pages = NULL; gra->curpg = NULL; /* Release records for embedded images */ if (NULL != gra->out.pdf.s_images) { if (NULL != gra->out.pdf.i_images) { dk4sto_it_reset(gra->out.pdf.i_images); do { puxo = (dk4_gra_pdf_img_xo_t *)dk4sto_it_next( gra->out.pdf.i_images ); if (NULL != puxo) { dk4gra_pdf_xo_delete(puxo); } } while(NULL != puxo); dk4sto_it_close(gra->out.pdf.i_images); } dk4sto_close(gra->out.pdf.s_images); } gra->out.pdf.s_images = NULL; gra->out.pdf.i_images = NULL; /* Release file name and output structure itself */ dk4gratool_close(gra); finished: return; } dk4_gra_t * dk4gra_pdf_open( const dkChar *fn, size_t w, size_t h, int docfl, dk4_er_t *erp ) { dk4_gra_t *back = NULL; int ok = 0; #if DK4_USE_ASSERT assert(NULL != fn); #endif /* Generic initialization */ back = dk4gratool_open(fn, w, h, docfl, erp); if (NULL == back) { goto finished; } /* PDF specific initialization */ back->out.pdf.s_imagno = NULL; back->out.pdf.i_imagno = NULL; back->out.pdf.s_images = NULL; back->out.pdf.i_images = NULL; back->out.pdf.s_objpos = NULL; back->out.pdf.i_objpos = NULL; back->out.pdf.nextobj = 4; back->out.pdf.unxo = 0; /* Pages container and iterator */ back->s_pages = dk4sto_open(erp); if (NULL == back->s_pages) { goto finished; } (void)dk4sto_set_comp(back->s_pages, dk4gra_pdf_compare_pages_by_number, 0); back->i_pages = dk4sto_it_open(back->s_pages, erp); if (NULL == back->i_pages) { goto finished; } /* PDF XObject container and iterator for embedded images */ back->out.pdf.s_images = dk4sto_open(erp); if (NULL == back->out.pdf.s_images) { goto finished; } (void)dk4sto_set_comp(back->out.pdf.s_images, dk4gra_pdf_compare_xo, 0); back->out.pdf.i_images = dk4sto_it_open(back->out.pdf.s_images, erp); if (NULL == back->out.pdf.i_images) { goto finished; } /* PDF XObject container and iterator sorted by object number */ back->out.pdf.s_imagno = dk4sto_open(erp); if (NULL == back->out.pdf.s_imagno) { goto finished; } (void)dk4sto_set_comp(back->out.pdf.s_imagno,dk4gra_pdf_compare_used_xo,0); back->out.pdf.i_imagno = dk4sto_it_open(back->out.pdf.s_imagno, erp); if (NULL == back->out.pdf.i_imagno) { goto finished; } /* Storage and iterator for object start positions */ back->out.pdf.s_objpos = dk4sto_open(erp); if (NULL == back->out.pdf.s_objpos) { goto finished; } (void)dk4sto_set_comp(back->out.pdf.s_objpos, dk4gra_pdf_compare_objpos, 0); back->out.pdf.i_objpos = dk4sto_it_open(back->out.pdf.s_objpos, erp); if (NULL == back->out.pdf.i_objpos) { goto finished; } /* Finally indicate success */ ok = 1; /* Cleanup section, destroy object if errors occured */ finished: if ((NULL != back) && (0 == ok)) { dk4gra_pdf_close(back); back = NULL; } return back; } int dk4gra_pdf_write_file_and_close( FILE *fout, dk4_gra_t *gra, dk4_er_t *erp ) { int back = 0; #if DK4_USE_ASSERT assert(NULL != gra); assert(NULL != fout); #endif back = dk4gra_pdf_file(fout, gra, erp); dk4gra_pdf_close(gra); return back; } int dk4gra_pdf_page( dk4_gra_t *gra, int flags, dk4_er_t *erp ) { dk4_gra_pdf_page_t *curpg = NULL; int back = 0; #if DK4_USE_ASSERT assert(NULL != gra); #endif /* Check number of pages already defined */ if (SIZE_MAX == gra->pages) { dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW); goto finished; } curpg = dk4gra_pdf_page_new(gra->pages, gra, flags, erp); if (NULL == curpg) { goto finished; } if (0 == dk4sto_add(gra->s_pages, curpg, erp)) { dk4gra_pgf_page_delete(curpg); goto finished; } gra->curpg = curpg; gra->pages += 1; back = 1; finished: return back; } int dk4gra_pdf_gsave( dk4_gra_t *gra, dk4_er_t *erp ) { dk4_gra_pdf_page_t *bptr; int back = 0; #if DK4_USE_ASSERT assert(NULL != gra); #endif bptr = (dk4_gra_pdf_page_t *)(gra->curpg); if (NULL == bptr->outstrm) { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); goto finished; } back = 1; dk4gra_pdf_i_outstream_kw(bptr->outstrm, 2, &back, erp); finished: return back; } void dk4gra_pdf_i_gsave( dk4_gra_t *gra, int *backptr, dk4_er_t *erp ) { #if DK4_USE_ASSERT assert(NULL != gra); #endif if (0 == dk4gra_pdf_gsave(gra, erp)) { if (NULL != backptr) { *backptr = 0; } } } int dk4gra_pdf_grestore( dk4_gra_t *gra, dk4_er_t *erp ) { dk4_gra_pdf_page_t *bptr; int back = 0; #if DK4_USE_ASSERT assert(NULL != gra); #endif bptr = (dk4_gra_pdf_page_t *)(gra->curpg); if (NULL == bptr->outstrm) { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); goto finished; } back = 1; dk4gra_pdf_i_outstream_kw(bptr->outstrm, 3, &back, erp); finished: return back; } void dk4gra_pdf_i_grestore( dk4_gra_t *gra, int *backptr, dk4_er_t *erp ) { #if DK4_USE_ASSERT assert(NULL != gra); #endif if (0 == dk4gra_pdf_grestore(gra, erp)) { if (NULL != backptr) { *backptr = 0; } } } int dk4gra_pdf_set_line_width( dk4_gra_t *gra, double lw, dk4_er_t *erp ) { dk4_gra_pdf_page_t *bptr; int back = 0; #if DK4_USE_ASSERT assert(NULL != gra); #endif bptr = (dk4_gra_pdf_page_t *)(gra->curpg); if (NULL == bptr->outstrm) { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); goto finished; } back = 1; bptr->attr.lw_requested = lw; finished: return back; } int dk4gra_pdf_set_line_style( dk4_gra_t *gra, int ls, double sv, dk4_er_t *erp ) { dk4_gra_pdf_page_t *bptr; int back = 0; #if DK4_USE_ASSERT assert(NULL != gra); #endif bptr = (dk4_gra_pdf_page_t *)(gra->curpg); if (NULL == bptr->outstrm) { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); goto finished; } back = 1; bptr->attr.ls_requested = ls; bptr->attr.sv_requested = sv; finished: return back; } int dk4gra_pdf_set_line_cap( dk4_gra_t *gra, int lc, dk4_er_t *erp ) { dk4_gra_pdf_page_t *bptr; int back = 0; #if DK4_USE_ASSERT assert(NULL != gra); #endif bptr = (dk4_gra_pdf_page_t *)(gra->curpg); if (NULL == bptr->outstrm) { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); goto finished; } back = 1; bptr->attr.lc_requested = lc; finished: return back; } int dk4gra_pdf_set_line_join( dk4_gra_t *gra, int lj, double ml, dk4_er_t *erp ) { dk4_gra_pdf_page_t *bptr; int back = 0; #if DK4_USE_ASSERT assert(NULL != gra); #endif bptr = (dk4_gra_pdf_page_t *)(gra->curpg); if (NULL == bptr->outstrm) { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); goto finished; } back = 1; bptr->attr.lj_requested = lj; bptr->attr.ml_requested = ml; if (1.0 > bptr->attr.ml_requested) { bptr->attr.ml_requested = 1.0; back = 0; dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } finished: return back; } int dk4gra_pdf_set_fill_gray( dk4_gra_t *gra, double g, dk4_er_t *erp ) { dk4_gra_pdf_page_t *bptr; int back = 0; #if DK4_USE_ASSERT assert(NULL != gra); #endif bptr = (dk4_gra_pdf_page_t *)(gra->curpg); if (NULL == bptr->outstrm) { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); goto finished; } back = 1; bptr->attr.col_fill_requested.what = DK4_GRA_COL_SPEC_GRAY; bptr->attr.col_fill_requested.data.gray = g; finished: return back; } int dk4gra_pdf_set_fill_rgb( dk4_gra_t *gra, double r, double g, double b, dk4_er_t *erp ) { dk4_gra_pdf_page_t *bptr; int back = 0; #if DK4_USE_ASSERT assert(NULL != gra); #endif bptr = (dk4_gra_pdf_page_t *)(gra->curpg); if (NULL == bptr->outstrm) { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); goto finished; } back = 1; bptr->attr.col_fill_requested.what = DK4_GRA_COL_SPEC_RGB; bptr->attr.col_fill_requested.data.rgb.r = r; bptr->attr.col_fill_requested.data.rgb.g = g; bptr->attr.col_fill_requested.data.rgb.b = b; finished: return back; } int dk4gra_pdf_set_fill_cmyk( dk4_gra_t *gra, double c, double m, double y, double k, dk4_er_t *erp ) { dk4_gra_pdf_page_t *bptr; int back = 0; #if DK4_USE_ASSERT assert(NULL != gra); #endif bptr = (dk4_gra_pdf_page_t *)(gra->curpg); if (NULL == bptr->outstrm) { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); goto finished; } back = 1; bptr->attr.col_fill_requested.what = DK4_GRA_COL_SPEC_CMYK; bptr->attr.col_fill_requested.data.cmyk.c = c; bptr->attr.col_fill_requested.data.cmyk.m = m; bptr->attr.col_fill_requested.data.cmyk.y = y; bptr->attr.col_fill_requested.data.cmyk.k = k; finished: return back; } int dk4gra_pdf_set_stroke_gray( dk4_gra_t *gra, double g, dk4_er_t *erp ) { dk4_gra_pdf_page_t *bptr; int back = 0; #if DK4_USE_ASSERT assert(NULL != gra); #endif bptr = (dk4_gra_pdf_page_t *)(gra->curpg); if (NULL == bptr->outstrm) { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); goto finished; } back = 1; bptr->attr.col_stroke_requested.what = DK4_GRA_COL_SPEC_GRAY; bptr->attr.col_stroke_requested.data.gray = g; finished: return back; } int dk4gra_pdf_set_stroke_rgb( dk4_gra_t *gra, double r, double g, double b, dk4_er_t *erp ) { dk4_gra_pdf_page_t *bptr; int back = 0; #if DK4_USE_ASSERT assert(NULL != gra); #endif bptr = (dk4_gra_pdf_page_t *)(gra->curpg); if (NULL == bptr->outstrm) { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); goto finished; } back = 1; bptr->attr.col_stroke_requested.what = DK4_GRA_COL_SPEC_RGB; bptr->attr.col_stroke_requested.data.rgb.r = r; bptr->attr.col_stroke_requested.data.rgb.g = g; bptr->attr.col_stroke_requested.data.rgb.b = b; finished: return back; } int dk4gra_pdf_set_stroke_cmyk( dk4_gra_t *gra, double c, double m, double y, double k, dk4_er_t *erp ) { dk4_gra_pdf_page_t *bptr; int back = 0; #if DK4_USE_ASSERT assert(NULL != gra); #endif bptr = (dk4_gra_pdf_page_t *)(gra->curpg); if (NULL == bptr->outstrm) { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); goto finished; } back = 1; bptr->attr.col_stroke_requested.what = DK4_GRA_COL_SPEC_CMYK; bptr->attr.col_stroke_requested.data.cmyk.c = c; bptr->attr.col_stroke_requested.data.cmyk.m = m; bptr->attr.col_stroke_requested.data.cmyk.y = y; bptr->attr.col_stroke_requested.data.cmyk.k = k; finished: return back; } int dk4gra_pdf_prepare_fill( dk4_gra_t *gra, dk4_er_t *erp ) { dk4_gra_pdf_page_t *bptr; int back = 0; #if DK4_USE_ASSERT assert(NULL != gra); #endif bptr = (dk4_gra_pdf_page_t *)(gra->curpg); if (NULL == bptr->outstrm) { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); goto finished; } back = 1; dk4gra_pdf_set_color_if_necessary( bptr->outstrm, &(bptr->attr.col_fill_active), &(bptr->attr.col_fill_requested), 1, &back, erp ); finished: return back; } int dk4gra_pdf_prepare_stroke( dk4_gra_t *gra, dk4_er_t *erp ) { double da[16]; dk4_gra_pdf_page_t *bptr; double gw; int back = 0; int lwc = 0; #if DK4_USE_ASSERT assert(NULL != gra); #endif bptr = (dk4_gra_pdf_page_t *)(gra->curpg); if (NULL == bptr->outstrm) { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); goto finished; } back = 1; /* Stroke color */ dk4gra_pdf_set_color_if_necessary( bptr->outstrm, &(bptr->attr.col_stroke_active), &(bptr->attr.col_stroke_requested), 0, &back, erp ); /* Line width */ if ( DK4_GRA_EPSILON_LINEWIDTH < fabs(bptr->attr.lw_active - bptr->attr.lw_requested) ) { dk4gratool_stream_double( bptr->outstrm, bptr->attr.lw_requested, &back, erp ); dk4gra_pdf_i_outstream_kw(bptr->outstrm, 25, &back, erp); bptr->attr.lw_active = bptr->attr.lw_requested; lwc = 1; } /* Line style */ lwc = dk4gratool_line_style_differs( bptr->attr.ls_active, bptr->attr.ls_requested, bptr->attr.sv_active, bptr->attr.sv_requested, lwc ); if (0 != lwc) { gw = (bptr->attr.sv_requested + bptr->attr.lw_requested) / 2.0; if ((2.0 * bptr->attr.lw_requested) < gw) { gw = 2.0 * bptr->attr.lw_requested; } switch (bptr->attr.lc_requested) { case DK4_GRA_LC_ROUNDED : case DK4_GRA_LC_PROJECTING : { gw += bptr->attr.lw_requested; } break; } switch (bptr->attr.ls_requested) { case DK4_GRA_LS_DASH : { da[0] = bptr->attr.sv_requested; da[1] = gw; dk4gra_pdf_dash_out( bptr->outstrm, da, 2, (da[0] / 2.0), &back, erp ); } break; case DK4_GRA_LS_DOT : { da[0] = da[1] = bptr->attr.lw_requested; dk4gra_pdf_dash_out( bptr->outstrm, da, 2, (da[0] / 2.0), &back, erp ); } break; case DK4_GRA_LS_DASH_DOT : { da[0] = bptr->attr.sv_requested; da[1] = gw; da[2] = bptr->attr.lw_requested; da[3] = gw; dk4gra_pdf_dash_out( bptr->outstrm, da, 4, (da[0] / 2.0), &back, erp ); } break; case DK4_GRA_LS_DASH_DOT_DOT : { da[0] = bptr->attr.sv_requested; da[1] = gw; da[2] = bptr->attr.lw_requested; da[3] = gw; da[4] = bptr->attr.lw_requested; da[5] = gw; dk4gra_pdf_dash_out( bptr->outstrm, da, 6, (da[0] / 2.0), &back, erp ); } break; case DK4_GRA_LS_DASH_DOT_DOT_DOT : { da[0] = bptr->attr.sv_requested; da[1] = gw; da[2] = bptr->attr.lw_requested; da[3] = gw; da[4] = bptr->attr.lw_requested; da[5] = gw; da[6] = bptr->attr.lw_requested; da[7] = gw; dk4gra_pdf_dash_out( bptr->outstrm, da, 8, (da[0] / 2.0), &back, erp ); } break; default : { /* solid */ dk4gra_pdf_i_outstream_kw(bptr->outstrm, 32, &back, erp); } break; } bptr->attr.ls_active = bptr->attr.ls_requested; bptr->attr.sv_active = bptr->attr.sv_requested; } /* Line cap */ if (bptr->attr.lc_active != bptr->attr.lc_requested) { switch (bptr->attr.lc_requested) { case DK4_GRA_LC_ROUNDED : { /* 1 */ dk4gra_pdf_i_outstream_kw(bptr->outstrm, 27, &back, erp); } break; case DK4_GRA_LC_PROJECTING : { /* 2 */ dk4gra_pdf_i_outstream_kw(bptr->outstrm, 28, &back, erp); } break; default : { /* 0 */ dk4gra_pdf_i_outstream_kw(bptr->outstrm, 26, &back, erp); } break; } bptr->attr.lc_active = bptr->attr.lc_requested; } /* Line join */ if (bptr->attr.lj_active != bptr->attr.lj_requested) { switch (bptr->attr.lj_requested) { case DK4_GRA_LJ_ROUNDED : { /* 1 */ dk4gra_pdf_i_outstream_kw(bptr->outstrm, 30, &back, erp); } break; case DK4_GRA_LJ_BEVELED : { /* 2 */ dk4gra_pdf_i_outstream_kw(bptr->outstrm, 31, &back, erp); } break; default : { /* 0 */ dk4gra_pdf_i_outstream_kw(bptr->outstrm, 29, &back, erp); } break; } bptr->attr.lj_active = bptr->attr.lj_requested; } if (DK4_GRA_LJ_MITERED == bptr->attr.lj_active) { if ( DK4_GRA_EPSILON_MITERLIMIT < fabs(bptr->attr.ml_active - bptr->attr.ml_requested) ) { dk4gra_pdf_i_values_and_kw( bptr->outstrm, &(bptr->attr.ml_requested), 1, 84, &back, erp ); bptr->attr.ml_active = bptr->attr.ml_requested; } } finished: return back; } int dk4gra_pdf_prepare_fill_and_stroke( dk4_gra_t *gra, dk4_er_t *erp ) { int back = 0; #if DK4_USE_ASSERT assert(NULL != gra); #endif back = dk4gra_pdf_prepare_fill(gra, erp); if (0 == dk4gra_pdf_prepare_stroke(gra, erp)) { back = 0; } return back; } int dk4gra_pdf_fill( dk4_gra_t *gra, dk4_er_t *erp ) { dk4_gra_pdf_page_t *bptr; int back = 0; #if DK4_USE_ASSERT assert(NULL != gra); #endif bptr = (dk4_gra_pdf_page_t *)(gra->curpg); if (NULL == bptr->outstrm) { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); goto finished; } back = 1; dk4gra_pdf_i_outstream_kw( bptr->outstrm, ((0 != gra->eor) ? (10) : (9)), &back, erp ); finished: return back; } int dk4gra_pdf_stroke( dk4_gra_t *gra, dk4_er_t *erp ) { dk4_gra_pdf_page_t *bptr; int back = 0; #if DK4_USE_ASSERT assert(NULL != gra); #endif bptr = (dk4_gra_pdf_page_t *)(gra->curpg); if (NULL == bptr->outstrm) { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); goto finished; } back = 1; dk4gra_pdf_i_outstream_kw(bptr->outstrm, 8, &back, erp); finished: return back; } int dk4gra_pdf_fill_and_stroke( dk4_gra_t *gra, dk4_er_t *erp ) { dk4_gra_pdf_page_t *bptr; int back = 0; #if DK4_USE_ASSERT assert(NULL != gra); #endif bptr = (dk4_gra_pdf_page_t *)(gra->curpg); if (NULL == bptr->outstrm) { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); goto finished; } back = 1; dk4gra_pdf_i_outstream_kw( bptr->outstrm, ((0 != gra->eor) ? (12) : (11)), &back, erp ); finished: return back; } int dk4gra_pdf_clip( dk4_gra_t *gra, dk4_er_t *erp ) { dk4_gra_pdf_page_t *bptr; int back = 0; #if DK4_USE_ASSERT assert(NULL != gra); #endif bptr = (dk4_gra_pdf_page_t *)(gra->curpg); if (NULL == bptr->outstrm) { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); goto finished; } back = 1; dk4gra_pdf_i_outstream_kw( bptr->outstrm, ((0 != gra->eor) ? (14) : (13)), &back, erp ); finished: return back; } static void dk4gra_pdf_i_newpath_moveto( dk4_stream_t *os, double x, double y, int *backptr, dk4_er_t *erp ) { #if DK4_USE_ASSERT assert(NULL != os); #endif dk4gratool_stream_double(os, x, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 1, backptr, erp); dk4gratool_stream_double(os, y, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 4, backptr, erp); } static void dk4gra_pdf_i_lineto( dk4_stream_t *os, double x, double y, int *backptr, dk4_er_t *erp ) { #if DK4_USE_ASSERT assert(NULL != os); #endif dk4gratool_stream_double(os, x, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 1, backptr, erp); dk4gratool_stream_double(os, y, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 5, backptr, erp); } static void dk4gra_pdf_i_curveto( dk4_stream_t *os, double xc1, double yc1, double xc2, double yc2, double x, double y, int *backptr, dk4_er_t *erp ) { #if DK4_USE_ASSERT assert(NULL != os); #endif dk4gratool_stream_double(os, xc1, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 1, backptr, erp); dk4gratool_stream_double(os, yc1, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 1, backptr, erp); dk4gratool_stream_double(os, xc2, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 1, backptr, erp); dk4gratool_stream_double(os, yc2, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 1, backptr, erp); dk4gratool_stream_double(os, x, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 1, backptr, erp); dk4gratool_stream_double(os, y, backptr, erp); dk4gra_pdf_i_outstream_kw(os, 6, backptr, erp); } static void dk4gra_pdf_i_closepath( dk4_stream_t *os, int *backptr, dk4_er_t *erp ) { #if DK4_USE_ASSERT assert(NULL != os); #endif dk4gra_pdf_i_outstream_kw(os, 7, backptr, erp); } int dk4gra_pdf_newpath_moveto( dk4_gra_t *gra, double x, double y, dk4_er_t *erp ) { dk4_gra_pdf_page_t *bptr; int back = 0; #if DK4_USE_ASSERT assert(NULL != gra); #endif bptr = (dk4_gra_pdf_page_t *)(gra->curpg); if (NULL == bptr->outstrm) { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); goto finished; } back = 1; dk4gra_pdf_i_newpath_moveto(bptr->outstrm, x, y, &back, erp); finished: return back; } int dk4gra_pdf_lineto( dk4_gra_t *gra, double x, double y, dk4_er_t *erp ) { dk4_gra_pdf_page_t *bptr; int back = 0; #if DK4_USE_ASSERT assert(NULL != gra); #endif bptr = (dk4_gra_pdf_page_t *)(gra->curpg); if (NULL == bptr->outstrm) { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); goto finished; } back = 1; dk4gra_pdf_i_lineto(bptr->outstrm, x, y, &back, erp); finished: return back; } int dk4gra_pdf_curveto( dk4_gra_t *gra, double xc1, double yc1, double xc2, double yc2, double x, double y, dk4_er_t *erp ) { dk4_gra_pdf_page_t *bptr; int back = 0; #if DK4_USE_ASSERT assert(NULL != gra); #endif bptr = (dk4_gra_pdf_page_t *)(gra->curpg); if (NULL == bptr->outstrm) { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); goto finished; } back = 1; dk4gra_pdf_i_curveto( bptr->outstrm, xc1, yc1, xc2, yc2, x, y, &back, erp ); finished: return back; } int dk4gra_pdf_closepath( dk4_gra_t *gra, dk4_er_t *erp ) { dk4_gra_pdf_page_t *bptr; int back = 0; #if DK4_USE_ASSERT assert(NULL != gra); #endif bptr = (dk4_gra_pdf_page_t *)(gra->curpg); if (NULL == bptr->outstrm) { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); goto finished; } back = 1; dk4gra_pdf_i_closepath( bptr->outstrm, &back, erp ); finished: return back; } void dk4gra_pdf_save_attributes( dk4_gra_t *gra ) { dk4_gra_pdf_page_t *bptr; #if DK4_USE_ASSERT assert(NULL != gra); #endif bptr = (dk4_gra_pdf_page_t *)(gra->curpg); dk4mem_cpy( &(bptr->catt), &(bptr->attr), sizeof(dk4gra_attributes_t), NULL ); } void dk4gra_pdf_restore_attributes( dk4_gra_t *gra ) { dk4_gra_pdf_page_t *bptr; #if DK4_USE_ASSERT assert(NULL != gra); #endif bptr = (dk4_gra_pdf_page_t *)(gra->curpg); dk4mem_cpy( &(bptr->attr), &(bptr->catt), sizeof(dk4gra_attributes_t), NULL ); } void dk4gra_pdf_reset_attributes( dk4_gra_t *gra ) { dk4_gra_pdf_page_t *bptr; #if DK4_USE_ASSERT assert(NULL != gra); #endif bptr = (dk4_gra_pdf_page_t *)(gra->curpg); dk4gratool_reset_active_attributes(&(bptr->attr)); } /* vim: set ai sw=4 ts=4 : */