~valavanisalex/ubuntu/oneiric/inkscape/inkscape_0.48.1-2ubuntu4

« back to all changes in this revision

Viewing changes to src/extension/internal/pdfinput/svg-builder.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Kees Cook, Ted Gould, Kees Cook
  • Date: 2009-06-24 14:00:43 UTC
  • mfrom: (1.1.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20090624140043-07stp20mry48hqup
Tags: 0.47~pre0-0ubuntu1
* New upstream release

[ Ted Gould ]
* debian/control: Adding libgsl0 and removing version specifics on boost

[ Kees Cook ]
* debian/watch: updated to run uupdate and mangle pre-release versions.
* Dropped patches that have been taken upstream:
  - 01_mips
  - 02-poppler-0.8.3
  - 03-chinese-inkscape
  - 05_fix_latex_patch
  - 06_gcc-4.4
  - 07_cdr2svg
  - 08_skip-bad-utf-on-pdf-import
  - 09_gtk-clist
  - 10_belarussian
  - 11_libpng
  - 12_desktop
  - 13_slider
  - 100_svg_import_improvements
  - 102_sp_pattern_painter_free
  - 103_bitmap_type_print

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
# include <config.h>
15
15
#endif
16
16
 
 
17
#include <string> 
 
18
 
17
19
#ifdef HAVE_POPPLER
18
20
 
19
21
#include "svg-builder.h"
34
36
#include "io/stringstream.h"
35
37
#include "io/base64stream.h"
36
38
#include "display/nr-filter-utils.h"
37
 
#include "libnr/nr-matrix-ops.h"
38
39
#include "libnr/nr-macros.h"
39
40
#include "libnrtype/font-instance.h"
40
41
 
89
90
    // Set default preference settings
90
91
    _preferences = _xml_doc->createElement("svgbuilder:prefs");
91
92
    _preferences->setAttribute("embedImages", "1");
 
93
    _preferences->setAttribute("localFonts", "1");
92
94
}
93
95
 
94
96
SvgBuilder::SvgBuilder(SvgBuilder *parent, Inkscape::XML::Node *root) {
113
115
    _current_font = NULL;
114
116
    _current_state = NULL;
115
117
 
 
118
    // Fill _availableFontNames (Bug LP #179589) (code cfr. FontLister)
 
119
    FamilyToStylesMap familyStyleMap;
 
120
    font_factory::Default()->GetUIFamiliesAndStyles(&familyStyleMap);
 
121
    for (FamilyToStylesMap::iterator iter = familyStyleMap.begin();
 
122
         iter != familyStyleMap.end();
 
123
         iter++) {
 
124
        _availableFontNames.push_back(iter->first.c_str());
 
125
    }
 
126
 
116
127
    _transp_group_stack = NULL;
117
128
    SvgGraphicsState initial_state;
118
129
    initial_state.softmask = NULL;
215
226
}
216
227
 
217
228
static gchar *svgConvertRGBToText(double r, double g, double b) {
 
229
    using Inkscape::Filters::clamp;
218
230
    static gchar tmp[1023] = {0};
219
231
    snprintf(tmp, 1023,
220
232
             "#%02x%02x%02x",
221
 
             NR::clamp(SP_COLOR_F_TO_U(r)),
222
 
             NR::clamp(SP_COLOR_F_TO_U(g)),
223
 
             NR::clamp(SP_COLOR_F_TO_U(b)));
 
233
             clamp(SP_COLOR_F_TO_U(r)),
 
234
             clamp(SP_COLOR_F_TO_U(g)),
 
235
             clamp(SP_COLOR_F_TO_U(b)));
224
236
    return (gchar *)&tmp;
225
237
}
226
238
 
233
245
 
234
246
static void svgSetTransform(Inkscape::XML::Node *node, double c0, double c1,
235
247
                            double c2, double c3, double c4, double c5) {
236
 
    NR::Matrix matrix(c0, c1, c2, c3, c4, c5);
 
248
    Geom::Matrix matrix(c0, c1, c2, c3, c4, c5);
237
249
    gchar *transform_text = sp_svg_transform_write(matrix);
238
250
    node->setAttribute("transform", transform_text);
239
251
    g_free(transform_text);
530
542
 * \return true on success; false on invalid transformation
531
543
 */
532
544
bool SvgBuilder::getTransform(double *transform) {
533
 
    NR::Matrix svd;
 
545
    Geom::Matrix svd;
534
546
    gchar const *tr = _container->attribute("transform");
535
547
    bool valid = sp_svg_transform_read(tr, &svd);
536
548
    if (valid) {
596
608
        if ( pattern->getType() == 2 ) {  // Shading pattern
597
609
            GfxShadingPattern *shading_pattern = (GfxShadingPattern*)pattern;
598
610
            id = _createGradient(shading_pattern->getShading(),
599
 
                                 shading_pattern->getMatrix());
 
611
                                 shading_pattern->getMatrix(),
 
612
                                 !is_stroke);
600
613
        } else if ( pattern->getType() == 1 ) {   // Tiling pattern
601
614
            id = _createTilingPattern((GfxTilingPattern*)pattern, state, is_stroke);
602
615
        }
619
632
    Inkscape::XML::Node *pattern_node = _xml_doc->createElement("svg:pattern");
620
633
    // Set pattern transform matrix
621
634
    double *p2u = tiling_pattern->getMatrix();
622
 
    NR::Matrix pat_matrix(p2u[0], p2u[1], p2u[2], p2u[3], p2u[4], p2u[5]);
 
635
    Geom::Matrix pat_matrix(p2u[0], p2u[1], p2u[2], p2u[3], p2u[4], p2u[5]);
623
636
    gchar *transform_text = sp_svg_transform_write(pat_matrix);
624
637
    pattern_node->setAttribute("patternTransform", transform_text);
625
638
    g_free(transform_text);
717
730
    gradient->setAttribute("gradientUnits", "userSpaceOnUse");
718
731
    // If needed, flip the gradient transform around the y axis
719
732
    if (matrix) {
720
 
        NR::Matrix pat_matrix(matrix[0], matrix[1], matrix[2], matrix[3],
 
733
        Geom::Matrix pat_matrix(matrix[0], matrix[1], matrix[2], matrix[3],
721
734
                              matrix[4], matrix[5]);
722
735
        if ( !for_shading && _is_top_level ) {
723
 
            NR::Matrix flip(1.0, 0.0, 0.0, -1.0, 0.0, _height * PT_PER_PX);
 
736
            Geom::Matrix flip(1.0, 0.0, 0.0, -1.0, 0.0, _height * PT_PER_PX);
724
737
            pat_matrix *= flip;
725
738
        }
726
739
        gchar *transform_text = sp_svg_transform_write(pat_matrix);
759
772
        double gray = (double)color->r / 65535.0;
760
773
        gray = CLAMP(gray, 0.0, 1.0);
761
774
        os_opacity << gray;
762
 
        color_text = "#ffffff";
 
775
        color_text = (char*) "#ffffff";
763
776
    } else {
764
777
        os_opacity << opacity;
765
778
        color_text = svgConvertGfxRGB(color);
850
863
    }
851
864
}
852
865
 
 
866
/*
 
867
    MatchingChars
 
868
    Count for how many characters s1 matches sp taking into account 
 
869
    that a space in sp may be removed or replaced by some other tokens
 
870
    specified in the code. (Bug LP #179589)
 
871
*/
 
872
static int MatchingChars(std::string s1, std::string sp)
 
873
{
 
874
    unsigned int is = 0;
 
875
    unsigned int ip = 0;
 
876
 
 
877
    while(is < s1.length() && ip < sp.length()) {
 
878
        if (s1[is] == sp[ip]) {
 
879
            is++; ip++;
 
880
        } else if (sp[ip] == ' ') {
 
881
            ip++;
 
882
            if (s1[is] == '_') { // Valid matches to spaces in sp.
 
883
                is++;
 
884
            }
 
885
        } else {
 
886
            break;
 
887
        }
 
888
    }
 
889
    return(ip);
 
890
}
 
891
 
 
892
/*
 
893
    SvgBuilder::_BestMatchingFont
 
894
    Scan the available fonts to find the font name that best matches PDFname.
 
895
    (Bug LP #179589)
 
896
*/
 
897
std::string SvgBuilder::_BestMatchingFont(std::string PDFname)
 
898
{
 
899
    double bestMatch = 0;
 
900
    std::string bestFontname = "Arial";
 
901
    
 
902
    for (guint i = 0; i < _availableFontNames.size(); i++) {
 
903
        std::string fontname = _availableFontNames[i];
 
904
        
 
905
        // At least the first word of the font name should match.
 
906
        guint minMatch = fontname.find(" ");
 
907
        if (minMatch == std::string::npos) {
 
908
           minMatch = fontname.length();
 
909
        }
 
910
        
 
911
        int Match = MatchingChars(PDFname, fontname);
 
912
        if (Match >= minMatch) {
 
913
            double relMatch = (float)Match / (fontname.length() + PDFname.length());
 
914
            if (relMatch > bestMatch) {
 
915
                bestMatch = relMatch;
 
916
                bestFontname = fontname;
 
917
            }
 
918
        }
 
919
    }
 
920
 
 
921
    if (bestMatch == 0)
 
922
        return PDFname;
 
923
    else
 
924
        return bestFontname;
 
925
}
 
926
 
853
927
/**
854
928
 * This array holds info about translating font weight names to more or less CSS equivalents
855
929
 */
856
930
static char *font_weight_translator[][2] = {
857
 
    {"bold", "bold"},
858
 
    {"light", "300"},
859
 
    {"black", "900"},
860
 
    {"heavy", "900"},
861
 
    {"ultrabold", "800"},
862
 
    {"extrabold", "800"},
863
 
    {"demibold", "600"},
864
 
    {"semibold", "600"},
865
 
    {"medium", "500"},
866
 
    {"book", "normal"},
867
 
    {"regular", "normal"},
868
 
    {"roman", "normal"},
869
 
    {"normal", "normal"},
870
 
    {"ultralight", "200"},
871
 
    {"extralight", "200"},
872
 
    {"thin", "100"}
 
931
    {(char*) "bold",        (char*) "bold"},
 
932
    {(char*) "light",       (char*) "300"},
 
933
    {(char*) "black",       (char*) "900"},
 
934
    {(char*) "heavy",       (char*) "900"},
 
935
    {(char*) "ultrabold",   (char*) "800"},
 
936
    {(char*) "extrabold",   (char*) "800"},
 
937
    {(char*) "demibold",    (char*) "600"},
 
938
    {(char*) "semibold",    (char*) "600"},
 
939
    {(char*) "medium",      (char*) "500"},
 
940
    {(char*) "book",        (char*) "normal"},
 
941
    {(char*) "regular",     (char*) "normal"},
 
942
    {(char*) "roman",       (char*) "normal"},
 
943
    {(char*) "normal",      (char*) "normal"},
 
944
    {(char*) "ultralight",  (char*) "200"},
 
945
    {(char*) "extralight",  (char*) "200"},
 
946
    {(char*) "thin",        (char*) "100"}
873
947
};
874
948
 
875
949
/**
892
966
    } else if (font->getName()) {
893
967
        _font_specification = font->getName()->getCString();
894
968
    } else {
895
 
        _font_specification = "Arial";
 
969
        _font_specification = (char*) "Arial";
896
970
    }
897
971
 
898
972
    // Prune the font name to get the correct font family name
916
990
    }
917
991
 
918
992
    // Font family
919
 
    if (font->getFamily()) {
 
993
    if (font->getFamily()) { // if font family is explicitly given use it.
920
994
        sp_repr_css_set_property(_font_style, "font-family", font->getFamily()->getCString());
921
 
    } else {
922
 
        sp_repr_css_set_property(_font_style, "font-family", font_family);
 
995
    } else { 
 
996
        int attr_value = 1;
 
997
        sp_repr_get_int(_preferences, "localFonts", &attr_value);
 
998
        if (attr_value != 0) {
 
999
            // Find the font that best matches the stripped down (orig)name (Bug LP #179589).
 
1000
            sp_repr_css_set_property(_font_style, "font-family", _BestMatchingFont(font_family).c_str());
 
1001
        } else {
 
1002
            sp_repr_css_set_property(_font_style, "font-family", font_family);
 
1003
        }
923
1004
    }
924
1005
 
925
1006
    // Font style
942
1023
    char *css_font_weight = NULL;
943
1024
    if ( font_weight != GfxFont::WeightNotDefined ) {
944
1025
        if ( font_weight == GfxFont::W400 ) {
945
 
            css_font_weight = "normal";
 
1026
            css_font_weight = (char*) "normal";
946
1027
        } else if ( font_weight == GfxFont::W700 ) {
947
 
            css_font_weight = "bold";
 
1028
            css_font_weight = (char*) "bold";
948
1029
        } else {
949
1030
            gchar weight_num[4] = "100";
950
1031
            weight_num[0] = (gchar)( '1' + (font_weight - GfxFont::W100) );
959
1040
            }
960
1041
        }
961
1042
    } else {
962
 
        css_font_weight = "normal";
 
1043
        css_font_weight = (char*) "normal";
963
1044
    }
964
1045
    if (css_font_weight) {
965
1046
        sp_repr_css_set_property(_font_style, "font-weight", css_font_weight);
974
1055
    gchar *stretch_value = NULL;
975
1056
    switch (font_stretch) {
976
1057
        case GfxFont::UltraCondensed:
977
 
            stretch_value = "ultra-condensed";
 
1058
            stretch_value = (char*) "ultra-condensed";
978
1059
            break;
979
1060
        case GfxFont::ExtraCondensed:
980
 
            stretch_value = "extra-condensed";
 
1061
            stretch_value = (char*) "extra-condensed";
981
1062
            break;
982
1063
        case GfxFont::Condensed:
983
 
            stretch_value = "condensed";
 
1064
            stretch_value = (char*) "condensed";
984
1065
            break;
985
1066
        case GfxFont::SemiCondensed:
986
 
            stretch_value = "semi-condensed";
 
1067
            stretch_value = (char*) "semi-condensed";
987
1068
            break;
988
1069
        case GfxFont::Normal:
989
 
            stretch_value = "normal";
 
1070
            stretch_value = (char*) "normal";
990
1071
            break;
991
1072
        case GfxFont::SemiExpanded:
992
 
            stretch_value = "semi-expanded";
 
1073
            stretch_value = (char*) "semi-expanded";
993
1074
            break;
994
1075
        case GfxFont::Expanded:
995
 
            stretch_value = "expanded";
 
1076
            stretch_value = (char*) "expanded";
996
1077
            break;
997
1078
        case GfxFont::ExtraExpanded:
998
 
            stretch_value = "extra-expanded";
 
1079
            stretch_value = (char*) "extra-expanded";
999
1080
            break;
1000
1081
        case GfxFont::UltraExpanded:
1001
 
            stretch_value = "ultra-expanded";
 
1082
            stretch_value = (char*) "ultra-expanded";
1002
1083
            break;
1003
1084
        default:
1004
1085
            break;
1046
1127
 * \brief Updates current text position
1047
1128
 */
1048
1129
void SvgBuilder::updateTextPosition(double tx, double ty) {
1049
 
    NR::Point new_position(tx, ty);
 
1130
    Geom::Point new_position(tx, ty);
1050
1131
    _text_position = new_position;
1051
1132
}
1052
1133
 
1066
1147
        max_scale = h_scale;
1067
1148
    }
1068
1149
    // Calculate new text matrix
1069
 
    NR::Matrix new_text_matrix(text_matrix[0] * state->getHorizScaling(),
 
1150
    Geom::Matrix new_text_matrix(text_matrix[0] * state->getHorizScaling(),
1070
1151
                               text_matrix[1] * state->getHorizScaling(),
1071
1152
                               -text_matrix[2], -text_matrix[3],
1072
1153
                               0.0, 0.0);
1101
1182
 
1102
1183
    Inkscape::XML::Node *text_node = _xml_doc->createElement("svg:text");
1103
1184
    // Set text matrix
1104
 
    NR::Matrix text_transform(_text_matrix);
 
1185
    Geom::Matrix text_transform(_text_matrix);
1105
1186
    text_transform[4] = first_glyph.position[0];
1106
1187
    text_transform[5] = first_glyph.position[1];
1107
1188
    gchar *transform = sp_svg_transform_write(text_transform);
1110
1191
 
1111
1192
    bool new_tspan = true;
1112
1193
    bool same_coords[2] = {true, true};
1113
 
    NR::Point last_delta_pos;
 
1194
    Geom::Point last_delta_pos;
1114
1195
    unsigned int glyphs_in_a_row = 0;
1115
1196
    Inkscape::XML::Node *tspan_node = NULL;
1116
1197
    Glib::ustring x_coords;
1176
1257
                Glib::ustring properFontSpec = font_factory::Default()->ConstructFontSpecification(descr);
1177
1258
                pango_font_description_free(descr);
1178
1259
                sp_repr_css_set_property(glyph.style, "-inkscape-font-specification", properFontSpec.c_str());
1179
 
                
 
1260
 
1180
1261
                // Set style and unref SPCSSAttr if it won't be needed anymore
1181
1262
                sp_repr_css_change(tspan_node, glyph.style, "style");
1182
1263
                if ( glyph.style_changed && i != _glyphs.begin() ) {    // Free previous style
1197
1278
            }
1198
1279
        }
1199
1280
        // Append the coordinates to their respective strings
1200
 
        NR::Point delta_pos( glyph.text_position - first_glyph.text_position );
 
1281
        Geom::Point delta_pos( glyph.text_position - first_glyph.text_position );
1201
1282
        delta_pos[1] += glyph.rise;
1202
1283
        delta_pos[1] *= -1.0;   // flip it
1203
1284
        delta_pos *= _font_scaling;
1210
1291
        last_delta_pos = delta_pos;
1211
1292
 
1212
1293
        // Append the character to the text buffer
1213
 
        text_buffer.append((char *)&glyph.code, 1);
 
1294
        if (0 != glyph.code[0]) {
 
1295
            text_buffer.append((char *)&glyph.code, 1);
 
1296
        }
1214
1297
 
1215
1298
        glyphs_in_a_row++;
1216
1299
        i++;
1245
1328
    bool is_space = ( uLen == 1 && u[0] == 32 );
1246
1329
    // Skip beginning space
1247
1330
    if ( is_space && _glyphs.size() < 1 ) {
1248
 
        NR::Point delta(dx, dy);
 
1331
        Geom::Point delta(dx, dy);
1249
1332
         _text_position += delta;
1250
1333
         return;
1251
1334
    }
1252
1335
    // Allow only one space in a row
1253
1336
    if ( is_space && _glyphs[_glyphs.size() - 1].code_size == 1 &&
1254
1337
         _glyphs[_glyphs.size() - 1].code[0] == 32 ) {
1255
 
        NR::Point delta(dx, dy);
 
1338
        Geom::Point delta(dx, dy);
1256
1339
        _text_position += delta;
1257
1340
        return;
1258
1341
    }
1259
1342
 
1260
1343
    SvgGlyph new_glyph;
1261
1344
    new_glyph.is_space = is_space;
1262
 
    new_glyph.position = NR::Point( x - originX, y - originY );
 
1345
    new_glyph.position = Geom::Point( x - originX, y - originY );
1263
1346
    new_glyph.text_position = _text_position;
1264
1347
    new_glyph.dx = dx;
1265
1348
    new_glyph.dy = dy;
1266
 
    NR::Point delta(dx, dy);
 
1349
    Geom::Point delta(dx, dy);
1267
1350
    _text_position += delta;
1268
1351
 
1269
1352
    // Convert the character to UTF-8 since that's our SVG document's encoding
1362
1445
        return NULL;
1363
1446
    }
1364
1447
    // Decide whether we should embed this image
1365
 
    double attr_value = 1.0;
1366
 
    sp_repr_get_double(_preferences, "embedImages", &attr_value);
1367
 
    bool embed_image = ( attr_value != 0.0 );
 
1448
    int attr_value = 1;
 
1449
    sp_repr_get_int(_preferences, "embedImages", &attr_value);
 
1450
    bool embed_image = ( attr_value != 0 );
1368
1451
    // Set read/write functions
1369
1452
    Inkscape::IO::StringOutputStream base64_string;
1370
1453
    Inkscape::IO::Base64OutputStream base64_stream(base64_string);
1631
1714
        mask_image_node->setAttribute("transform", NULL);
1632
1715
        mask_node->appendChild(mask_image_node);
1633
1716
        // Scale the mask to the size of the image
1634
 
        NR::Matrix mask_transform((double)width, 0.0, 0.0, (double)height, 0.0, 0.0);
 
1717
        Geom::Matrix mask_transform((double)width, 0.0, 0.0, (double)height, 0.0, 0.0);
1635
1718
        gchar *transform_text = sp_svg_transform_write(mask_transform);
1636
1719
        mask_node->setAttribute("maskTransform", transform_text);
1637
1720
        g_free(transform_text);