From ef288ea4aa607f91eecb2f58a57714b3f923167a Mon Sep 17 00:00:00 2001 From: ulferikson Date: Sun, 25 Nov 2007 21:33:44 +0000 Subject: [PATCH] Export/Import text as text + some bug-fixes. --- src/extension/internal/emf-win32-inout.cpp | 372 +++++++++++++++++++-- src/extension/internal/emf-win32-print.cpp | 183 +++++++++- src/extension/internal/emf-win32-print.h | 9 +- 3 files changed, 522 insertions(+), 42 deletions(-) diff --git a/src/extension/internal/emf-win32-inout.cpp b/src/extension/internal/emf-win32-inout.cpp index 6e008b754..7c0d7e724 100644 --- a/src/extension/internal/emf-win32-inout.cpp +++ b/src/extension/internal/emf-win32-inout.cpp @@ -155,16 +155,16 @@ EmfWin32::save (Inkscape::Extension::Output *mod, SPDocument *doc, const gchar * if (ext == NULL) return; -// bool old_textToPath = ext->get_param_bool("textToPath"); -// bool new_val = mod->get_param_bool("textToPath"); -// ext->set_param_bool("textToPath", new_val); + bool old_textToPath = ext->get_param_bool("textToPath"); + bool new_val = mod->get_param_bool("textToPath"); + ext->set_param_bool("textToPath", new_val); gchar * final_name; final_name = g_strdup_printf("%s", uri); emf_print_document_to_file(doc, final_name); g_free(final_name); -// ext->set_param_bool("textToPath", old_textToPath); + ext->set_param_bool("textToPath", old_textToPath); return; } @@ -180,9 +180,11 @@ typedef struct emf_callback_data { Glib::ustring *outsvg; Glib::ustring *path; struct SPStyle style; + class SPTextStyle tstyle; bool stroke_set; bool fill_set; double xDPI, yDPI; + bool pathless_stroke; SIZEL sizeWnd; SIZEL sizeView; @@ -207,35 +209,43 @@ output_style(PEMF_CALLBACK_DATA d, int iType) SVGOStringStream tmp_style; char tmp[1024] = {0}; + float fill_rgb[3]; + sp_color_get_rgb_floatv( &(d->style.fill.value.color), fill_rgb ); + + float stroke_rgb[3]; + sp_color_get_rgb_floatv(&(d->style.stroke.value.color), stroke_rgb); + *(d->outsvg) += "\n\tstyle=\""; if (iType == EMR_STROKEPATH || !d->fill_set) { tmp_style << "fill:none;"; } else { - float rgb[3]; - sp_color_get_rgb_floatv( &(d->style.fill.value.color), rgb ); snprintf(tmp, 1023, "fill:#%02x%02x%02x;", - SP_COLOR_F_TO_U(rgb[0]), - SP_COLOR_F_TO_U(rgb[1]), - SP_COLOR_F_TO_U(rgb[2])); + SP_COLOR_F_TO_U(fill_rgb[0]), + SP_COLOR_F_TO_U(fill_rgb[1]), + SP_COLOR_F_TO_U(fill_rgb[2])); tmp_style << tmp; snprintf(tmp, 1023, "fill-rule:%s;", d->style.fill_rule.value != 0 ? "evenodd" : "nonzero"); tmp_style << tmp; tmp_style << "fill-opacity:1;"; + + if (d->fill_set && d->stroke_set && d->style.stroke_width.value == 1 && + fill_rgb[0]==stroke_rgb[0] && fill_rgb[1]==stroke_rgb[1] && fill_rgb[2]==stroke_rgb[2]) + { + d->stroke_set = false; + } } if (iType == EMR_FILLPATH || !d->stroke_set) { tmp_style << "stroke:none;"; } else { - float rgb[3]; - sp_color_get_rgb_floatv(&(d->style.stroke.value.color), rgb); snprintf(tmp, 1023, "stroke:#%02x%02x%02x;", - SP_COLOR_F_TO_U(rgb[0]), - SP_COLOR_F_TO_U(rgb[1]), - SP_COLOR_F_TO_U(rgb[2])); + SP_COLOR_F_TO_U(stroke_rgb[0]), + SP_COLOR_F_TO_U(stroke_rgb[1]), + SP_COLOR_F_TO_U(stroke_rgb[2])); tmp_style << tmp; tmp_style << "stroke-width:" << @@ -315,6 +325,35 @@ select_pen(PEMF_CALLBACK_DATA d, int index) return; switch (pEmr->lopn.lopnStyle) { + case PS_DASH: + case PS_DOT: + case PS_DASHDOT: + case PS_DASHDOTDOT: + { + int i = 0; + d->style.stroke_dash.n_dash = + PS_DASHDOTDOT ? 6 : PS_DASHDOT ? 4 : 2; + if (d->style.stroke_dash.dash) + delete[] d->style.stroke_dash.dash; + d->style.stroke_dash.dash = new double[d->style.stroke_dash.n_dash]; + if (pEmr->lopn.lopnStyle==PS_DASH || pEmr->lopn.lopnStyle==PS_DASHDOT || pEmr->lopn.lopnStyle==PS_DASHDOTDOT) { + d->style.stroke_dash.dash[i++] = 3; + d->style.stroke_dash.dash[i++] = 1; + } + if (pEmr->lopn.lopnStyle==PS_DOT || pEmr->lopn.lopnStyle==PS_DASHDOT || pEmr->lopn.lopnStyle==PS_DASHDOTDOT) { + d->style.stroke_dash.dash[i++] = 1; + d->style.stroke_dash.dash[i++] = 1; + } + if (pEmr->lopn.lopnStyle==PS_DASHDOTDOT) { + d->style.stroke_dash.dash[i++] = 1; + d->style.stroke_dash.dash[i++] = 1; + } + + d->style.stroke_dasharray_set = 1; + break; + } + + case PS_SOLID: default: { d->style.stroke_dasharray_set = 0; @@ -322,10 +361,16 @@ select_pen(PEMF_CALLBACK_DATA d, int index) } } - if (pEmr->lopn.lopnWidth.x) { + d->stroke_set = true; + + if (pEmr->lopn.lopnStyle == PS_NULL) { + d->style.stroke_width.value = 0; + d->stroke_set = false; + } else if (pEmr->lopn.lopnWidth.x) { d->style.stroke_width.value = pix_size_to_point( d, pEmr->lopn.lopnWidth.x ); } else { // this stroke should always be rendered as 1 pixel wide, independent of zoom level (can that be done in SVG?) - d->style.stroke_width.value = 1.0; + //d->style.stroke_width.value = 1.0; + d->style.stroke_width.value = pix_size_to_point( d, 1 ); } double r, g, b; @@ -335,8 +380,6 @@ select_pen(PEMF_CALLBACK_DATA d, int index) d->style.stroke.value.color.set( r, g, b ); d->style.stroke_linejoin.computed = 1; - - d->stroke_set = true; } @@ -449,6 +492,28 @@ select_brush(PEMF_CALLBACK_DATA d, int index) } +static void +select_font(PEMF_CALLBACK_DATA d, int index) +{ + PEMREXTCREATEFONTINDIRECTW pEmr = NULL; + + if (index >= 0 && index < d->n_obj) + pEmr = (PEMREXTCREATEFONTINDIRECTW) d->emf_obj[index].lpEMFR; + + if (!pEmr) + return; + + d->style.font_size.computed = pix_size_to_point( d, pEmr->elfw.elfLogFont.lfHeight ); + d->style.font_weight.value = pEmr->elfw.elfLogFont.lfWeight; + d->style.font_style.value = (pEmr->elfw.elfLogFont.lfItalic ? SP_CSS_FONT_STYLE_ITALIC : SP_CSS_FONT_STYLE_NORMAL); + d->style.text_decoration.underline = pEmr->elfw.elfLogFont.lfUnderline; + d->style.text_decoration.line_through = pEmr->elfw.elfLogFont.lfStrikeOut; + if (d->tstyle.font_family.value) + g_free(d->tstyle.font_family.value); + d->tstyle.font_family.value = + (gchar *) g_utf16_to_utf8( (gunichar2*) pEmr->elfw.elfLogFont.lfFaceName, -1, NULL, NULL, NULL ); +} + static void delete_object(PEMF_CALLBACK_DATA d, int index) { @@ -482,6 +547,21 @@ myEnhMetaFileProc(HDC hDC, HANDLETABLE *lpHTable, ENHMETARECORD *lpEMFR, int nOb d = (PEMF_CALLBACK_DATA) lpData; + if (d->pathless_stroke) { + if (lpEMFR->iType!=EMR_POLYBEZIERTO && lpEMFR->iType!=EMR_POLYBEZIERTO16 && + lpEMFR->iType!=EMR_POLYLINETO && lpEMFR->iType!=EMR_POLYLINETO16 && + lpEMFR->iType!=EMR_LINETO && lpEMFR->iType!=EMR_ARCTO) + { + *(d->outsvg) += " outsvg) += "\n\t"; + *(d->outsvg) += *(d->path); + *(d->outsvg) += " \" /> \n"; + *(d->path) = ""; + d->pathless_stroke = false; + } + } + switch (lpEMFR->iType) { case EMR_HEADER: @@ -505,7 +585,7 @@ myEnhMetaFileProc(HDC hDC, HANDLETABLE *lpHTable, ENHMETARECORD *lpEMFR, int nOb if (pEmr->nHandles) { d->n_obj = pEmr->nHandles; d->emf_obj = new EMF_OBJECT[d->n_obj]; - + // Init the new emf_obj list elements to null, provided the // dynamic allocation succeeded. if ( d->emf_obj != NULL ) @@ -614,6 +694,9 @@ myEnhMetaFileProc(HDC hDC, HANDLETABLE *lpHTable, ENHMETARECORD *lpEMFR, int nOb PEMRPOLYBEZIERTO pEmr = (PEMRPOLYBEZIERTO) lpEMFR; DWORD i,j; + if (d->path->empty()) + *(d->path) = "d=\""; + for (i=0; icptl;) { tmp_path << "\n\tC "; for (j=0; j<3 && icptl; j++,i++) { @@ -630,6 +713,9 @@ myEnhMetaFileProc(HDC hDC, HANDLETABLE *lpHTable, ENHMETARECORD *lpEMFR, int nOb PEMRPOLYLINETO pEmr = (PEMRPOLYLINETO) lpEMFR; DWORD i; + if (d->path->empty()) + *(d->path) = "d=\""; + for (i=0; icptl;i++) { tmp_path << "\n\tL " << @@ -640,13 +726,53 @@ myEnhMetaFileProc(HDC hDC, HANDLETABLE *lpHTable, ENHMETARECORD *lpEMFR, int nOb break; } case EMR_POLYPOLYLINE: - break; case EMR_POLYPOLYGON: + { + PEMRPOLYPOLYGON pEmr = (PEMRPOLYPOLYGON) lpEMFR; + unsigned int n, i, j; + + if (lpEMFR->iType == EMR_POLYPOLYGON) + *(d->outsvg) += "\n"; + else + *(d->outsvg) += "\n"; + + *(d->outsvg) += "iType==EMR_POLYPOLYGON ? EMR_STROKEANDFILLPATH : EMR_STROKEPATH); + *(d->outsvg) += "\n\td=\""; + + POINTL *aptl = (POINTL *) &pEmr->aPolyCounts[pEmr->nPolys]; + + i = 0; + for (n=0; nnPolys && icptl; n++) { + SVGOStringStream poly_path; + + poly_path << "\n\tM " << + pix_x_to_point( d, aptl[i].x ) << " " << + pix_y_to_point( d, aptl[i].y ) << " "; + i++; + + for (j=1; jaPolyCounts[n] && icptl; j++) { + poly_path << "\n\tL " << + pix_x_to_point( d, aptl[i].x ) << " " << + pix_y_to_point( d, aptl[i].y ) << " "; + i++; + } + + *(d->outsvg) += poly_path.str().c_str(); + if (lpEMFR->iType == EMR_POLYPOLYGON) + *(d->outsvg) += " z"; + *(d->outsvg) += " \n"; + } + + *(d->outsvg) += " \" /> \n"; break; + } case EMR_SETWINDOWEXTEX: { PEMRSETWINDOWEXTEX pEmr = (PEMRSETWINDOWEXTEX) lpEMFR; + *(d->outsvg) += "\n"; + d->sizeWnd = pEmr->szlExtent; d->PixelsX = d->sizeWnd.cx; d->PixelsY = d->sizeWnd.cy; @@ -666,6 +792,8 @@ myEnhMetaFileProc(HDC hDC, HANDLETABLE *lpHTable, ENHMETARECORD *lpEMFR, int nOb { PEMRSETVIEWPORTEXTEX pEmr = (PEMRSETVIEWPORTEXTEX) lpEMFR; + *(d->outsvg) += "\n"; + d->sizeView = pEmr->szlExtent; if (d->sizeWnd.cx && d->sizeWnd.cy) { @@ -705,6 +833,7 @@ myEnhMetaFileProc(HDC hDC, HANDLETABLE *lpHTable, ENHMETARECORD *lpEMFR, int nOb break; } case EMR_SETBRUSHORGEX: + *(d->outsvg) += "\n"; break; case EMR_EOF: { @@ -712,12 +841,16 @@ myEnhMetaFileProc(HDC hDC, HANDLETABLE *lpHTable, ENHMETARECORD *lpEMFR, int nOb break; } case EMR_SETPIXELV: + *(d->outsvg) += "\n"; break; case EMR_SETMAPPERFLAGS: + *(d->outsvg) += "\n"; break; case EMR_SETMAPMODE: + *(d->outsvg) += "\n"; break; case EMR_SETBKMODE: + *(d->outsvg) += "\n"; break; case EMR_SETPOLYFILLMODE: { @@ -728,22 +861,35 @@ myEnhMetaFileProc(HDC hDC, HANDLETABLE *lpHTable, ENHMETARECORD *lpEMFR, int nOb break; } case EMR_SETROP2: + *(d->outsvg) += "\n"; break; case EMR_SETSTRETCHBLTMODE: + *(d->outsvg) += "\n"; break; case EMR_SETTEXTALIGN: + *(d->outsvg) += "\n"; break; case EMR_SETCOLORADJUSTMENT: + *(d->outsvg) += "\n"; break; case EMR_SETTEXTCOLOR: + *(d->outsvg) += "\n"; break; case EMR_SETBKCOLOR: + *(d->outsvg) += "\n"; break; case EMR_OFFSETCLIPRGN: + *(d->outsvg) += "\n"; break; case EMR_MOVETOEX: { PEMRMOVETOEX pEmr = (PEMRMOVETOEX) lpEMFR; + + if (d->path->empty()) { + d->pathless_stroke = true; + *(d->path) = "d=\""; + } + tmp_path << "\n\tM " << pix_x_to_point( d, pEmr->ptl.x ) << " " << @@ -751,22 +897,31 @@ myEnhMetaFileProc(HDC hDC, HANDLETABLE *lpHTable, ENHMETARECORD *lpEMFR, int nOb break; } case EMR_SETMETARGN: + *(d->outsvg) += "\n"; break; case EMR_EXCLUDECLIPRECT: + *(d->outsvg) += "\n"; break; case EMR_INTERSECTCLIPRECT: + *(d->outsvg) += "\n"; break; case EMR_SCALEVIEWPORTEXTEX: + *(d->outsvg) += "\n"; break; case EMR_SCALEWINDOWEXTEX: + *(d->outsvg) += "\n"; break; case EMR_SAVEDC: + *(d->outsvg) += "\n"; break; case EMR_RESTOREDC: + *(d->outsvg) += "\n"; break; case EMR_SETWORLDTRANSFORM: + *(d->outsvg) += "\n"; break; case EMR_MODIFYWORLDTRANSFORM: + *(d->outsvg) += "\n"; break; case EMR_SELECTOBJECT: { @@ -825,7 +980,7 @@ myEnhMetaFileProc(HDC hDC, HANDLETABLE *lpHTable, ENHMETARECORD *lpEMFR, int nOb } } } else { - if (index >= 0 && index < (unsigned int)d->n_obj) { + if (index >= 0 && index < (unsigned int) d->n_obj) { switch (d->emf_obj[index].type) { case EMR_CREATEPEN: @@ -837,6 +992,9 @@ myEnhMetaFileProc(HDC hDC, HANDLETABLE *lpHTable, ENHMETARECORD *lpEMFR, int nOb case EMR_EXTCREATEPEN: select_extpen(d, index); break; + case EMR_EXTCREATEFONTINDIRECTW: + select_font(d, index); + break; } } } @@ -869,34 +1027,51 @@ myEnhMetaFileProc(HDC hDC, HANDLETABLE *lpHTable, ENHMETARECORD *lpEMFR, int nOb case EMR_DELETEOBJECT: break; case EMR_ANGLEARC: + *(d->outsvg) += "\n"; break; case EMR_ELLIPSE: + *(d->outsvg) += "\n"; break; case EMR_RECTANGLE: + *(d->outsvg) += "\n"; break; case EMR_ROUNDRECT: + *(d->outsvg) += "\n"; break; case EMR_ARC: + *(d->outsvg) += "\n"; break; case EMR_CHORD: + *(d->outsvg) += "\n"; break; case EMR_PIE: + *(d->outsvg) += "\n"; break; case EMR_SELECTPALETTE: + *(d->outsvg) += "\n"; break; case EMR_CREATEPALETTE: + *(d->outsvg) += "\n"; break; case EMR_SETPALETTEENTRIES: + *(d->outsvg) += "\n"; break; case EMR_RESIZEPALETTE: + *(d->outsvg) += "\n"; break; case EMR_REALIZEPALETTE: + *(d->outsvg) += "\n"; break; case EMR_EXTFLOODFILL: + *(d->outsvg) += "\n"; break; case EMR_LINETO: { PEMRLINETO pEmr = (PEMRLINETO) lpEMFR; + + if (d->path->empty()) + *(d->path) = "d=\""; + tmp_path << "\n\tL " << pix_x_to_point( d, pEmr->ptl.x ) << " " << @@ -904,10 +1079,13 @@ myEnhMetaFileProc(HDC hDC, HANDLETABLE *lpHTable, ENHMETARECORD *lpEMFR, int nOb break; } case EMR_ARCTO: + *(d->outsvg) += "\n"; break; case EMR_POLYDRAW: + *(d->outsvg) += "\n"; break; case EMR_SETARCDIRECTION: + *(d->outsvg) += "\n"; break; case EMR_SETMITERLIMIT: { @@ -921,7 +1099,7 @@ myEnhMetaFileProc(HDC hDC, HANDLETABLE *lpHTable, ENHMETARECORD *lpEMFR, int nOb } case EMR_BEGINPATH: { - tmp_path << " d=\""; + tmp_path << "d=\""; *(d->path) = ""; break; } @@ -944,46 +1122,145 @@ myEnhMetaFileProc(HDC hDC, HANDLETABLE *lpHTable, ENHMETARECORD *lpEMFR, int nOb *(d->outsvg) += "\n\t"; *(d->outsvg) += *(d->path); *(d->outsvg) += " /> \n"; + *(d->path) = ""; break; } case EMR_FLATTENPATH: + *(d->outsvg) += "\n"; break; case EMR_WIDENPATH: + *(d->outsvg) += "\n"; break; case EMR_SELECTCLIPPATH: + *(d->outsvg) += "\n"; break; case EMR_ABORTPATH: + *(d->outsvg) += "\n"; break; case EMR_GDICOMMENT: + *(d->outsvg) += "\n"; break; case EMR_FILLRGN: + *(d->outsvg) += "\n"; break; case EMR_FRAMERGN: + *(d->outsvg) += "\n"; break; case EMR_INVERTRGN: + *(d->outsvg) += "\n"; break; case EMR_PAINTRGN: + *(d->outsvg) += "\n"; break; case EMR_EXTSELECTCLIPRGN: + *(d->outsvg) += "\n"; break; case EMR_BITBLT: + *(d->outsvg) += "\n"; break; case EMR_STRETCHBLT: + *(d->outsvg) += "\n"; break; case EMR_MASKBLT: + *(d->outsvg) += "\n"; break; case EMR_PLGBLT: + *(d->outsvg) += "\n"; break; case EMR_SETDIBITSTODEVICE: + *(d->outsvg) += "\n"; break; case EMR_STRETCHDIBITS: + *(d->outsvg) += "\n"; break; case EMR_EXTCREATEFONTINDIRECTW: + { + PEMREXTCREATEFONTINDIRECTW pEmr = (PEMREXTCREATEFONTINDIRECTW) lpEMFR; + int index = pEmr->ihFont; + + EMREXTCREATEFONTINDIRECTW *pFont = + (EMREXTCREATEFONTINDIRECTW *) malloc( sizeof(EMREXTCREATEFONTINDIRECTW) ); + pFont->elfw = pEmr->elfw; + insert_object(d, index, EMR_EXTCREATEFONTINDIRECTW, (ENHMETARECORD *) pFont); + break; + } case EMR_EXTTEXTOUTA: + { + *(d->outsvg) += "\n"; break; + } case EMR_EXTTEXTOUTW: + { + PEMREXTTEXTOUTW pEmr = (PEMREXTTEXTOUTW) lpEMFR; + + double x = pEmr->emrtext.ptlReference.x; + double y = pEmr->emrtext.ptlReference.y; + + x = pix_x_to_point(d, x); + y = pix_y_to_point(d, y); + + wchar_t *text = (wchar_t *) ((char *) pEmr + pEmr->emrtext.offString); +/* + int i; + for (i=0; iemrtext.nChars; i++) { + if (text[i] < L' ' || text[i] > L'z') + text[i] = L'?'; + } +*/ + gchar *t = + (gchar *) g_utf16_to_utf8( (gunichar2 *) text, pEmr->emrtext.nChars, NULL, NULL, NULL ); + + if (t) { + SVGOStringStream ts; + + gchar *escaped = g_markup_escape_text(t, -1); + + int j; + for (j=0; j 127) + escaped[j] = '?'; + } + + float text_rgb[3]; + sp_color_get_rgb_floatv( &(d->style.fill.value.color), text_rgb ); + + char tmp[128]; + snprintf(tmp, 127, + "fill:#%02x%02x%02x;", + SP_COLOR_F_TO_U(text_rgb[0]), + SP_COLOR_F_TO_U(text_rgb[1]), + SP_COLOR_F_TO_U(text_rgb[2])); + + bool i = (d->style.font_style.value == SP_CSS_FONT_STYLE_ITALIC); + bool o = (d->style.font_style.value == SP_CSS_FONT_STYLE_OBLIQUE); + bool b = (d->style.font_weight.value == SP_CSS_FONT_WEIGHT_BOLD) || + (d->style.font_weight.value >= SP_CSS_FONT_WEIGHT_500 && d->style.font_weight.value <= SP_CSS_FONT_WEIGHT_900); + + ts << " style.font_size.computed << "px;" + << tmp + << "font-style:" << (i ? "italic" : "normal") << ";" + << "font-weight:" << (b ? "bold" : "normal") << ";" +// << "text-align:" << (b ? "start" : "center" : "end") << ";" + << "font-family:" << d->tstyle.font_family.value << ";" + << "\"\n"; + ts << " >"; + ts << escaped; + ts << "\n"; + + *(d->outsvg) += ts.str().c_str(); + + g_free(escaped); + g_free(t); + } + break; + } case EMR_POLYBEZIER16: { PEMRPOLYBEZIER16 pEmr = (PEMRPOLYBEZIER16) lpEMFR; @@ -1078,6 +1355,9 @@ myEnhMetaFileProc(HDC hDC, HANDLETABLE *lpHTable, ENHMETARECORD *lpEMFR, int nOb POINTS *apts = (POINTS *) pEmr->apts; // Bug in MinGW wingdi.h ? DWORD i,j; + if (d->path->empty()) + *(d->path) = "d=\""; + for (i=0; icpts;) { tmp_path << "\n\tC "; for (j=0; j<3 && icpts; j++,i++) { @@ -1095,6 +1375,9 @@ myEnhMetaFileProc(HDC hDC, HANDLETABLE *lpHTable, ENHMETARECORD *lpEMFR, int nOb POINTS *apts = (POINTS *) pEmr->apts; // Bug in MinGW wingdi.h ? DWORD i; + if (d->path->empty()) + *(d->path) = "d=\""; + for (i=0; icpts;i++) { tmp_path << "\n\tL " << @@ -1105,44 +1388,55 @@ myEnhMetaFileProc(HDC hDC, HANDLETABLE *lpHTable, ENHMETARECORD *lpEMFR, int nOb break; } case EMR_POLYPOLYLINE16: - break; case EMR_POLYPOLYGON16: { PEMRPOLYPOLYGON16 pEmr = (PEMRPOLYPOLYGON16) lpEMFR; unsigned int n, i, j; + if (lpEMFR->iType == EMR_POLYPOLYGON16) + *(d->outsvg) += "\n"; + else + *(d->outsvg) += "\n"; + *(d->outsvg) += "iType==EMR_POLYPOLYGON16 ? EMR_STROKEANDFILLPATH : EMR_STROKEPATH); *(d->outsvg) += "\n\td=\""; - i = pEmr->nPolys-1; // ??? - for (n=0; nnPolys /*&& icpts*/; n++) { + POINTS *apts = (POINTS *) &pEmr->aPolyCounts[pEmr->nPolys]; + + i = 0; + for (n=0; nnPolys && icpts; n++) { SVGOStringStream poly_path; poly_path << "\n\tM " << - pix_x_to_point( d, pEmr->apts[i].x ) << " " << - pix_y_to_point( d, pEmr->apts[i].y ) << " "; + pix_x_to_point( d, apts[i].x ) << " " << + pix_y_to_point( d, apts[i].y ) << " "; i++; - for (j=1; jaPolyCounts[n] /*&& icpts*/; j++) { + for (j=1; jaPolyCounts[n] && icpts; j++) { poly_path << "\n\tL " << - pix_x_to_point( d, pEmr->apts[i].x ) << " " << - pix_y_to_point( d, pEmr->apts[i].y ) << " "; + pix_x_to_point( d, apts[i].x ) << " " << + pix_y_to_point( d, apts[i].y ) << " "; i++; } *(d->outsvg) += poly_path.str().c_str(); - *(d->outsvg) += " z \n"; + if (lpEMFR->iType == EMR_POLYPOLYGON16) + *(d->outsvg) += " z"; + *(d->outsvg) += " \n"; } *(d->outsvg) += " \" /> \n"; break; } case EMR_POLYDRAW16: + *(d->outsvg) += "\n"; break; case EMR_CREATEMONOBRUSH: + *(d->outsvg) += "\n"; break; case EMR_CREATEDIBPATTERNBRUSHPT: + *(d->outsvg) += "\n"; break; case EMR_EXTCREATEPEN: { @@ -1166,25 +1460,34 @@ myEnhMetaFileProc(HDC hDC, HANDLETABLE *lpHTable, ENHMETARECORD *lpEMFR, int nOb break; } case EMR_POLYTEXTOUTA: + *(d->outsvg) += "\n"; break; case EMR_POLYTEXTOUTW: + *(d->outsvg) += "\n"; break; case EMR_SETICMMODE: + *(d->outsvg) += "\n"; break; case EMR_CREATECOLORSPACE: + *(d->outsvg) += "\n"; break; case EMR_SETCOLORSPACE: + *(d->outsvg) += "\n"; break; case EMR_DELETECOLORSPACE: + *(d->outsvg) += "\n"; break; case EMR_GLSRECORD: + *(d->outsvg) += "\n"; break; case EMR_GLSBOUNDEDRECORD: + *(d->outsvg) += "\n"; break; case EMR_PIXELFORMAT: + *(d->outsvg) += "\n"; break; } - + *(d->outsvg) += tmp_outsvg.str().c_str(); *(d->path) += tmp_path.str().c_str(); @@ -1358,7 +1661,7 @@ EmfWin32::open( Inkscape::Extension::Input *mod, const gchar *uri ) delete_object(&d, i); delete[] d.emf_obj; } - + if (d.style.stroke_dash.dash) delete[] d.style.stroke_dash.dash; @@ -1409,6 +1712,7 @@ EmfWin32::init (void) "\n" "" N_("EMF Output") "\n" "org.inkscape.output.emf.win32\n" + "true\n" "\n" ".emf\n" "image/x-emf\n" diff --git a/src/extension/internal/emf-win32-print.cpp b/src/extension/internal/emf-win32-print.cpp index 9e76ce457..6b2fd912c 100644 --- a/src/extension/internal/emf-win32-print.cpp +++ b/src/extension/internal/emf-win32-print.cpp @@ -53,6 +53,10 @@ #include "sp-paint-server.h" #include "inkscape_version.h" +#include "FontFactory.h" +#include "libnrtype/font-instance.h" +#include "libnrtype/font-style-to-pos.h" + #include "win32.h" #include "emf-win32-print.h" @@ -79,6 +83,7 @@ static float dwDPI = 2540; PrintEmfWin32::PrintEmfWin32 (void): hdc(NULL), hbrush(NULL), + hbrushOld(NULL), hpen(NULL), fill_path(NULL) { @@ -235,12 +240,16 @@ PrintEmfWin32::comment (Inkscape::Extension::Print * module, } -void +int PrintEmfWin32::create_brush(SPStyle const *style) { float rgb[3]; if (style) { + float opacity = SP_SCALE24_TO_FLOAT(style->fill_opacity.value); + if (opacity <= 0.0) + return 1; + sp_color_get_rgb_floatv( &style->fill.value.color, rgb ); hbrush = CreateSolidBrush( RGB(255*rgb[0], 255*rgb[1], 255*rgb[2]) ); hbrushOld = (HBRUSH) SelectObject( hdc, hbrush ); @@ -253,6 +262,8 @@ PrintEmfWin32::create_brush(SPStyle const *style) hbrushOld = (HBRUSH) SelectObject( hdc, hbrush ); SetPolyFillMode( hdc, ALTERNATE ); } + + return 0; } @@ -263,11 +274,12 @@ PrintEmfWin32::destroy_brush() if (hbrush) DeleteObject( hbrush ); hbrush = NULL; + hbrushOld = NULL; } void -PrintEmfWin32::create_pen(SPStyle const *style) +PrintEmfWin32::create_pen(SPStyle const *style, const NRMatrix *transform) { if (style) { float rgb[3]; @@ -285,7 +297,20 @@ PrintEmfWin32::create_pen(SPStyle const *style) DWORD *dash = NULL; float oldmiterlimit; - DWORD linewidth = MAX( 1, (DWORD) (style->stroke_width.computed * IN_PER_PX * dwDPI) ); + using NR::X; + using NR::Y; + + NR::Matrix tf = *transform; + + NR::Point zero(0, 0); + NR::Point one(1, 1); + NR::Point p0(zero * tf); + NR::Point p1(one * tf); + NR::Point p(p1 - p0); + + double scale = sqrt( (p[X]*p[X]) + (p[Y]*p[Y]) ) / sqrt(2); + + DWORD linewidth = MAX( 1, (DWORD) (scale * style->stroke_width.computed * IN_PER_PX * dwDPI) ); if (style->stroke_linecap.computed == 0) { linecap = PS_ENDCAP_FLAT; @@ -445,6 +470,18 @@ PrintEmfWin32::cmp_bpath(const NArtBpath *bp1, const NArtBpath *bp2) return bp1->code != NR_END || bp2->code != NR_END; } +unsigned int +PrintEmfWin32::bind(Inkscape::Extension::Print *mod, NRMatrix const *transform, float opacity) +{ + text_transform = *transform; + return 0; +} + +unsigned int +PrintEmfWin32::release(Inkscape::Extension::Print *mod) +{ + return 0; +} unsigned int PrintEmfWin32::fill(Inkscape::Extension::Print *mod, @@ -456,7 +493,8 @@ PrintEmfWin32::fill(Inkscape::Extension::Print *mod, flush_fill(); // flush any pending fills if (style->fill.isColor()) { - create_brush(style); + if (create_brush(style)) + return 0; } else { // create_brush(NULL); return 0; @@ -486,9 +524,9 @@ PrintEmfWin32::stroke (Inkscape::Extension::Print *mod, } if (style->stroke.isColor()) { - create_pen(style); + create_pen(style, transform); } else { - // create_pen(NULL); + // create_pen(NULL, transform); return 0; } @@ -590,6 +628,139 @@ PrintEmfWin32::textToPath(Inkscape::Extension::Print * ext) return ext->get_param_bool("textToPath"); } +unsigned int +PrintEmfWin32::text(Inkscape::Extension::Print *mod, char const *text, NR::Point p, + SPStyle const *const style) +{ + if (!hdc) return 0; + + HFONT hfont = NULL; + +#ifdef USE_PANGO_WIN32 +/* + font_instance *tf = (font_factory::Default())->Face(style->text->font_family.value, font_style_to_pos(*style)); + if (tf) { + LOGFONT *lf = pango_win32_font_logfont(tf->pFont); + tf->Unref(); + hfont = CreateFontIndirect(lf); + g_free(lf); + } +*/ +#endif + + if (!hfont) { + if (PrintWin32::is_os_wide()) { + LOGFONTW *lf = (LOGFONTW*)g_malloc(sizeof(LOGFONTW)); + g_assert(lf != NULL); + + lf->lfHeight = style->font_size.computed * IN_PER_PX * dwDPI; + lf->lfWidth = 0; + lf->lfEscapement = 0; + lf->lfOrientation = 0; + lf->lfWeight = + style->font_weight.value == SP_CSS_FONT_WEIGHT_100 ? FW_THIN : + style->font_weight.value == SP_CSS_FONT_WEIGHT_200 ? FW_EXTRALIGHT : + style->font_weight.value == SP_CSS_FONT_WEIGHT_300 ? FW_LIGHT : + style->font_weight.value == SP_CSS_FONT_WEIGHT_400 ? FW_NORMAL : + style->font_weight.value == SP_CSS_FONT_WEIGHT_500 ? FW_MEDIUM : + style->font_weight.value == SP_CSS_FONT_WEIGHT_600 ? FW_SEMIBOLD : + style->font_weight.value == SP_CSS_FONT_WEIGHT_700 ? FW_BOLD : + style->font_weight.value == SP_CSS_FONT_WEIGHT_800 ? FW_EXTRABOLD : + style->font_weight.value == SP_CSS_FONT_WEIGHT_900 ? FW_HEAVY : + style->font_weight.value == SP_CSS_FONT_WEIGHT_NORMAL ? FW_NORMAL : + style->font_weight.value == SP_CSS_FONT_WEIGHT_BOLD ? FW_BOLD : + style->font_weight.value == SP_CSS_FONT_WEIGHT_LIGHTER ? FW_EXTRALIGHT : + style->font_weight.value == SP_CSS_FONT_WEIGHT_BOLDER ? FW_EXTRABOLD : + FW_NORMAL; + lf->lfItalic = (style->font_style.value == SP_CSS_FONT_STYLE_ITALIC); + lf->lfUnderline = style->text_decoration.underline; + lf->lfStrikeOut = style->text_decoration.line_through; + lf->lfCharSet = DEFAULT_CHARSET; + lf->lfOutPrecision = OUT_DEFAULT_PRECIS; + lf->lfClipPrecision = CLIP_DEFAULT_PRECIS; + lf->lfQuality = DEFAULT_QUALITY; + lf->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; + + gunichar2 *unicode_name = g_utf8_to_utf16( style->text->font_family.value, -1, NULL, NULL, NULL ); + wcsncpy(lf->lfFaceName, (wchar_t*) unicode_name, LF_FACESIZE-1); + g_free(unicode_name); + + hfont = CreateFontIndirectW(lf); + + g_free(lf); + } + else { + LOGFONTA *lf = (LOGFONTA*)g_malloc(sizeof(LOGFONTA)); + g_assert(lf != NULL); + + lf->lfHeight = style->font_size.computed * IN_PER_PX * dwDPI; + lf->lfWidth = 0; + lf->lfEscapement = 0; + lf->lfOrientation = 0; + lf->lfWeight = + style->font_weight.value == SP_CSS_FONT_WEIGHT_100 ? FW_THIN : + style->font_weight.value == SP_CSS_FONT_WEIGHT_200 ? FW_EXTRALIGHT : + style->font_weight.value == SP_CSS_FONT_WEIGHT_300 ? FW_LIGHT : + style->font_weight.value == SP_CSS_FONT_WEIGHT_400 ? FW_NORMAL : + style->font_weight.value == SP_CSS_FONT_WEIGHT_500 ? FW_MEDIUM : + style->font_weight.value == SP_CSS_FONT_WEIGHT_600 ? FW_SEMIBOLD : + style->font_weight.value == SP_CSS_FONT_WEIGHT_700 ? FW_BOLD : + style->font_weight.value == SP_CSS_FONT_WEIGHT_800 ? FW_EXTRABOLD : + style->font_weight.value == SP_CSS_FONT_WEIGHT_900 ? FW_HEAVY : + style->font_weight.value == SP_CSS_FONT_WEIGHT_NORMAL ? FW_NORMAL : + style->font_weight.value == SP_CSS_FONT_WEIGHT_BOLD ? FW_BOLD : + style->font_weight.value == SP_CSS_FONT_WEIGHT_LIGHTER ? FW_EXTRALIGHT : + style->font_weight.value == SP_CSS_FONT_WEIGHT_BOLDER ? FW_EXTRABOLD : + FW_NORMAL; + lf->lfItalic = (style->font_style.value == SP_CSS_FONT_STYLE_ITALIC); + lf->lfUnderline = style->text_decoration.underline; + lf->lfStrikeOut = style->text_decoration.line_through; + lf->lfCharSet = DEFAULT_CHARSET; + lf->lfOutPrecision = OUT_DEFAULT_PRECIS; + lf->lfClipPrecision = CLIP_DEFAULT_PRECIS; + lf->lfQuality = DEFAULT_QUALITY; + lf->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; + + strncpy(lf->lfFaceName, (char*) style->text->font_family.value, LF_FACESIZE-1); + + hfont = CreateFontIndirectA(lf); + + g_free(lf); + } + } + + HFONT hfontOld = (HFONT) SelectObject(hdc, hfont); + + float rgb[3]; + sp_color_get_rgb_floatv( &style->fill.value.color, rgb ); + SetTextColor(hdc, RGB(255*rgb[0], 255*rgb[1], 255*rgb[2])); + + int align = + style->text_align.value == SP_CSS_TEXT_ALIGN_RIGHT ? TA_RIGHT : + style->text_align.value == SP_CSS_TEXT_ALIGN_CENTER ? TA_CENTER : TA_LEFT; + SetTextAlign(hdc, TA_BASELINE | align); + + p = p * text_transform; + p[NR::X] = (p[NR::X] * IN_PER_PX * dwDPI); + p[NR::Y] = (p[NR::Y] * IN_PER_PX * dwDPI); + + if (PrintWin32::is_os_wide()) { + gunichar2 *unicode_text = g_utf8_to_utf16( text, -1, NULL, NULL, NULL ); + TextOutW(hdc, p[NR::X], p[NR::Y], (WCHAR*)unicode_text, wcslen((wchar_t*)unicode_text)); + } + else { + TextOutA(hdc, p[NR::X], p[NR::Y], (CHAR*)text, strlen((char*)text)); + } + + SelectObject(hdc, hfontOld); + DeleteObject(hfont); + + return 0; + + + + return 0; +} void PrintEmfWin32::init (void) diff --git a/src/extension/internal/emf-win32-print.h b/src/extension/internal/emf-win32-print.h index 305507824..26ffc1807 100644 --- a/src/extension/internal/emf-win32-print.h +++ b/src/extension/internal/emf-win32-print.h @@ -46,6 +46,7 @@ class PrintEmfWin32 : public Inkscape::Extension::Implementation::Implementation NArtBpath *fill_path_copy; NRMatrix fill_transform; NRRect fill_pbox; + NRMatrix text_transform; unsigned int print_bpath (const NArtBpath *bp, const NRMatrix *transform, NRRect const *pbox); @@ -60,6 +61,8 @@ public: virtual unsigned int finish (Inkscape::Extension::Print * module); /* Rendering methods */ + virtual unsigned int bind(Inkscape::Extension::Print *module, NRMatrix const *transform, float opacity); + virtual unsigned int release(Inkscape::Extension::Print *module); virtual unsigned int fill (Inkscape::Extension::Print * module, const NRBPath *bpath, const NRMatrix *ctm, const SPStyle *style, const NRRect *pbox, const NRRect *dbox, const NRRect *bbox); @@ -67,16 +70,18 @@ public: const NRBPath *bpath, const NRMatrix *transform, const SPStyle *style, const NRRect *pbox, const NRRect *dbox, const NRRect *bbox); virtual unsigned int comment(Inkscape::Extension::Print *module, const char * comment); + virtual unsigned int text(Inkscape::Extension::Print *module, char const *text, + NR::Point p, SPStyle const *style); bool textToPath (Inkscape::Extension::Print * ext); static void init (void); protected: - void create_brush(SPStyle const *style); + int create_brush(SPStyle const *style); void destroy_brush(); - void create_pen(SPStyle const *style); + void create_pen(SPStyle const *style, const NRMatrix *transform); void destroy_pen(); -- 2.30.2