113
115
_current_font = NULL;
114
116
_current_state = NULL;
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();
124
_availableFontNames.push_back(iter->first.c_str());
116
127
_transp_group_stack = NULL;
117
128
SvgGraphicsState initial_state;
118
129
initial_state.softmask = NULL;
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,
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;
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);
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(),
600
613
} else if ( pattern->getType() == 1 ) { // Tiling pattern
601
614
id = _createTilingPattern((GfxTilingPattern*)pattern, state, is_stroke);
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
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;
726
739
gchar *transform_text = sp_svg_transform_write(pat_matrix);
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)
872
static int MatchingChars(std::string s1, std::string sp)
877
while(is < s1.length() && ip < sp.length()) {
878
if (s1[is] == sp[ip]) {
880
} else if (sp[ip] == ' ') {
882
if (s1[is] == '_') { // Valid matches to spaces in sp.
893
SvgBuilder::_BestMatchingFont
894
Scan the available fonts to find the font name that best matches PDFname.
897
std::string SvgBuilder::_BestMatchingFont(std::string PDFname)
899
double bestMatch = 0;
900
std::string bestFontname = "Arial";
902
for (guint i = 0; i < _availableFontNames.size(); i++) {
903
std::string fontname = _availableFontNames[i];
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();
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;
854
928
* This array holds info about translating font weight names to more or less CSS equivalents
856
930
static char *font_weight_translator[][2] = {
861
{"ultrabold", "800"},
862
{"extrabold", "800"},
867
{"regular", "normal"},
869
{"normal", "normal"},
870
{"ultralight", "200"},
871
{"extralight", "200"},
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"}
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());
922
sp_repr_css_set_property(_font_style, "font-family", font_family);
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());
1002
sp_repr_css_set_property(_font_style, "font-family", font_family);
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";
949
1030
gchar weight_num[4] = "100";
950
1031
weight_num[0] = (gchar)( '1' + (font_weight - GfxFont::W100) );
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";
979
1060
case GfxFont::ExtraCondensed:
980
stretch_value = "extra-condensed";
1061
stretch_value = (char*) "extra-condensed";
982
1063
case GfxFont::Condensed:
983
stretch_value = "condensed";
1064
stretch_value = (char*) "condensed";
985
1066
case GfxFont::SemiCondensed:
986
stretch_value = "semi-condensed";
1067
stretch_value = (char*) "semi-condensed";
988
1069
case GfxFont::Normal:
989
stretch_value = "normal";
1070
stretch_value = (char*) "normal";
991
1072
case GfxFont::SemiExpanded:
992
stretch_value = "semi-expanded";
1073
stretch_value = (char*) "semi-expanded";
994
1075
case GfxFont::Expanded:
995
stretch_value = "expanded";
1076
stretch_value = (char*) "expanded";
997
1078
case GfxFont::ExtraExpanded:
998
stretch_value = "extra-expanded";
1079
stretch_value = (char*) "extra-expanded";
1000
1081
case GfxFont::UltraExpanded:
1001
stretch_value = "ultra-expanded";
1082
stretch_value = (char*) "ultra-expanded";
1066
1147
max_scale = h_scale;
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],
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());
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
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;
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;
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;
1269
1352
// Convert the character to UTF-8 since that's our SVG document's encoding
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 );
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);