Code

Pot and Dutch translation update
[inkscape.git] / src / extension / internal / pdfinput / svg-builder.cpp
index e28264eff9aa2166476c14103418e9ef47c7605d..e343dbf338a62d404c7c2f6c12679d7acc532dcb 100644 (file)
@@ -14,6 +14,8 @@
 # include <config.h>
 #endif
 
+#include <string> 
+
 #ifdef HAVE_POPPLER
 
 #include "svg-builder.h"
@@ -34,7 +36,6 @@
 #include "io/stringstream.h"
 #include "io/base64stream.h"
 #include "display/nr-filter-utils.h"
-#include "libnr/nr-matrix-ops.h"
 #include "libnr/nr-macros.h"
 #include "libnrtype/font-instance.h"
 
@@ -89,6 +90,7 @@ SvgBuilder::SvgBuilder(SPDocument *document, gchar *docname, XRef *xref) {
     // Set default preference settings
     _preferences = _xml_doc->createElement("svgbuilder:prefs");
     _preferences->setAttribute("embedImages", "1");
+    _preferences->setAttribute("localFonts", "1");
 }
 
 SvgBuilder::SvgBuilder(SvgBuilder *parent, Inkscape::XML::Node *root) {
@@ -113,6 +115,15 @@ void SvgBuilder::_init() {
     _current_font = NULL;
     _current_state = NULL;
 
+    // Fill _availableFontNames (Bug LP #179589) (code cfr. FontLister)
+    FamilyToStylesMap familyStyleMap;
+    font_factory::Default()->GetUIFamiliesAndStyles(&familyStyleMap);
+    for (FamilyToStylesMap::iterator iter = familyStyleMap.begin();
+         iter != familyStyleMap.end();
+         iter++) {
+        _availableFontNames.push_back(iter->first.c_str());
+    }
+
     _transp_group_stack = NULL;
     SvgGraphicsState initial_state;
     initial_state.softmask = NULL;
@@ -215,12 +226,13 @@ Inkscape::XML::Node *SvgBuilder::getContainer() {
 }
 
 static gchar *svgConvertRGBToText(double r, double g, double b) {
+    using Inkscape::Filters::clamp;
     static gchar tmp[1023] = {0};
     snprintf(tmp, 1023,
              "#%02x%02x%02x",
-             NR::clamp(SP_COLOR_F_TO_U(r)),
-             NR::clamp(SP_COLOR_F_TO_U(g)),
-             NR::clamp(SP_COLOR_F_TO_U(b)));
+             clamp(SP_COLOR_F_TO_U(r)),
+             clamp(SP_COLOR_F_TO_U(g)),
+             clamp(SP_COLOR_F_TO_U(b)));
     return (gchar *)&tmp;
 }
 
@@ -596,7 +608,8 @@ gchar *SvgBuilder::_createPattern(GfxPattern *pattern, GfxState *state, bool is_
         if ( pattern->getType() == 2 ) {  // Shading pattern
             GfxShadingPattern *shading_pattern = (GfxShadingPattern*)pattern;
             id = _createGradient(shading_pattern->getShading(),
-                                 shading_pattern->getMatrix());
+                                 shading_pattern->getMatrix(),
+                                 !is_stroke);
         } else if ( pattern->getType() == 1 ) {   // Tiling pattern
             id = _createTilingPattern((GfxTilingPattern*)pattern, state, is_stroke);
         }
@@ -850,6 +863,67 @@ void SvgBuilder::updateStyle(GfxState *state) {
     }
 }
 
+/*
+    MatchingChars
+    Count for how many characters s1 matches sp taking into account 
+    that a space in sp may be removed or replaced by some other tokens
+    specified in the code. (Bug LP #179589)
+*/
+static int MatchingChars(std::string s1, std::string sp)
+{
+    unsigned int is = 0;
+    unsigned int ip = 0;
+
+    while(is < s1.length() && ip < sp.length()) {
+        if (s1[is] == sp[ip]) {
+            is++; ip++;
+        } else if (sp[ip] == ' ') {
+            ip++;
+            if (s1[is] == '_') { // Valid matches to spaces in sp.
+                is++;
+            }
+        } else {
+            break;
+        }
+    }
+    return(ip);
+}
+
+/*
+    SvgBuilder::_BestMatchingFont
+    Scan the available fonts to find the font name that best matches PDFname.
+    (Bug LP #179589)
+*/
+std::string SvgBuilder::_BestMatchingFont(std::string PDFname)
+{
+    double bestMatch = 0;
+    std::string bestFontname = "Arial";
+    
+    for (guint i = 0; i < _availableFontNames.size(); i++) {
+        std::string fontname = _availableFontNames[i];
+        
+        // At least the first word of the font name should match.
+        guint minMatch = fontname.find(" ");
+        if (minMatch == std::string::npos) {
+           minMatch = fontname.length();
+        }
+        
+        int Match = MatchingChars(PDFname, fontname);
+        if (Match >= minMatch) {
+            double relMatch = (float)Match / (fontname.length() + PDFname.length());
+            if (relMatch > bestMatch) {
+                bestMatch = relMatch;
+                bestFontname = fontname;
+            }
+        }
+    }
+
+    if (bestMatch == 0)
+        return PDFname;
+    else
+        return bestFontname;
+}
+
 /**
  * This array holds info about translating font weight names to more or less CSS equivalents
  */
@@ -916,10 +990,17 @@ void SvgBuilder::updateFont(GfxState *state) {
     }
 
     // Font family
-    if (font->getFamily()) {
+    if (font->getFamily()) { // if font family is explicitly given use it.
         sp_repr_css_set_property(_font_style, "font-family", font->getFamily()->getCString());
-    } else {
-        sp_repr_css_set_property(_font_style, "font-family", font_family);
+    } else { 
+        int attr_value = 1;
+        sp_repr_get_int(_preferences, "localFonts", &attr_value);
+        if (attr_value != 0) {
+            // Find the font that best matches the stripped down (orig)name (Bug LP #179589).
+            sp_repr_css_set_property(_font_style, "font-family", _BestMatchingFont(font_family).c_str());
+        } else {
+            sp_repr_css_set_property(_font_style, "font-family", font_family);
+        }
     }
 
     // Font style
@@ -1176,7 +1257,7 @@ void SvgBuilder::_flushText() {
                 Glib::ustring properFontSpec = font_factory::Default()->ConstructFontSpecification(descr);
                 pango_font_description_free(descr);
                 sp_repr_css_set_property(glyph.style, "-inkscape-font-specification", properFontSpec.c_str());
-                
+
                 // Set style and unref SPCSSAttr if it won't be needed anymore
                 sp_repr_css_change(tspan_node, glyph.style, "style");
                 if ( glyph.style_changed && i != _glyphs.begin() ) {    // Free previous style
@@ -1210,7 +1291,9 @@ void SvgBuilder::_flushText() {
         last_delta_pos = delta_pos;
 
         // Append the character to the text buffer
-        text_buffer.append((char *)&glyph.code, 1);
+       if ( !glyph.code.empty() ) {
+            text_buffer.append(1, glyph.code[0]);
+       }
 
         glyphs_in_a_row++;
         i++;
@@ -1250,8 +1333,8 @@ void SvgBuilder::addChar(GfxState *state, double x, double y,
          return;
     }
     // Allow only one space in a row
-    if ( is_space && _glyphs[_glyphs.size() - 1].code_size == 1 &&
-         _glyphs[_glyphs.size() - 1].code[0] == 32 ) {
+    if ( is_space && (_glyphs[_glyphs.size() - 1].code.size() == 1) &&
+         (_glyphs[_glyphs.size() - 1].code[0] == 32) ) {
         Geom::Point delta(dx, dy);
         _text_position += delta;
         return;
@@ -1267,18 +1350,21 @@ void SvgBuilder::addChar(GfxState *state, double x, double y,
     _text_position += delta;
 
     // Convert the character to UTF-8 since that's our SVG document's encoding
-    static UnicodeMap *u_map = NULL;
-    if ( u_map == NULL ) {
-        GooString *enc = new GooString("UTF-8");
-        u_map = globalParams->getUnicodeMap(enc);
-        u_map->incRefCnt();
-        delete enc;
-    }
-    int code_size = 0;
-    for ( int i = 0 ; i < uLen ; i++ ) {
-        code_size += u_map->mapUnicode(u[i], (char *)&new_glyph.code[code_size], sizeof(new_glyph.code) - code_size);
+    {
+        gunichar2 uu[8] = {0};
+
+        for (int i = 0; i < uLen; i++) {
+            uu[i] = u[i];
+        }
+
+        gchar *tmp = g_utf16_to_utf8(uu, uLen, NULL, NULL, NULL);
+        if ( tmp && *tmp ) {
+            new_glyph.code = tmp;
+        } else {
+            new_glyph.code.clear();
+        }
+        g_free(tmp);
     }
-    new_glyph.code_size = code_size;
 
     // Copy current style if it has changed since the previous glyph
     if (_invalidated_style || _glyphs.size() == 0 ) {
@@ -1362,9 +1448,9 @@ Inkscape::XML::Node *SvgBuilder::_createImage(Stream *str, int width, int height
         return NULL;
     }
     // Decide whether we should embed this image
-    double attr_value = 1.0;
-    sp_repr_get_double(_preferences, "embedImages", &attr_value);
-    bool embed_image = ( attr_value != 0.0 );
+    int attr_value = 1;
+    sp_repr_get_int(_preferences, "embedImages", &attr_value);
+    bool embed_image = ( attr_value != 0 );
     // Set read/write functions
     Inkscape::IO::StringOutputStream base64_string;
     Inkscape::IO::Base64OutputStream base64_stream(base64_string);
@@ -1453,7 +1539,7 @@ Inkscape::XML::Node *SvgBuilder::_createImage(Stream *str, int width, int height
             }
             png_write_row(png_ptr, (png_bytep)buffer);
         }
-        delete buffer;
+        delete [] buffer;
     } else if (color_map) {
         image_stream = new ImageStream(str, width,
                                        color_map->getNumPixelComps(),
@@ -1492,7 +1578,7 @@ Inkscape::XML::Node *SvgBuilder::_createImage(Stream *str, int width, int height
                 png_write_row(png_ptr, (png_bytep)buffer);
             }
         }
-        delete buffer;
+        delete [] buffer;
 
     } else {    // A colormap must be provided, so quit
         png_destroy_write_struct(&png_ptr, &info_ptr);