%% options copyright owner = Dirk Krause copyright year = 2020-xxxx SPDX-License-Identifier: BSD-3-Clause %% header /** @file WxdkdrawWrite.h Write drawing to file. */ #include "WxdkdrawTypes.h" /** Initialize a writer status structure. @param pstat Status structure to initialize. @param wxe Encoding for wxChar strings. */ void wxdwr_status_init(wxdwr_status_t *pstat, int wxe); /** Write drawing to file. @param fout Output file to write, opened for text writing. @param pdrw Drawing to write to file. @param pstat Writer status. @return 1 on success, 0 on error. */ int wxdwr_write_file(FILE *fout, Wxd_drawing_t *pdrw, wxdwr_status_t *pstat); %% module #include "wxdkdraw.h" $!trace-include /** Contant text fragments, not localized. */ static char const * const wxdwr_c8_kw[] = { $!string-table # # 0 Newline # \n # # 1 Space # # # 2 Keyword WXD for file recognition. # WXD # # 3 Numeric value 0 # 0 # # 4 Numeric value 1 # 1 # # 5 Zoom level # 0 2 # # 6 Borders # 0 4 # # 7 Grid unit # 0 5 1\n # # 8 Grid base # 0 6 1\n # # # $!end }; /** Indicate error condition in a status structure. The function does not overwrite existing error conditions, so the status reports the first error found. @param pstat Status structure to modify. @param ec Error code. @param s String we can not handle. */ static void wxdwr_status_set_error(wxdwr_status_t *pstat, int ec, wxChar *s) { if (NULL != pstat) { if (WXDWR_E_NONE == pstat->ec) { pstat->ec = ec; pstat->str = s; } } } /** Write char string to output file. @param fout Output file. @param str String to write. @param bptr Address of success variable to reset on error. @param pstat Status structure for error notification. */ static void wxdwr_out_string_c8( FILE *fout, char const *str, int *bptr, wxdwr_status_t *pstat ) { if (EOF == fputs(str, fout)) { *bptr = 0; wxdwr_status_set_error(pstat, WXDWR_E_WRITE, NULL); } } /** Write unsigned number to output file. @param fout Output file. @param um Unsigned value to write. @param bptr Address of success variable to reset on error. @param pstat Status structure for error notification. */ static void wxdwr_out_unsigned( FILE *fout, dk4_um_t um, int *bptr, wxdwr_status_t *pstat ) { char buf[16*sizeof(dk4_um_t)]; size_t const szbuf = DK4_SIZEOF(buf,char); (void)dk4ma_write_c8_decimal_unsigned(buf, szbuf, um, 0, NULL); wxdwr_out_string_c8(fout, buf, bptr, pstat); } /** Write signed integer value to output file. @param fout Output file. @param im Integer value to write. @param bptr Address of success variable to reset on error. @param pstat Status structure for error notification. */ static void wxdwr_out_signed( FILE *fout, dk4_im_t im, int *bptr, wxdwr_status_t *pstat ) { char buf[16*sizeof(dk4_um_t)]; size_t const szbuf = DK4_SIZEOF(buf,char); (void)dk4ma_write_c8_decimal_signed(buf, szbuf, im, 0, NULL); wxdwr_out_string_c8(fout, buf, bptr, pstat); } /** Write double value to output file. @param fout Output file. @param dbl Value to write. @param bptr Address of success variable to reset on error. @param pstat Status structure for error notification. */ static void wxdwr_out_double( FILE *fout, double dbl, int *bptr, wxdwr_status_t *pstat ) { char buf[32*sizeof(double)]; size_t const szbuf = DK4_SIZEOF(buf,char); (void)dk4ma_write_c8_double(buf, szbuf, dbl, 0, 1, NULL); wxdwr_out_string_c8(fout, buf, bptr, pstat); } /** Write first line for a drawing to output file. @param fout Output file. @param pdrw Drawing. @param bptr Address of success variable to reset on error. @param pstat Status structure for error notification. */ static void wxdwr_write_first_line( FILE *fout, Wxd_drawing_t *pdrw, int *bptr, wxdwr_status_t *pstat ) { wxdwr_out_string_c8(fout, wxdwr_c8_kw[2], bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_unsigned(fout, pdrw->fv_maj, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_unsigned(fout, pdrw->fv_min, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[0], bptr, pstat); } /** Write bounding box for a drawing to output file. @param fout Output file. @param pdrw Drawing. @param bptr Address of success variable to reset on error. @param pstat Status structure for error notification. */ static void wxdwr_write_bounding_box( FILE *fout, Wxd_drawing_t *pdrw, int *bptr, wxdwr_status_t *pstat ) { wxdwr_out_string_c8(fout, wxdwr_c8_kw[3], bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[3], bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_signed(fout, (pdrw->bb).xl, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_signed(fout, (pdrw->bb).xr, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_signed(fout, (pdrw->bb).yb, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_signed(fout, (pdrw->bb).yt, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[0], bptr, pstat); } /** Write base line width for a drawing to output file if necessary. @param fout Output file. @param pdrw Drawing. @param bptr Address of success variable to reset on error. @param pstat Status structure for error notification. */ static void wxdwr_write_base_line_width( FILE *fout, Wxd_drawing_t *pdrw, int *bptr, wxdwr_status_t *pstat ) { if (101600UL != (unsigned long)(pdrw->baselw)) { wxdwr_out_string_c8(fout, wxdwr_c8_kw[3], bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[4], bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_unsigned(fout, pdrw->baselw, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[0], bptr, pstat); } } /** Write zoom level for a drawing to output file if necessary. @param fout Output file. @param pdrw Drawing. @param bptr Address of success variable to reset on error. @param pstat Status structure for error notification. */ static void wxdwr_write_zoom_level( FILE *fout, Wxd_drawing_t *pdrw, int *bptr, wxdwr_status_t *pstat ) { if (0 != (int)(pdrw->zl)) { wxdwr_out_string_c8(fout, wxdwr_c8_kw[5], bptr, pstat); wxdwr_out_signed(fout, pdrw->zl, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[0], bptr, pstat); } } /** Write grid unit and grid base for a drawing to output file if necessary. @param fout Output file. @param pdrw Drawing. @param bptr Address of success variable to reset on error. @param pstat Status structure for error notification. */ static void wxdwr_write_grid_unit_and_base( FILE *fout, Wxd_drawing_t *pdrw, int *bptr, wxdwr_status_t *pstat ) { if ((uint8_t)0U != pdrw->gridunit) { wxdwr_out_string_c8(fout, wxdwr_c8_kw[7], bptr, pstat); } if ((uint8_t)0U != pdrw->gridbase) { wxdwr_out_string_c8(fout, wxdwr_c8_kw[8], bptr, pstat); } } /** Write 5 style attributes for a graphics object to file. @param fout Output file. @param pdrw Drawing. @param pobj Object to handle. @param bptr Address of success variable to reset on error. @param pstat Status structure for error notification. */ static void wxdwr_write_elements_05( FILE *fout, Wxd_object_t *pobj, int *bptr, wxdwr_status_t *pstat ) { wxdwr_out_signed(fout, pobj->ot, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_signed(fout, pobj->lay, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); switch ( (int)(pobj->ot) ) { case WXD_OT_DOT_WHITE : case WXD_OT_DOT_FILLED : case WXD_OT_TEXT : { wxdwr_out_unsigned(fout, pobj->sc[0], bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_unsigned(fout, pobj->sc[1], bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_unsigned(fout, pobj->sc[2], bptr, pstat); } break; default : { wxdwr_out_unsigned(fout, pobj->fc[0], bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_unsigned(fout, pobj->fc[1], bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_unsigned(fout, pobj->fc[2], bptr, pstat); } break; } wxdwr_out_string_c8(fout, wxdwr_c8_kw[0], bptr, pstat); } /** Write 12 style attributes for a graphics object to file. @param fout Output file. @param pdrw Drawing. @param pobj Object to handle. @param bptr Address of success variable to reset on error. @param pstat Status structure for error notification. */ static void wxdwr_write_elements_12( FILE *fout, Wxd_object_t *pobj, int *bptr, wxdwr_status_t *pstat ) { /* object type */ wxdwr_out_signed(fout, pobj->ot, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* layer */ wxdwr_out_signed(fout, pobj->lay, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* stroke red */ wxdwr_out_unsigned(fout, pobj->sc[0], bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* stroke green */ wxdwr_out_unsigned(fout, pobj->sc[1], bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* stroke blue */ wxdwr_out_unsigned(fout, pobj->sc[2], bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* fill red */ wxdwr_out_unsigned(fout, pobj->fc[0], bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* fill green */ wxdwr_out_unsigned(fout, pobj->fc[1], bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* fill blue */ wxdwr_out_unsigned(fout, pobj->fc[2], bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* line width */ wxdwr_out_unsigned(fout, pobj->lw, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* line style */ wxdwr_out_unsigned(fout, pobj->ls, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* style value */ wxdwr_out_unsigned(fout, pobj->sl, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* fill style */ wxdwr_out_unsigned(fout, pobj->fs, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[0], bptr, pstat); } /** Write 15 style attributes for a graphics object to file. @param fout Output file. @param pdrw Drawing. @param pobj Object to handle. @param bptr Address of success variable to reset on error. @param pstat Status structure for error notification. */ static void wxdwr_write_elements_15( FILE *fout, Wxd_object_t *pobj, int *bptr, wxdwr_status_t *pstat ) { /* object type */ wxdwr_out_signed(fout, pobj->ot, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* number of points */ switch ( (int)(pobj->ot) ) { case WXD_OT_POLYLINE : case WXD_OT_POLYGON : { wxdwr_out_unsigned(fout, (pobj->det).p.n, bptr, pstat); } break; default : { wxdwr_out_unsigned(fout, (pobj->det).s.n, bptr, pstat); } break; } wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* layer */ wxdwr_out_signed(fout, pobj->lay, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* stroke red */ wxdwr_out_unsigned(fout, pobj->sc[0], bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* stroke green */ wxdwr_out_unsigned(fout, pobj->sc[1], bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* stroke blue */ wxdwr_out_unsigned(fout, pobj->sc[2], bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* fill red */ wxdwr_out_unsigned(fout, pobj->fc[0], bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* fill green */ wxdwr_out_unsigned(fout, pobj->fc[1], bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* fill blue */ wxdwr_out_unsigned(fout, pobj->fc[2], bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* line width */ wxdwr_out_unsigned(fout, pobj->lw, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* line style */ wxdwr_out_unsigned(fout, pobj->ls, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* style value */ wxdwr_out_unsigned(fout, pobj->sl, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* join style */ wxdwr_out_unsigned(fout, pobj->js, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* miter limit */ wxdwr_out_unsigned(fout, pobj->ml, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* fill style */ wxdwr_out_unsigned(fout, pobj->fs, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[0], bptr, pstat); } /** Write 18 style attributes for a graphics object to file. @param fout Output file. @param pdrw Drawing. @param pobj Object to handle. @param bptr Address of success variable to reset on error. @param pstat Status structure for error notification. */ static void wxdwr_write_elements_18( FILE *fout, Wxd_object_t *pobj, int *bptr, wxdwr_status_t *pstat ) { /* object type */ wxdwr_out_signed(fout, pobj->ot, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* number of points */ switch ( (int)(pobj->ot) ) { case WXD_OT_POLYLINE : case WXD_OT_POLYGON : { wxdwr_out_unsigned(fout, (pobj->det).p.n, bptr, pstat); } break; default : { wxdwr_out_unsigned(fout, (pobj->det).s.n, bptr, pstat); } break; } wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* layer */ wxdwr_out_signed(fout, pobj->lay, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* stroke red */ wxdwr_out_unsigned(fout, pobj->sc[0], bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* stroke green */ wxdwr_out_unsigned(fout, pobj->sc[1], bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* stroke blue */ wxdwr_out_unsigned(fout, pobj->sc[2], bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* line width */ wxdwr_out_unsigned(fout, pobj->lw, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* line style */ wxdwr_out_unsigned(fout, pobj->ls, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* style value */ wxdwr_out_unsigned(fout, pobj->sl, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* cap style */ wxdwr_out_unsigned(fout, pobj->cs, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* join style */ wxdwr_out_unsigned(fout, pobj->js, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* miter limit */ wxdwr_out_unsigned(fout, pobj->ml, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* arrow type */ wxdwr_out_unsigned(fout, pobj->aft, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* arrow length */ wxdwr_out_unsigned(fout, pobj->afl, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* arrow width */ wxdwr_out_unsigned(fout, pobj->afw, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* arrow type */ wxdwr_out_unsigned(fout, pobj->abt, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* arrow length */ wxdwr_out_unsigned(fout, pobj->abl, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* arrow width */ wxdwr_out_unsigned(fout, pobj->abw, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[0], bptr, pstat); } /** Write text label to output file. @param fout Output file. @param pdrw Drawing. @param pobj Object to handle. @param bptr Address of success variable to reset on error. @param pstat Status structure for error notification. */ static void wxdwr_write_text_label( FILE *fout, Wxd_object_t *pobj, int *bptr, wxdwr_status_t *pstat ) { char bte[1024]; char bts[1024]; size_t const szbte = DK4_SIZEOF(bte,char); size_t const szbts = DK4_SIZEOF(bts,char); int canrun = 1; int res; #if 0 /* 2020-03-24 Modification Turned into an initialization due to clang static analyzers complaints about dead assignment. */ canrun = 1; #endif bte[0] = '\0'; bts[0] = '\0'; if (NULL != (pobj->det).t.t) { res = dk4recwx_wxchar_to_char( bte, szbte, DK4_ENCODING_UTF8, (pobj->det).t.t, pstat->wxe, NULL ); if (0 != res) { if (1022 > strlen(bte)) { canrun = 1; if (NULL != (pobj->det).t.tsc) { res = dk4recwx_wxchar_to_char( bts, szbts, DK4_ENCODING_UTF8, (pobj->det).t.tsc, pstat->wxe, NULL ); if (0 != res) { if (1021 < strlen(bts)) { canrun = 0; /* ERROR: String too long */ wxdwr_status_set_error( pstat, WXDWR_E_STRING_TOO_LONG, (pobj->det).t.t ); } } else { canrun = 0; /* ERROR: Encoding failed */ wxdwr_status_set_error( pstat, WXDWR_E_RECODE_TEXT, (pobj->det).t.t ); } } if (0 != canrun) { wxdwr_write_elements_05(fout, pobj, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_unsigned(fout, (pobj->det).t.find, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_unsigned(fout, (pobj->det).t.fsz, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_unsigned(fout, (pobj->det).t.al, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_unsigned(fout, (pobj->det).t.fl, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_signed(fout, (pobj->det).t.x, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_signed(fout, (pobj->det).t.y, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_signed(fout, (pobj->det).t.a, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[0], bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_string_c8(fout, bte, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[0], bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); if (NULL != (pobj->det).t.tsc) { wxdwr_out_string_c8(fout, bts, bptr, pstat); } wxdwr_out_string_c8(fout, wxdwr_c8_kw[0], bptr, pstat); } } else { /* ERROR: String too long */ wxdwr_status_set_error( pstat, WXDWR_E_STRING_TOO_LONG, (pobj->det).t.t ); } } else { /* ERROR: Encoding failed */ wxdwr_status_set_error(pstat, WXDWR_E_RECODE_TEXT, (pobj->det).t.t); } } else { /* ERROR: No text. */ wxdwr_status_set_error(pstat, WXDWR_E_STRING_EMPTY, NULL); } } /** Write polygon or polyline to output file. @param fout Output file. @param pdrw Drawing. @param pobj Object to handle. @param bptr Address of success variable to reset on error. @param pstat Status structure for error notification. */ static void wxdwr_write_polyline( FILE *fout, Wxd_object_t *pobj, int *bptr, wxdwr_status_t *pstat ) { uint16_t u; if (WXD_OT_POLYLINE == pobj->ot) { wxdwr_write_elements_18(fout, pobj, bptr, pstat); } else { wxdwr_write_elements_15(fout, pobj, bptr, pstat); } for (u = 0; u < (pobj->det).p.n; u++) { wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_signed(fout, ((pobj->det).p.p)[u].x, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_signed(fout, ((pobj->det).p.p)[u].y, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[0], bptr, pstat); } } /** Write spline to output file. @param fout Output file. @param pdrw Drawing. @param pobj Object to handle. @param bptr Address of success variable to reset on error. @param pstat Status structure for error notification. */ static void wxdwr_write_spline( FILE *fout, Wxd_object_t *pobj, int *bptr, wxdwr_status_t *pstat ) { uint16_t u; if (WXD_OT_O_SPLINE == pobj->ot) { wxdwr_write_elements_18(fout, pobj, bptr, pstat); } else { wxdwr_write_elements_15(fout, pobj, bptr, pstat); } for (u = 0; u < (pobj->det).s.n; u++) { wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_signed(fout, ((pobj->det).s.p)[u].x, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_signed(fout, ((pobj->det).s.p)[u].y, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_double(fout, ((pobj->det).s.p)[u].s, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[0], bptr, pstat); } } /** Write arc to output file. @param fout Output file. @param pdrw Drawing. @param pobj Object to handle. @param bptr Address of success variable to reset on error. @param pstat Status structure for error notification. */ static void wxdwr_write_arc( FILE *fout, Wxd_object_t *pobj, int *bptr, wxdwr_status_t *pstat ) { /* object type */ wxdwr_out_signed(fout, pobj->ot, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* layer */ wxdwr_out_signed(fout, pobj->lay, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* stroke red */ wxdwr_out_unsigned(fout, pobj->sc[0], bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* stroke green */ wxdwr_out_unsigned(fout, pobj->sc[1], bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* stroke blue */ wxdwr_out_unsigned(fout, pobj->sc[2], bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); if (WXD_OT_O_ARC == pobj->ot) { /* line width */ wxdwr_out_unsigned(fout, pobj->lw, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* line style */ wxdwr_out_unsigned(fout, pobj->ls, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* style value */ wxdwr_out_unsigned(fout, pobj->sl, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* cap style */ wxdwr_out_unsigned(fout, pobj->cs, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* arrow type */ wxdwr_out_unsigned(fout, pobj->aft, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* arrow length */ wxdwr_out_unsigned(fout, pobj->afl, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* arrow width */ wxdwr_out_unsigned(fout, pobj->afw, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* arrow type */ wxdwr_out_unsigned(fout, pobj->abt, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* arrow length */ wxdwr_out_unsigned(fout, pobj->abl, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* arrow width */ wxdwr_out_unsigned(fout, pobj->abw, bptr, pstat); } else { /* fill red */ wxdwr_out_unsigned(fout, pobj->fc[0], bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* fill green */ wxdwr_out_unsigned(fout, pobj->fc[1], bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* fill blue */ wxdwr_out_unsigned(fout, pobj->fc[2], bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* line width */ wxdwr_out_unsigned(fout, pobj->lw, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* line style */ wxdwr_out_unsigned(fout, pobj->ls, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* style value */ wxdwr_out_unsigned(fout, pobj->sl, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* join style */ wxdwr_out_unsigned(fout, pobj->js, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* miter limit */ wxdwr_out_unsigned(fout, pobj->ml, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* fill style */ wxdwr_out_unsigned(fout, pobj->fs, bptr, pstat); } wxdwr_out_string_c8(fout, wxdwr_c8_kw[0], bptr, pstat); /* second line: 3 point coordinates */ wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_signed(fout, (pobj->det).a.x1, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_signed(fout, (pobj->det).a.y1, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_signed(fout, (pobj->det).a.x2, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_signed(fout, (pobj->det).a.y2, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_signed(fout, (pobj->det).a.x3, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_signed(fout, (pobj->det).a.y3, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[0], bptr, pstat); } /** Write circle to output file. @param fout Output file. @param pdrw Drawing. @param pobj Object to handle. @param bptr Address of success variable to reset on error. @param pstat Status structure for error notification. */ static void wxdwr_write_circle( FILE *fout, Wxd_object_t *pobj, int *bptr, wxdwr_status_t *pstat ) { wxdwr_write_elements_12(fout, pobj, bptr, pstat); /* Second line */ wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_signed(fout, (pobj->det).e.x, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_signed(fout, (pobj->det).e.y, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_unsigned(fout, (pobj->det).e.rx, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[0], bptr, pstat); } /** Write ellipse to output file. @param fout Output file. @param pdrw Drawing. @param pobj Object to handle. @param bptr Address of success variable to reset on error. @param pstat Status structure for error notification. */ static void wxdwr_write_ellipse( FILE *fout, Wxd_object_t *pobj, int *bptr, wxdwr_status_t *pstat ) { wxdwr_write_elements_12(fout, pobj, bptr, pstat); /* Second line */ wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_signed(fout, (pobj->det).e.x, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_signed(fout, (pobj->det).e.y, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_unsigned(fout, (pobj->det).e.rx, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_unsigned(fout, (pobj->det).e.ry, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_signed(fout, (pobj->det).e.a, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[0], bptr, pstat); } /** Write box to output file. @param fout Output file. @param pdrw Drawing. @param pobj Object to handle. @param bptr Address of success variable to reset on error. @param pstat Status structure for error notification. */ static void wxdwr_write_box( FILE *fout, Wxd_object_t *pobj, int *bptr, wxdwr_status_t *pstat ) { wxdwr_write_elements_12(fout, pobj, bptr, pstat); /* Second line */ wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_signed(fout, (pobj->det).b.b.xl, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_signed(fout, (pobj->det).b.b.xr, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_signed(fout, (pobj->det).b.b.yb, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_signed(fout, (pobj->det).b.b.yt, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_unsigned(fout, (pobj->det).b.r, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[0], bptr, pstat); } /** Calculate difference of 2 int32_t values as uint32_t value. @param xl Smaller number. @param xr Larger number. @return Result (large - small number). */ static uint32_t wxdwr_diff_signed(int32_t xl, int32_t xr) { dk4_er_t er; uint32_t back = 0UL; int32_t axl; if (0L <= xr) { if (0L <= xl) { back = (uint32_t)(xr - xl); } else { dk4error_init(&er); axl = dk4ma_int32_t_abs(xl, &er); if (DK4_E_NONE == er.ec) { back = (uint32_t)xr + (uint32_t)axl; } else { back = (uint32_t)xr + (uint32_t)(DK4_I32_MAX) + (uint32_t)1UL; } } } else { if (0L <= xl) { back = wxdwr_diff_signed(xr, xl); } else { back = (uint32_t)(xr - xl); } } return back; } /** Write image object to output file. @param fout Output file. @param pdrw Drawing. @param pobj Object to handle. @param bptr Address of success variable to reset on error. @param pstat Status structure for error notification. */ static void wxdwr_write_image( FILE *fout, Wxd_object_t *pobj, int *bptr, wxdwr_status_t *pstat ) { char bfn[1024]; wxChar *fnco; /* File name to convert */ size_t const szbfn = DK4_SIZEOF(bfn,char); int32_t x; int32_t y; uint32_t w; uint32_t h; int res; $? "+ wxdwr_write_image" if (NULL != (pobj->det).i.fn) { fnco = (pobj->det).i.fn; #if TRACE_DEBUG #if DK4_SIZEOF_WXCHAR > 1 $? ". (1) \"%!ws\"", fnco #else $? ". (1) \"%s\"", fnco #endif #endif if (NULL != pstat->dirn) { if (0 != dk4strx_path_is_in_subdir(fnco, pstat->dirn, NULL)) { fnco = &(fnco[dk4strx_len(pstat->dirn) + (size_t)1U]); } } #if TRACE_DEBUG #if DK4_SIZEOF_WXCHAR > 1 $? ". (2) \"%!ws\"", fnco #else $? ". (2) \"%s\"", fnco #endif #endif res = dk4recwx_wxchar_to_char( bfn, szbfn, DK4_ENCODING_UTF8, fnco, pstat->wxe, NULL ); if (0 != res) { if (1022 > strlen(bfn)) { if ((pobj->det).i.br.xr >= (pobj->det).i.br.xl) { x = (pobj->det).i.br.xl; w = wxdwr_diff_signed( (pobj->det).i.br.xl, (pobj->det).i.br.xr ); } else { x = (pobj->det).i.br.xr; w = wxdwr_diff_signed( (pobj->det).i.br.xr, (pobj->det).i.br.xl ); } if ((pobj->det).i.br.yt >= (pobj->det).i.br.yb) { y = (pobj->det).i.br.yb; h = wxdwr_diff_signed( (pobj->det).i.br.yb, (pobj->det).i.br.yt ); } else { y = (pobj->det).i.br.yt; h = wxdwr_diff_signed( (pobj->det).i.br.yt, (pobj->det).i.br.yb ); } /* First line */ wxdwr_write_elements_05(fout, pobj, bptr, pstat); /* Second line */ wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* flags */ wxdwr_out_unsigned(fout, (pobj->det).i.fl, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* rgb2gray */ wxdwr_out_signed(fout, (pobj->det).i.r2g, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* rgb2cmyk */ wxdwr_out_signed(fout, (pobj->det).i.r2c, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* x */ wxdwr_out_signed(fout, x, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* y */ wxdwr_out_signed(fout, y, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* w */ wxdwr_out_signed(fout, w, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* h */ wxdwr_out_signed(fout, h, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[0], bptr, pstat); /* Third line */ wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_string_c8(fout, bfn, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[0], bptr, pstat); } else { wxdwr_status_set_error( pstat, WXDWR_E_STRING_TOO_LONG, (pobj->det).i.fn ); } } else { wxdwr_status_set_error( pstat, WXDWR_E_RECODE_FILENAME, (pobj->det).i.fn ); } } else { $? "! empty" } $? "- wxdwr_write_image" } /** Write dot to output file. @param fout Output file. @param pdrw Drawing. @param pobj Object to handle. @param bptr Address of success variable to reset on error. @param pstat Status structure for error notification. */ static void wxdwr_write_dot( FILE *fout, Wxd_object_t *pobj, int *bptr, wxdwr_status_t *pstat ) { wxdwr_write_elements_05(fout, pobj, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* x */ wxdwr_out_signed(fout, (pobj->det).d.x, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* y */ wxdwr_out_signed(fout, (pobj->det).d.y, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); /* d */ wxdwr_out_unsigned(fout, (pobj->det).d.d, bptr, pstat); if (WXD_OT_DOT_WHITE == pobj->ot) { /* l */ wxdwr_out_string_c8(fout, wxdwr_c8_kw[1], bptr, pstat); wxdwr_out_unsigned(fout, pobj->lw, bptr, pstat); } wxdwr_out_string_c8(fout, wxdwr_c8_kw[0], bptr, pstat); } /** Write graphics object to output file. @param fout Output file. @param pdrw Drawing. @param pobj Object to handle. @param bptr Address of success variable to reset on error. @param pstat Status structure for error notification. */ static void wxdwr_write_object( FILE *fout, Wxd_object_t *pobj, int *bptr, wxdwr_status_t *pstat ) { switch ( (int)(pobj->ot) ) { case WXD_OT_TEXT : { wxdwr_write_text_label(fout, pobj, bptr, pstat); } break; case WXD_OT_POLYLINE : case WXD_OT_POLYGON : { wxdwr_write_polyline(fout, pobj, bptr, pstat); } break; case WXD_OT_O_SPLINE : case WXD_OT_C_SPLINE : { wxdwr_write_spline(fout, pobj, bptr, pstat); } break; case WXD_OT_O_ARC : case WXD_OT_C_ARC : { wxdwr_write_arc(fout, pobj, bptr, pstat); } break; case WXD_OT_CIRCLE : { wxdwr_write_circle(fout, pobj, bptr, pstat); } break; case WXD_OT_ELLIPSE : { wxdwr_write_ellipse(fout, pobj, bptr, pstat); } break; case WXD_OT_BOX : { wxdwr_write_box(fout, pobj, bptr, pstat); } break; case WXD_OT_IMAGE : { wxdwr_write_image(fout, pobj, bptr, pstat); } break; case WXD_OT_DOT_FILLED : { wxdwr_write_dot(fout, pobj, bptr, pstat); } break; case WXD_OT_DOT_WHITE : { wxdwr_write_dot(fout, pobj, bptr, pstat); } break; } } static void wxdwr_write_group_structure( FILE *fout, Wxd_object_t *proot, int *bptr, wxdwr_status_t *pstat ) { Wxd_object_t *pgrp; Wxd_object_t *pobj; pgrp = proot; dk4sto_it_reset((pgrp->det).g.i_e); wxdwr_out_signed(fout, WXD_OT_GROUP_BEGIN, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[0], bptr, pstat); while (NULL != pgrp) { pobj = (Wxd_object_t *)dk4sto_it_next((pgrp->det).g.i_e); if (NULL != pobj) { if (WXD_OT_GROUP_BEGIN == pobj->ot) { if (NULL != (pobj->det).g.i_e) { dk4sto_it_reset((pobj->det).g.i_e); pgrp = pobj; wxdwr_out_signed(fout, WXD_OT_GROUP_BEGIN, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[0], bptr, pstat); } } else { wxdwr_write_object(fout, pobj, bptr, pstat); } } else { pgrp = pgrp->pa; wxdwr_out_signed(fout, WXD_OT_GROUP_END, bptr, pstat); wxdwr_out_string_c8(fout, wxdwr_c8_kw[0], bptr, pstat); } } } int wxdwr_write_file(FILE *fout, Wxd_drawing_t *pdrw, wxdwr_status_t *pstat) { Wxd_object_t *pgrp; int back = 1; if ((NULL != fout) && (NULL != pdrw)) { wxdwr_write_first_line(fout, pdrw, &back, pstat); wxdwr_write_bounding_box(fout, pdrw, &back, pstat); wxdwr_write_base_line_width(fout, pdrw, &back, pstat); wxdwr_write_zoom_level(fout, pdrw, &back, pstat); wxdwr_write_grid_unit_and_base(fout, pdrw, &back, pstat); dk4sto_it_reset(pdrw->i_stru); do { pgrp = (Wxd_object_t *)dk4sto_it_next(pdrw->i_stru); if (NULL != pgrp) { if (WXD_OT_GROUP_BEGIN == pgrp->ot) { wxdwr_write_group_structure(fout, pgrp, &back, pstat); } else { wxdwr_write_object(fout, pgrp, &back, pstat); } } } while (NULL != pgrp); } return back; } void wxdwr_status_init(wxdwr_status_t *pstat, int wxe) { if (NULL != pstat) { pstat->ec = WXDWR_E_NONE; pstat->wxe = wxe; pstat->str = NULL; pstat->dirn = NULL; } } /* vim: set ai sw=4 ts=4 : */