X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fextension%2Finternal%2Femf-win32-print.cpp;h=c7f8e3d4cb93f66207638057385d990ba09282aa;hb=aec3c9ae3da6e2f0e5ff87d431716dfccfc7bd71;hp=6b2fd912c455098c4ce6b8ac97614d21c13e0bc5;hpb=ef288ea4aa607f91eecb2f58a57714b3f923167a;p=inkscape.git diff --git a/src/extension/internal/emf-win32-print.cpp b/src/extension/internal/emf-win32-print.cpp index 6b2fd912c..c7f8e3d4c 100644 --- a/src/extension/internal/emf-win32-print.cpp +++ b/src/extension/internal/emf-win32-print.cpp @@ -1,11 +1,12 @@ -/** \file - * Enhanced Metafile Printing. +/** @file + * @brief Enhanced Metafile printing */ -/* - * Authors: +/* Authors: * Ulf Erikson + * Jon A. Cruz + * Abhishek Sharma * - * Copyright (C) 2006 Authors + * Copyright (C) 2006-2009 Authors * * Released under GNU GPL, read the file 'COPYING' for more information */ @@ -27,51 +28,50 @@ # include "config.h" #endif -#include -#include -#include - -#include "libnr/n-art-bpath.h" -#include "libnr/nr-point-matrix-ops.h" -#include "libnr/nr-rect.h" -#include "libnr/nr-matrix.h" -#include "libnr/nr-matrix-fns.h" -#include "libnr/nr-path.h" -#include "libnr/nr-pixblock.h" -#include "display/canvas-bpath.h" +//#include +//#include +//#include + +#include <2geom/pathvector.h> +#include <2geom/rect.h> +#include <2geom/bezier-curve.h> +#include <2geom/hvlinesegment.h> +#include "helper/geom.h" +#include "helper/geom-curves.h" +//#include "display/canvas-bpath.h" #include "sp-item.h" -#include "glib.h" -#include "gtk/gtkdialog.h" -#include "gtk/gtkbox.h" -#include "gtk/gtkstock.h" +//#include "glib.h" +//#include "gtk/gtkdialog.h" +//#include "gtk/gtkbox.h" +//#include "gtk/gtkstock.h" -#include "glibmm/i18n.h" -#include "enums.h" -#include "document.h" +//#include "glibmm/i18n.h" +//#include "enums.h" +//#include "document.h" #include "style.h" -#include "sp-paint-server.h" -#include "inkscape_version.h" +//#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 "libnrtype/FontFactory.h" +//#include "libnrtype/font-instance.h" +//#include "libnrtype/font-style-to-pos.h" + +#define WIN32_LEAN_AND_MEAN +#include #include "win32.h" #include "emf-win32-print.h" #include "unit-constants.h" -#include "extension/extension.h" +//#include "extension/extension.h" #include "extension/system.h" #include "extension/print.h" -#include "io/sys.h" +//#include "io/sys.h" -#include "macros.h" - -#define WIN32_LEAN_AND_MEAN -#include +//#include "macros.h" namespace Inkscape { namespace Extension { @@ -85,7 +85,9 @@ PrintEmfWin32::PrintEmfWin32 (void): hbrush(NULL), hbrushOld(NULL), hpen(NULL), - fill_path(NULL) + stroke_and_fill(false), + fill_only(false), + simple_shape(false) { } @@ -104,12 +106,12 @@ PrintEmfWin32::~PrintEmfWin32 (void) #if !defined(_WIN32) && !defined(__WIN32__) (void) signal(SIGPIPE, SIG_DFL); #endif - return; + return; } unsigned int -PrintEmfWin32::setup (Inkscape::Extension::Print *mod) +PrintEmfWin32::setup (Inkscape::Extension::Print * /*mod*/) { return TRUE; } @@ -135,8 +137,8 @@ PrintEmfWin32::begin (Inkscape::Extension::Print *mod, SPDocument *doc) WCHAR *unicode_uri = (WCHAR *) unicode_fn; // width and height in px - _width = sp_document_width(doc); - _height = sp_document_height(doc); + _width = doc->getWidth(); + _height = doc->getHeight(); NRRect d; bool pageBoundingBox; @@ -146,8 +148,8 @@ PrintEmfWin32::begin (Inkscape::Extension::Print *mod, SPDocument *doc) d.x1 = _width; d.y1 = _height; } else { - SPItem* doc_item = SP_ITEM(sp_document_root(doc)); - sp_item_invoke_bbox(doc_item, &d, sp_item_i2r_affine(doc_item), TRUE); + SPItem* doc_item = SP_ITEM(doc->getRoot()); + doc_item->invoke_bbox(&d, doc_item->i2d_affine(), TRUE); } d.x0 *= IN_PER_PX; @@ -165,16 +167,34 @@ PrintEmfWin32::begin (Inkscape::Extension::Print *mod, SPDocument *doc) HDC hScreenDC = GetDC( NULL ); // Get the physical characteristics of the reference DC - float PixelsX = (float) GetDeviceCaps( hScreenDC, HORZRES ); - float PixelsY = (float) GetDeviceCaps( hScreenDC, VERTRES ); - float MMX = (float) GetDeviceCaps( hScreenDC, HORZSIZE ); - float MMY = (float) GetDeviceCaps( hScreenDC, VERTSIZE ); - - // Create the Metafile - if (PrintWin32::is_os_wide()) - hdc = CreateEnhMetaFileW( hScreenDC, unicode_uri, &rc, NULL ); + int PixelsX = GetDeviceCaps( hScreenDC, HORZRES ); + int PixelsY = GetDeviceCaps( hScreenDC, VERTRES ); + int MMX = GetDeviceCaps( hScreenDC, HORZSIZE ); + int MMY = GetDeviceCaps( hScreenDC, VERTSIZE ); + + CHAR buff[1024]; + ZeroMemory(buff, sizeof(buff)); + snprintf(buff, sizeof(buff)-1, "Inkscape %s (%s)", Inkscape::version_string, __DATE__); + INT len = strlen(buff); + CHAR *p1 = strrchr(ansi_uri, '\\'); + CHAR *p2 = strrchr(ansi_uri, '/'); + CHAR *p = MAX(p1, p2); + if (p) + p++; else - hdc = CreateEnhMetaFileA( hScreenDC, ansi_uri, &rc, NULL ); + p = ansi_uri; + snprintf(buff+len+1, sizeof(buff)-len-2, "%s", p); + + // Create the Metafile + if (PrintWin32::is_os_wide()) { + WCHAR wbuff[1024]; + ZeroMemory(wbuff, sizeof(wbuff)); + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, buff, sizeof(buff)/sizeof(buff[0]), wbuff, sizeof(wbuff)/sizeof(wbuff[0])); + hdc = CreateEnhMetaFileW( hScreenDC, unicode_uri, &rc, wbuff ); + } + else { + hdc = CreateEnhMetaFileA( hScreenDC, ansi_uri, &rc, buff ); + } // Release the reference DC ReleaseDC( NULL, hScreenDC ); @@ -191,26 +211,37 @@ PrintEmfWin32::begin (Inkscape::Extension::Print *mod, SPDocument *doc) SetMapMode( hdc, MM_ANISOTROPIC ); // Set the Windows extent - SetWindowExtEx( hdc, (int) (dwInchesX*dwDPI), (int) (dwInchesY*dwDPI), NULL ); + int windowextX = (int) ceil(dwInchesX*dwDPI); + int windowextY = (int) ceil(dwInchesY*dwDPI); + SetWindowExtEx( hdc, windowextX, windowextY, NULL ); // Set the viewport extent to reflect // dwInchesX" x dwInchesY" in device units - SetViewportExtEx( hdc, - (int) ((float) dwInchesX*25.4f*PixelsX/MMX), - (int) ((float) dwInchesY*25.4f*PixelsY/MMY), - NULL ); + int viewportextX = (int)((float)dwInchesX*25.4f*(float)PixelsX/(float)MMX); + int viewportextY = (int)((float)dwInchesY*25.4f*(float)PixelsY/(float)MMY); + SetViewportExtEx( hdc, viewportextX, viewportextY, NULL ); + + if (1) { + snprintf(buff, sizeof(buff)-1, "Screen=%dx%dpx, %dx%dmm", PixelsX, PixelsY, MMX, MMY); + GdiComment(hdc, strlen(buff), (BYTE*) buff); + + snprintf(buff, sizeof(buff)-1, "Drawing=%.1lfx%.1lfpx, %.1lfx%.1lfmm", _width, _height, dwInchesX * MM_PER_IN, dwInchesY * MM_PER_IN); + GdiComment(hdc, strlen(buff), (BYTE*) buff); + } SetRect( &rc, 0, 0, (int) ceil(dwInchesX*dwDPI), (int) ceil(dwInchesY*dwDPI) ); g_free(local_fn); g_free(unicode_fn); + m_tr_stack.push( Geom::Scale(1, -1) * Geom::Translate(0, doc->getHeight())); + return 0; } unsigned int -PrintEmfWin32::finish (Inkscape::Extension::Print *mod) +PrintEmfWin32::finish (Inkscape::Extension::Print * /*mod*/) { if (!hdc) return 0; @@ -229,8 +260,8 @@ PrintEmfWin32::finish (Inkscape::Extension::Print *mod) unsigned int -PrintEmfWin32::comment (Inkscape::Extension::Print * module, - const char *comment) +PrintEmfWin32::comment (Inkscape::Extension::Print * /*module*/, + const char * /*comment*/) { if (!hdc) return 0; @@ -279,14 +310,15 @@ PrintEmfWin32::destroy_brush() void -PrintEmfWin32::create_pen(SPStyle const *style, const NRMatrix *transform) +PrintEmfWin32::create_pen(SPStyle const *style, const Geom::Matrix &transform) { if (style) { float rgb[3]; sp_color_get_rgb_floatv(&style->stroke.value.color, rgb); - LOGBRUSH lb = {0}; + LOGBRUSH lb; + ZeroMemory(&lb, sizeof(lb)); lb.lbStyle = BS_SOLID; lb.lbColor = RGB( 255*rgb[0], 255*rgb[1], 255*rgb[2] ); @@ -295,18 +327,15 @@ PrintEmfWin32::create_pen(SPStyle const *style, const NRMatrix *transform) int linejoin = 0; DWORD n_dash = 0; DWORD *dash = NULL; - float oldmiterlimit; - - using NR::X; - using NR::Y; - NR::Matrix tf = *transform; + using Geom::X; + using Geom::Y; - 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); + Geom::Point zero(0, 0); + Geom::Point one(1, 1); + Geom::Point p0(zero * transform); + Geom::Point p1(one * transform); + Geom::Point p(p1 - p0); double scale = sqrt( (p[X]*p[X]) + (p[Y]*p[Y]) ) / sqrt(2); @@ -378,12 +407,18 @@ PrintEmfWin32::create_pen(SPStyle const *style, const NRMatrix *transform) hpenOld = (HPEN) SelectObject( hdc, hpen ); if (linejoin == PS_JOIN_MITER) { + float oldmiterlimit; float miterlimit = style->stroke_miterlimit.value; + + miterlimit = miterlimit * 10.0 / 4.0; if (miterlimit < 1) - miterlimit = 4.0; + miterlimit = 10.0; + + miterlimit = miterlimit * IN_PER_PX * dwDPI; + SetMiterLimit( hdc, - miterlimit * IN_PER_PX * dwDPI, + miterlimit, &oldmiterlimit ); } @@ -411,85 +446,49 @@ PrintEmfWin32::destroy_pen() void PrintEmfWin32::flush_fill() { - if (fill_path) { - print_bpath(fill_path, &fill_transform, &fill_pbox); - FillPath( hdc ); + if (!fill_pathv.empty()) { + stroke_and_fill = false; + fill_only = true; + print_pathv(fill_pathv, fill_transform); + fill_only = false; + if (!simple_shape) + FillPath( hdc ); destroy_brush(); - delete[] fill_path; - fill_path = NULL; + fill_pathv.clear(); } } - -NArtBpath * -PrintEmfWin32::copy_bpath(const NArtBpath *bp) -{ - NArtBpath *tmp = (NArtBpath *) bp; - int num = 1; - - while (tmp->code != NR_END) { - num++; - tmp += 1; - } - - tmp = new NArtBpath[num]; - while (num--) { - tmp[num] = bp[num]; - } - - return tmp; -} - - -int -PrintEmfWin32::cmp_bpath(const NArtBpath *bp1, const NArtBpath *bp2) +unsigned int +PrintEmfWin32::bind(Inkscape::Extension::Print * /*mod*/, Geom::Matrix const *transform, float /*opacity*/) { - if (!bp1 || !bp2) { - return 1; - } + Geom::Matrix tr = *transform; - while (bp1->code != NR_END && bp2->code != NR_END) { - if (bp1->code != bp2->code) { - return 1; - } - - if ( fabs(bp1->x1 - bp2->x1) > 0.00000001 || - fabs(bp1->y1 - bp2->y1) > 0.00000001 || - fabs(bp1->x2 - bp2->x2) > 0.00000001 || - fabs(bp1->y2 - bp2->y2) > 0.00000001 || - fabs(bp1->x3 - bp2->x3) > 0.00000001 || - fabs(bp1->y3 - bp2->y3) > 0.00000001 ) - { - return 1; - } - - bp1 += 1; - bp2 += 1; + if (m_tr_stack.size()) { + Geom::Matrix tr_top = m_tr_stack.top(); + m_tr_stack.push(tr * tr_top); + } else { + m_tr_stack.push(tr); } - - 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; + return 1; } unsigned int -PrintEmfWin32::release(Inkscape::Extension::Print *mod) +PrintEmfWin32::release(Inkscape::Extension::Print * /*mod*/) { - return 0; + m_tr_stack.pop(); + return 1; } unsigned int -PrintEmfWin32::fill(Inkscape::Extension::Print *mod, - NRBPath const *bpath, NRMatrix const *transform, SPStyle const *style, - NRRect const *pbox, NRRect const *dbox, NRRect const *bbox) +PrintEmfWin32::fill(Inkscape::Extension::Print * /*mod*/, + Geom::PathVector const &pathv, Geom::Matrix const * /*transform*/, SPStyle const *style, + NRRect const * /*pbox*/, NRRect const * /*dbox*/, NRRect const * /*bbox*/) { if (!hdc) return 0; + Geom::Matrix tf = m_tr_stack.top(); + flush_fill(); // flush any pending fills if (style->fill.isColor()) { @@ -500,9 +499,9 @@ PrintEmfWin32::fill(Inkscape::Extension::Print *mod, return 0; } - fill_path = copy_bpath( bpath->path ); - fill_transform = *transform; - fill_pbox = *pbox; + fill_pathv.clear(); + std::copy(pathv.begin(), pathv.end(), std::back_inserter(fill_pathv)); + fill_transform = tf; // postpone fill in case of stroke-and-fill @@ -511,34 +510,37 @@ PrintEmfWin32::fill(Inkscape::Extension::Print *mod, unsigned int -PrintEmfWin32::stroke (Inkscape::Extension::Print *mod, - const NRBPath *bpath, const NRMatrix *transform, const SPStyle *style, - const NRRect *pbox, const NRRect *dbox, const NRRect *bbox) +PrintEmfWin32::stroke (Inkscape::Extension::Print * /*mod*/, + Geom::PathVector const &pathv, const Geom::Matrix * /*transform*/, const SPStyle *style, + const NRRect * /*pbox*/, const NRRect * /*dbox*/, const NRRect * /*bbox*/) { if (!hdc) return 0; - bool stroke_and_fill = ( cmp_bpath( bpath->path, fill_path ) == 0 ); + Geom::Matrix tf = m_tr_stack.top(); + + stroke_and_fill = ( pathv == fill_pathv ); if (!stroke_and_fill) { flush_fill(); // flush any pending fills } if (style->stroke.isColor()) { - create_pen(style, transform); + create_pen(style, tf); } else { - // create_pen(NULL, transform); + // create_pen(NULL, tf); return 0; } - print_bpath(bpath->path, transform, pbox); + print_pathv(pathv, tf); if (stroke_and_fill) { - StrokeAndFillPath( hdc ); + if (!simple_shape) + StrokeAndFillPath( hdc ); destroy_brush(); - delete[] fill_path; - fill_path = NULL; + fill_pathv.clear(); } else { - StrokePath( hdc ); + if (!simple_shape) + StrokePath( hdc ); } destroy_pen(); @@ -547,56 +549,280 @@ PrintEmfWin32::stroke (Inkscape::Extension::Print *mod, } +bool +PrintEmfWin32::print_simple_shape(Geom::PathVector const &pathv, const Geom::Matrix &transform) +{ + Geom::PathVector pv = pathv_to_linear_and_cubic_beziers( pathv * transform ); + + int nodes = 0; + int moves = 0; + int lines = 0; + int curves = 0; + + for (Geom::PathVector::const_iterator pit = pv.begin(); pit != pv.end(); ++pit) + { + moves++; + nodes++; + + for (Geom::Path::const_iterator cit = pit->begin(); cit != pit->end_open(); ++cit) + { + nodes++; + + if ( is_straight_curve(*cit) ) { + lines++; + } + else if (Geom::CubicBezier const *cubic = dynamic_cast(&*cit)) { + cubic = cubic; + curves++; + } + } + } + + if (!nodes) + return false; + + POINT *lpPoints = new POINT[moves + lines + curves*3]; + int i = 0; + + /** + * For all Subpaths in the + */ + for (Geom::PathVector::const_iterator pit = pv.begin(); pit != pv.end(); ++pit) + { + using Geom::X; + using Geom::Y; + + Geom::Point p0 = pit->initialPoint(); + + p0[X] = (p0[X] * IN_PER_PX * dwDPI); + p0[Y] = (p0[Y] * IN_PER_PX * dwDPI); + + LONG const x0 = (LONG) round(p0[X]); + LONG const y0 = (LONG) round(rc.bottom-p0[Y]); + + lpPoints[i].x = x0; + lpPoints[i].y = y0; + i = i + 1; + + /** + * For all segments in the subpath + */ + for (Geom::Path::const_iterator cit = pit->begin(); cit != pit->end_open(); ++cit) + { + if ( is_straight_curve(*cit) ) + { + //Geom::Point p0 = cit->initialPoint(); + Geom::Point p1 = cit->finalPoint(); + + //p0[X] = (p0[X] * IN_PER_PX * dwDPI); + p1[X] = (p1[X] * IN_PER_PX * dwDPI); + //p0[Y] = (p0[Y] * IN_PER_PX * dwDPI); + p1[Y] = (p1[Y] * IN_PER_PX * dwDPI); + + //LONG const x0 = (LONG) round(p0[X]); + //LONG const y0 = (LONG) round(rc.bottom-p0[Y]); + LONG const x1 = (LONG) round(p1[X]); + LONG const y1 = (LONG) round(rc.bottom-p1[Y]); + + lpPoints[i].x = x1; + lpPoints[i].y = y1; + i = i + 1; + } + else if (Geom::CubicBezier const *cubic = dynamic_cast(&*cit)) + { + std::vector points = cubic->points(); + //Geom::Point p0 = points[0]; + Geom::Point p1 = points[1]; + Geom::Point p2 = points[2]; + Geom::Point p3 = points[3]; + + //p0[X] = (p0[X] * IN_PER_PX * dwDPI); + p1[X] = (p1[X] * IN_PER_PX * dwDPI); + p2[X] = (p2[X] * IN_PER_PX * dwDPI); + p3[X] = (p3[X] * IN_PER_PX * dwDPI); + //p0[Y] = (p0[Y] * IN_PER_PX * dwDPI); + p1[Y] = (p1[Y] * IN_PER_PX * dwDPI); + p2[Y] = (p2[Y] * IN_PER_PX * dwDPI); + p3[Y] = (p3[Y] * IN_PER_PX * dwDPI); + + //LONG const x0 = (LONG) round(p0[X]); + //LONG const y0 = (LONG) round(rc.bottom-p0[Y]); + LONG const x1 = (LONG) round(p1[X]); + LONG const y1 = (LONG) round(rc.bottom-p1[Y]); + LONG const x2 = (LONG) round(p2[X]); + LONG const y2 = (LONG) round(rc.bottom-p2[Y]); + LONG const x3 = (LONG) round(p3[X]); + LONG const y3 = (LONG) round(rc.bottom-p3[Y]); + + POINT pt[3]; + pt[0].x = x1; + pt[0].y = y1; + pt[1].x = x2; + pt[1].y = y2; + pt[2].x = x3; + pt[2].y = y3; + + lpPoints[i].x = x1; + lpPoints[i].y = y1; + lpPoints[i+1].x = x2; + lpPoints[i+1].y = y2; + lpPoints[i+2].x = x3; + lpPoints[i+2].y = y3; + i = i + 3; + } + } + } + + bool done = false; + bool closed = (lpPoints[0].x == lpPoints[i-1].x) && (lpPoints[0].y == lpPoints[i-1].y); + bool polygon = false; + bool rectangle = false; + bool ellipse = false; + + if (moves == 1 && moves+lines == nodes && closed) { + polygon = true; +// if (nodes==5) { // disable due to LP Bug 407394 +// if (lpPoints[0].x == lpPoints[3].x && lpPoints[1].x == lpPoints[2].x && +// lpPoints[0].y == lpPoints[1].y && lpPoints[2].y == lpPoints[3].y) +// { +// rectangle = true; +// } +// } + } + else if (moves == 1 && nodes == 5 && moves+curves == nodes && closed) { +// if (lpPoints[0].x == lpPoints[1].x && lpPoints[1].x == lpPoints[11].x && +// lpPoints[5].x == lpPoints[6].x && lpPoints[6].x == lpPoints[7].x && +// lpPoints[2].x == lpPoints[10].x && lpPoints[3].x == lpPoints[9].x && lpPoints[4].x == lpPoints[8].x && +// lpPoints[2].y == lpPoints[3].y && lpPoints[3].y == lpPoints[4].y && +// lpPoints[8].y == lpPoints[9].y && lpPoints[9].y == lpPoints[10].y && +// lpPoints[5].y == lpPoints[1].y && lpPoints[6].y == lpPoints[0].y && lpPoints[7].y == lpPoints[11].y) +// { // disable due to LP Bug 407394 +// ellipse = true; +// } + } + + if (polygon || ellipse) { + HPEN hpenTmp = NULL; + HPEN hpenOld = NULL; + HBRUSH hbrushTmp = NULL; + HBRUSH hbrushOld = NULL; + + if (!stroke_and_fill) { + if (fill_only) { + hpenTmp = (HPEN) GetStockObject(NULL_PEN); + hpenOld = (HPEN) SelectObject( hdc, hpenTmp ); + } + else { // if (stroke_only) + hbrushTmp = (HBRUSH) GetStockObject(NULL_BRUSH); + hbrushOld = (HBRUSH) SelectObject( hdc, hbrushTmp ); + } + } + + if (polygon) { + if (rectangle) + Rectangle( hdc, lpPoints[0].x, lpPoints[0].y, lpPoints[2].x, lpPoints[2].y ); + else + Polygon( hdc, lpPoints, nodes ); + } + else if (ellipse) { + Ellipse( hdc, lpPoints[6].x, lpPoints[3].y, lpPoints[0].x, lpPoints[9].y); + } + + done = true; + + if (hpenOld) + SelectObject( hdc, hpenOld ); + if (hpenTmp) + DeleteObject( hpenTmp ); + if (hbrushOld) + SelectObject( hdc, hbrushOld ); + if (hbrushTmp) + DeleteObject( hbrushTmp ); + } + + delete[] lpPoints; + + return done; +} + unsigned int -PrintEmfWin32::print_bpath(const NArtBpath *bp, const NRMatrix *transform, NRRect const *pbox) +PrintEmfWin32::print_pathv(Geom::PathVector const &pathv, const Geom::Matrix &transform) { - unsigned int closed; - NR::Matrix tf = *transform; + simple_shape = print_simple_shape(pathv, transform); + + if (simple_shape) + return TRUE; + Geom::PathVector pv = pathv_to_linear_and_cubic_beziers( pathv * transform ); + BeginPath( hdc ); - closed = FALSE; - while (bp->code != NR_END) { - using NR::X; - using NR::Y; - - NR::Point p1(bp->c(1) * tf); - NR::Point p2(bp->c(2) * tf); - NR::Point p3(bp->c(3) * tf); - - p1[X] = (p1[X] * IN_PER_PX * dwDPI); - p2[X] = (p2[X] * IN_PER_PX * dwDPI); - p3[X] = (p3[X] * IN_PER_PX * dwDPI); - p1[Y] = (p1[Y] * IN_PER_PX * dwDPI); - p2[Y] = (p2[Y] * IN_PER_PX * dwDPI); - p3[Y] = (p3[Y] * IN_PER_PX * dwDPI); - - LONG const x1 = (LONG) round(p1[X]); - LONG const y1 = (LONG) round(rc.bottom-p1[Y]); - LONG const x2 = (LONG) round(p2[X]); - LONG const y2 = (LONG) round(rc.bottom-p2[Y]); - LONG const x3 = (LONG) round(p3[X]); - LONG const y3 = (LONG) round(rc.bottom-p3[Y]); - - switch (bp->code) { - case NR_MOVETO: - if (closed) { - CloseFigure( hdc ); - } - closed = TRUE; - MoveToEx( hdc, x3, y3, NULL ); - break; - case NR_MOVETO_OPEN: - if (closed) { - CloseFigure( hdc ); - } - closed = FALSE; - MoveToEx( hdc, x3, y3, NULL ); - break; - case NR_LINETO: - LineTo( hdc, x3, y3 ); - break; - case NR_CURVETO: + + /** + * For all Subpaths in the + */ + for (Geom::PathVector::const_iterator pit = pv.begin(); pit != pv.end(); ++pit) + { + using Geom::X; + using Geom::Y; + + Geom::Point p0 = pit->initialPoint(); + + p0[X] = (p0[X] * IN_PER_PX * dwDPI); + p0[Y] = (p0[Y] * IN_PER_PX * dwDPI); + + LONG const x0 = (LONG) round(p0[X]); + LONG const y0 = (LONG) round(rc.bottom-p0[Y]); + + MoveToEx( hdc, x0, y0, NULL ); + + /** + * For all segments in the subpath + */ + for (Geom::Path::const_iterator cit = pit->begin(); cit != pit->end_open(); ++cit) + { + if ( is_straight_curve(*cit) ) + { + //Geom::Point p0 = cit->initialPoint(); + Geom::Point p1 = cit->finalPoint(); + + //p0[X] = (p0[X] * IN_PER_PX * dwDPI); + p1[X] = (p1[X] * IN_PER_PX * dwDPI); + //p0[Y] = (p0[Y] * IN_PER_PX * dwDPI); + p1[Y] = (p1[Y] * IN_PER_PX * dwDPI); + + //LONG const x0 = (LONG) round(p0[X]); + //LONG const y0 = (LONG) round(rc.bottom-p0[Y]); + LONG const x1 = (LONG) round(p1[X]); + LONG const y1 = (LONG) round(rc.bottom-p1[Y]); + + LineTo( hdc, x1, y1 ); + } + else if (Geom::CubicBezier const *cubic = dynamic_cast(&*cit)) { + std::vector points = cubic->points(); + //Geom::Point p0 = points[0]; + Geom::Point p1 = points[1]; + Geom::Point p2 = points[2]; + Geom::Point p3 = points[3]; + + //p0[X] = (p0[X] * IN_PER_PX * dwDPI); + p1[X] = (p1[X] * IN_PER_PX * dwDPI); + p2[X] = (p2[X] * IN_PER_PX * dwDPI); + p3[X] = (p3[X] * IN_PER_PX * dwDPI); + //p0[Y] = (p0[Y] * IN_PER_PX * dwDPI); + p1[Y] = (p1[Y] * IN_PER_PX * dwDPI); + p2[Y] = (p2[Y] * IN_PER_PX * dwDPI); + p3[Y] = (p3[Y] * IN_PER_PX * dwDPI); + + //LONG const x0 = (LONG) round(p0[X]); + //LONG const y0 = (LONG) round(rc.bottom-p0[Y]); + LONG const x1 = (LONG) round(p1[X]); + LONG const y1 = (LONG) round(rc.bottom-p1[Y]); + LONG const x2 = (LONG) round(p2[X]); + LONG const y2 = (LONG) round(rc.bottom-p2[Y]); + LONG const x3 = (LONG) round(p3[X]); + LONG const y3 = (LONG) round(rc.bottom-p3[Y]); + POINT pt[3]; pt[0].x = x1; pt[0].y = y1; @@ -606,19 +832,21 @@ PrintEmfWin32::print_bpath(const NArtBpath *bp, const NRMatrix *transform, NRRec pt[2].y = y3; PolyBezierTo( hdc, pt, 3 ); - break; } - default: - break; + else + { + g_warning("logical error, because pathv_to_linear_and_cubic_beziers was used"); + } + } + + if (pit->end_default() == pit->end_closed()) { + CloseFigure( hdc ); } - bp += 1; - } - if (closed) { - CloseFigure( hdc ); } + EndPath( hdc ); - return closed; + return TRUE; } @@ -629,8 +857,8 @@ PrintEmfWin32::textToPath(Inkscape::Extension::Print * ext) } unsigned int -PrintEmfWin32::text(Inkscape::Extension::Print *mod, char const *text, NR::Point p, - SPStyle const *const style) +PrintEmfWin32::text(Inkscape::Extension::Print * /*mod*/, char const *text, Geom::Point p, + SPStyle const *const style) { if (!hdc) return 0; @@ -658,21 +886,17 @@ PrintEmfWin32::text(Inkscape::Extension::Print *mod, char const *text, NR::Point 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 : + style->font_weight.computed == SP_CSS_FONT_WEIGHT_100 ? FW_THIN : + style->font_weight.computed == SP_CSS_FONT_WEIGHT_200 ? FW_EXTRALIGHT : + style->font_weight.computed == SP_CSS_FONT_WEIGHT_300 ? FW_LIGHT : + style->font_weight.computed == SP_CSS_FONT_WEIGHT_400 ? FW_NORMAL : + style->font_weight.computed == SP_CSS_FONT_WEIGHT_500 ? FW_MEDIUM : + style->font_weight.computed == SP_CSS_FONT_WEIGHT_600 ? FW_SEMIBOLD : + style->font_weight.computed == SP_CSS_FONT_WEIGHT_700 ? FW_BOLD : + style->font_weight.computed == SP_CSS_FONT_WEIGHT_800 ? FW_EXTRABOLD : + style->font_weight.computed == SP_CSS_FONT_WEIGHT_900 ? FW_HEAVY : FW_NORMAL; - lf->lfItalic = (style->font_style.value == SP_CSS_FONT_STYLE_ITALIC); + lf->lfItalic = (style->font_style.computed == SP_CSS_FONT_STYLE_ITALIC); lf->lfUnderline = style->text_decoration.underline; lf->lfStrikeOut = style->text_decoration.line_through; lf->lfCharSet = DEFAULT_CHARSET; @@ -698,21 +922,17 @@ PrintEmfWin32::text(Inkscape::Extension::Print *mod, char const *text, NR::Point 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 : + style->font_weight.computed == SP_CSS_FONT_WEIGHT_100 ? FW_THIN : + style->font_weight.computed == SP_CSS_FONT_WEIGHT_200 ? FW_EXTRALIGHT : + style->font_weight.computed == SP_CSS_FONT_WEIGHT_300 ? FW_LIGHT : + style->font_weight.computed == SP_CSS_FONT_WEIGHT_400 ? FW_NORMAL : + style->font_weight.computed == SP_CSS_FONT_WEIGHT_500 ? FW_MEDIUM : + style->font_weight.computed == SP_CSS_FONT_WEIGHT_600 ? FW_SEMIBOLD : + style->font_weight.computed == SP_CSS_FONT_WEIGHT_700 ? FW_BOLD : + style->font_weight.computed == SP_CSS_FONT_WEIGHT_800 ? FW_EXTRABOLD : + style->font_weight.computed == SP_CSS_FONT_WEIGHT_900 ? FW_HEAVY : FW_NORMAL; - lf->lfItalic = (style->font_style.value == SP_CSS_FONT_STYLE_ITALIC); + lf->lfItalic = (style->font_style.computed == SP_CSS_FONT_STYLE_ITALIC); lf->lfUnderline = style->text_decoration.underline; lf->lfStrikeOut = style->text_decoration.line_through; lf->lfCharSet = DEFAULT_CHARSET; @@ -728,37 +948,42 @@ PrintEmfWin32::text(Inkscape::Extension::Print *mod, char const *text, NR::Point 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); + // Text alignment: + // - (x,y) coordinates received by this filter are those of the point where the text + // actually starts, and already takes into account the text object's alignment; + // - for this reason, the EMF text alignment must always be TA_BASELINE|TA_LEFT. + SetTextAlign(hdc, TA_BASELINE | TA_LEFT); + + // Transparent text background + SetBkMode(hdc, TRANSPARENT); + + Geom::Matrix tf = m_tr_stack.top(); + + p = p * tf; + p[Geom::X] = (p[Geom::X] * IN_PER_PX * dwDPI); + p[Geom::Y] = (p[Geom::Y] * IN_PER_PX * dwDPI); - p = p * text_transform; - p[NR::X] = (p[NR::X] * IN_PER_PX * dwDPI); - p[NR::Y] = (p[NR::Y] * IN_PER_PX * dwDPI); + LONG const xpos = (LONG) round(p[Geom::X]); + LONG const ypos = (LONG) round(rc.bottom-p[Geom::Y]); 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)); + TextOutW(hdc, xpos, ypos, (WCHAR*)unicode_text, wcslen((wchar_t*)unicode_text)); } else { - TextOutA(hdc, p[NR::X], p[NR::Y], (CHAR*)text, strlen((char*)text)); + TextOutA(hdc, xpos, ypos, (CHAR*)text, strlen((char*)text)); } SelectObject(hdc, hfontOld); DeleteObject(hfont); - return 0; - - - return 0; } @@ -769,12 +994,12 @@ PrintEmfWin32::init (void) /* EMF print */ ext = Inkscape::Extension::build_from_mem( - "\n" + "\n" "Enhanced Metafile Print\n" "org.inkscape.print.emf.win32\n" "\n" - "TRUE\n" - "TRUE\n" + "true\n" + "true\n" "\n" "", new PrintEmfWin32()); @@ -797,4 +1022,4 @@ PrintEmfWin32::init (void) fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :