Code

emf import : recalculate text alignment for rotated text (Bug 341847)
[inkscape.git] / src / extension / internal / emf-win32-inout.cpp
index 8dd793f9238063e93af01d04183c3ffb41362f11..c817f6d4686cee5af2a6308c9749bc9f24a4fcef 100644 (file)
@@ -1,15 +1,15 @@
-/** \file
- * Enhanced Metafile Input and Output.
+/** @file
+ * @brief Windows-only Enhanced Metafile input and output.
  */
-/*
- * Authors:
+/* Authors:
  *   Ulf Erikson <ulferikson@users.sf.net>
+ *   Jon A. Cruz <jon@joncruz.org>
+ *   Abhishek Sharma
  *
  * Copyright (C) 2006-2008 Authors
  *
  * Released under GNU GPL, read the file 'COPYING' for more information
- */
-/*
+ *
  * References:
  *  - How to Create & Play Enhanced Metafiles in Win32
  *      http://support.microsoft.com/kb/q145999/
@@ -80,6 +80,7 @@ namespace Inkscape {
 namespace Extension {
 namespace Internal {
 
+static float device_scale = DEVICESCALE;
 
 EmfWin32::EmfWin32 (void) // The null constructor
 {
@@ -111,30 +112,31 @@ emf_print_document_to_file(SPDocument *doc, gchar const *filename)
     gchar *oldoutput;
     unsigned int ret;
 
-    sp_document_ensure_up_to_date(doc);
+    doc->ensureUpToDate();
 
     mod = Inkscape::Extension::get_print(PRINT_EMF_WIN32);
     oldconst = mod->get_param_string("destination");
     oldoutput = g_strdup(oldconst);
-    mod->set_param_string("destination", (gchar *)filename);
+    mod->set_param_string("destination", filename);
 
 /* Start */
     context.module = mod;
     /* fixme: This has to go into module constructor somehow */
     /* Create new arena */
-    mod->base = SP_ITEM(sp_document_root(doc));
+    mod->base = SP_ITEM(doc->getRoot());
     mod->arena = NRArena::create();
-    mod->dkey = sp_item_display_key_new(1);
-    mod->root = sp_item_invoke_show(mod->base, mod->arena, mod->dkey, SP_ITEM_SHOW_DISPLAY);
+    mod->dkey = SPItem::display_key_new(1);
+    mod->root = mod->base->invoke_show(mod->arena, mod->dkey, SP_ITEM_SHOW_DISPLAY);
     /* Print document */
     ret = mod->begin(doc);
     if (ret) {
+        g_free(oldoutput);
         throw Inkscape::Extension::Output::save_failed();
     }
-    sp_item_invoke_print(mod->base, &context);
+    mod->base->invoke_print(&context);
     ret = mod->finish();
     /* Release arena */
-    sp_item_invoke_hide(mod->base, mod->dkey);
+    mod->base->invoke_hide(mod->dkey);
     mod->base = NULL;
     mod->root = NULL;
     nr_object_unref((NRObject *) mod->arena);
@@ -149,7 +151,7 @@ emf_print_document_to_file(SPDocument *doc, gchar const *filename)
 
 
 void
-EmfWin32::save (Inkscape::Extension::Output *mod, SPDocument *doc, const gchar *uri)
+EmfWin32::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar const *filename)
 {
     Inkscape::Extension::Extension * ext;
 
@@ -161,10 +163,7 @@ EmfWin32::save (Inkscape::Extension::Output *mod, SPDocument *doc, const gchar *
     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);
+    emf_print_document_to_file(doc, filename);
 
     ext->set_param_bool("textToPath", old_textToPath);
 
@@ -342,7 +341,7 @@ pix_to_x_point(PEMF_CALLBACK_DATA d, double px, double py)
     double ppy = _pix_y_to_point(d, py);
 
     double x = ppx * d->dc[d->level].worldTransform.eM11 + ppy * d->dc[d->level].worldTransform.eM21 + d->dc[d->level].worldTransform.eDx;
-    x *= d->dc[d->level].ScaleOutX ? d->dc[d->level].ScaleOutX : DEVICESCALE;
+    x *= d->dc[d->level].ScaleOutX ? d->dc[d->level].ScaleOutX : device_scale;
     
     return x;
 }
@@ -354,7 +353,7 @@ pix_to_y_point(PEMF_CALLBACK_DATA d, double px, double py)
     double ppy = _pix_y_to_point(d, py);
 
     double y = ppx * d->dc[d->level].worldTransform.eM12 + ppy * d->dc[d->level].worldTransform.eM22 + d->dc[d->level].worldTransform.eDy;
-    y *= d->dc[d->level].ScaleOutY ? d->dc[d->level].ScaleOutY : DEVICESCALE;
+    y *= d->dc[d->level].ScaleOutY ? d->dc[d->level].ScaleOutY : device_scale;
     
     return y;
 }
@@ -366,9 +365,9 @@ pix_to_size_point(PEMF_CALLBACK_DATA d, double px)
     double ppy = 0;
 
     double dx = ppx * d->dc[d->level].worldTransform.eM11 + ppy * d->dc[d->level].worldTransform.eM21;
-    dx *= d->dc[d->level].ScaleOutX ? d->dc[d->level].ScaleOutX : DEVICESCALE;
+    dx *= d->dc[d->level].ScaleOutX ? d->dc[d->level].ScaleOutX : device_scale;
     double dy = ppx * d->dc[d->level].worldTransform.eM12 + ppy * d->dc[d->level].worldTransform.eM22;
-    dy *= d->dc[d->level].ScaleOutY ? d->dc[d->level].ScaleOutY : DEVICESCALE;
+    dy *= d->dc[d->level].ScaleOutY ? d->dc[d->level].ScaleOutY : device_scale;
 
     double tmp = sqrt(dx * dx + dy * dy);
     return tmp;
@@ -737,7 +736,7 @@ assert_empty_path(PEMF_CALLBACK_DATA d, const char * /*fun*/)
 
 
 static int CALLBACK
-myEnhMetaFileProc(HDC /*hDC*/, HANDLETABLE * /*lpHTable*/, ENHMETARECORD *lpEMFR, int /*nObj*/, LPARAM lpData)
+myEnhMetaFileProc(HDC /*hDC*/, HANDLETABLE * /*lpHTable*/, ENHMETARECORD const *lpEMFR, int /*nObj*/, LPARAM lpData)
 {
     PEMF_CALLBACK_DATA d;
     SVGOStringStream tmp_outsvg;
@@ -787,14 +786,18 @@ myEnhMetaFileProc(HDC /*hDC*/, HANDLETABLE * /*lpHTable*/, ENHMETARECORD *lpEMFR
             d->xDPI = 2540;
             d->yDPI = 2540;
 
-            d->dc[d->level].PixelsInX = pEmr->rclFrame.right - pEmr->rclFrame.left;
-            d->dc[d->level].PixelsInY = pEmr->rclFrame.bottom - pEmr->rclFrame.top;
+            d->dc[d->level].PixelsInX = pEmr->rclFrame.right;  // - pEmr->rclFrame.left;
+            d->dc[d->level].PixelsInY = pEmr->rclFrame.bottom; // - pEmr->rclFrame.top;
 
             d->MMX = d->dc[d->level].PixelsInX / 100.0;
             d->MMY = d->dc[d->level].PixelsInY / 100.0;
 
             d->dc[d->level].PixelsOutX = d->MMX * PX_PER_MM;
             d->dc[d->level].PixelsOutY = d->MMY * PX_PER_MM;
+
+            // calculate ratio of Inkscape dpi/device dpi
+            if (pEmr->szlMillimeters.cx && pEmr->szlDevice.cx)
+                device_scale = PX_PER_MM*pEmr->szlMillimeters.cx/pEmr->szlDevice.cx;
             
             tmp_outsvg <<
                 "  width=\"" << d->MMX << "mm\"\n" <<
@@ -1073,8 +1076,8 @@ myEnhMetaFileProc(HDC /*hDC*/, HANDLETABLE * /*lpHTable*/, ENHMETARECORD *lpEMFR
                 d->dc[d->level].ScaleOutY = (double) d->dc[d->level].PixelsOutY / (double) d->dc[d->level].sizeView.cy;
             }
             else {
-                d->dc[d->level].ScaleOutX = DEVICESCALE;
-                d->dc[d->level].ScaleOutY = DEVICESCALE;
+                d->dc[d->level].ScaleOutX = device_scale;
+                d->dc[d->level].ScaleOutY = device_scale;
             }
 
             break;
@@ -1124,8 +1127,8 @@ myEnhMetaFileProc(HDC /*hDC*/, HANDLETABLE * /*lpHTable*/, ENHMETARECORD *lpEMFR
                 d->dc[d->level].ScaleOutY = (double) d->dc[d->level].PixelsOutY / (double) d->dc[d->level].sizeView.cy;
             }
             else {
-                d->dc[d->level].ScaleOutX = DEVICESCALE;
-                d->dc[d->level].ScaleOutY = DEVICESCALE;
+                d->dc[d->level].ScaleOutX = device_scale;
+                d->dc[d->level].ScaleOutY = device_scale;
             }
 
             break;
@@ -1774,8 +1777,13 @@ myEnhMetaFileProc(HDC /*hDC*/, HANDLETABLE * /*lpHTable*/, ENHMETARECORD *lpEMFR
             }
 
             if (!(d->dc[d->level].textAlign & TA_BOTTOM))
-                y1 += fabs(d->dc[d->level].style.font_size.computed);
-            
+                if (d->dc[d->level].style.text_transform.value) {
+                    x1 += std::sin(d->dc[d->level].style.text_transform.value*M_PI/180.0)*fabs(d->dc[d->level].style.font_size.computed);
+                    y1 += std::cos(d->dc[d->level].style.text_transform.value*M_PI/180.0)*fabs(d->dc[d->level].style.font_size.computed);
+                }
+                else
+                    y1 += fabs(d->dc[d->level].style.font_size.computed);
+
             double x = pix_to_x_point(d, x1, y1);
             double y = pix_to_y_point(d, x1, y1);
 
@@ -2357,7 +2365,8 @@ EmfWin32::open( Inkscape::Extension::Input * /*mod*/, const gchar *uri )
                 d.pDesc[lstrlen(d.pDesc)] = '#';
         }
 
-        EnumEnhMetaFile(NULL, hemf, myEnhMetaFileProc, (LPVOID) &d, NULL);
+        // This ugly reinterpret_cast is to prevent old versions of gcc from whining about a mismatch in the const-ness of the arguments
+        EnumEnhMetaFile(NULL, hemf, reinterpret_cast<ENHMFENUMPROC>(myEnhMetaFileProc), (LPVOID) &d, NULL);
         DeleteEnhMetaFile(hemf);
     }
     else {
@@ -2370,7 +2379,7 @@ EmfWin32::open( Inkscape::Extension::Input * /*mod*/, const gchar *uri )
 
 //    std::cout << "SVG Output: " << std::endl << *(d.outsvg) << std::endl;
 
-    SPDocument *doc = sp_document_new_from_mem(d.outsvg->c_str(), d.outsvg->length(), TRUE);
+    SPDocument *doc = SPDocument::createNewDocFromMem(d.outsvg->c_str(), d.outsvg->length(), TRUE);
 
     delete d.outsvg;
     delete d.path;
@@ -2447,17 +2456,14 @@ EmfWin32::init (void)
 
 } } }  /* namespace Inkscape, Extension, Implementation */
 
-
 #endif /* WIN32 */
-
-
 /*
   Local Variables:
-  mode:cpp
+  mode:c++
   c-file-style:"stroustrup"
-  c-file-offsets:((innamespace . 0)(inline-open . 0))
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
   indent-tabs-mode:nil
   fill-column:99
   End:
 */
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :