summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/attributes.cpp1
-rw-r--r--src/attributes.h4
-rw-r--r--src/axis-manip.h4
-rw-r--r--src/desktop-style.cpp57
-rw-r--r--src/desktop-style.h1
-rw-r--r--src/dialogs/text-edit.cpp19
-rw-r--r--src/extension/internal/pdf-cairo.cpp2
-rw-r--r--src/extension/internal/pdfinput/svg-builder.cpp9
-rw-r--r--src/extension/internal/ps.cpp5
-rw-r--r--src/libnrtype/FontFactory.cpp528
-rw-r--r--src/libnrtype/FontFactory.h58
-rw-r--r--src/libnrtype/FontInstance.cpp6
-rw-r--r--src/libnrtype/font-lister.cpp87
-rw-r--r--src/libnrtype/font-lister.h6
-rw-r--r--src/persp3d.cpp2
-rw-r--r--src/sp-text.cpp4
-rw-r--r--src/style.cpp41
-rw-r--r--src/style.h3
-rw-r--r--src/widgets/font-selector.cpp156
-rw-r--r--src/widgets/toolbox.cpp98
-rw-r--r--src/xml/repr-css.cpp4
21 files changed, 851 insertions, 244 deletions
diff --git a/src/attributes.cpp b/src/attributes.cpp
index 4169dee51..c00268b96 100644
--- a/src/attributes.cpp
+++ b/src/attributes.cpp
@@ -321,6 +321,7 @@ static SPStyleProp const props[] = {
{SP_ATTR_LAYOUT_OPTIONS,"inkscape:layoutOptions"},
/* CSS2 */
+ {SP_PROP_INKSCAPE_FONT_SPEC, "-inkscape-font-specification"},
/* Font */
{SP_PROP_FONT, "font"},
{SP_PROP_FONT_FAMILY, "font-family"},
diff --git a/src/attributes.h b/src/attributes.h
index 33e060893..89b3f4d04 100644
--- a/src/attributes.h
+++ b/src/attributes.h
@@ -23,7 +23,7 @@ unsigned char const *sp_attribute_name(unsigned int id);
* True iff k is a property in SVG, i.e. something that can be written either in a style attribute
* or as its own XML attribute.
*/
-#define SP_ATTRIBUTE_IS_CSS(k) (((k) >= SP_PROP_FONT) && ((k) <= SP_PROP_TEXT_RENDERING))
+#define SP_ATTRIBUTE_IS_CSS(k) (((k) >= SP_PROP_INKSCAPE_FONT_SPEC) && ((k) <= SP_PROP_TEXT_RENDERING))
enum SPAttributeEnum {
SP_ATTR_INVALID, ///< Must have value 0.
@@ -321,6 +321,8 @@ enum SPAttributeEnum {
SP_ATTR_LAYOUT_OPTIONS,
/* CSS2 */
+ /* Custom full font name because Font stuff below is inadequate */
+ SP_PROP_INKSCAPE_FONT_SPEC,
/* Font */
SP_PROP_FONT,
SP_PROP_FONT_FAMILY,
diff --git a/src/axis-manip.h b/src/axis-manip.h
index 7513bebaf..8fb8fdc8e 100644
--- a/src/axis-manip.h
+++ b/src/axis-manip.h
@@ -19,8 +19,8 @@
namespace Proj {
enum VPState {
- FINITE = 0,
- INFINITE
+ VP_FINITE = 0,
+ VP_INFINITE
};
// The X-/Y-/Z-axis corresponds to the first/second/third digit
diff --git a/src/desktop-style.cpp b/src/desktop-style.cpp
index d0cecda03..e56e7fbbe 100644
--- a/src/desktop-style.cpp
+++ b/src/desktop-style.cpp
@@ -1051,6 +1051,59 @@ objects_query_fontfamily (GSList *objects, SPStyle *style_res)
}
int
+objects_query_fontspecification (GSList *objects, SPStyle *style_res)
+{
+ bool different = false;
+ int texts = 0;
+
+ if (style_res->text->font_specification.value) {
+ g_free(style_res->text->font_specification.value);
+ style_res->text->font_specification.value = NULL;
+ }
+ style_res->text->font_specification.set = FALSE;
+
+ for (GSList const *i = objects; i != NULL; i = i->next) {
+ SPObject *obj = SP_OBJECT (i->data);
+
+ if (!SP_IS_TEXT(obj) && !SP_IS_FLOWTEXT(obj)
+ && !SP_IS_TSPAN(obj) && !SP_IS_TREF(obj) && !SP_IS_TEXTPATH(obj)
+ && !SP_IS_FLOWDIV(obj) && !SP_IS_FLOWPARA(obj) && !SP_IS_FLOWTSPAN(obj))
+ continue;
+
+ SPStyle *style = SP_OBJECT_STYLE (obj);
+ if (!style) continue;
+
+ texts ++;
+
+ if (style_res->text->font_specification.value && style->text->font_specification.value &&
+ strcmp (style_res->text->font_specification.value, style->text->font_specification.value)) {
+ different = true; // different fonts
+ }
+
+ if (style_res->text->font_specification.value) {
+ g_free(style_res->text->font_specification.value);
+ style_res->text->font_specification.value = NULL;
+ }
+
+ style_res->text->font_specification.set = TRUE;
+ style_res->text->font_specification.value = g_strdup(style->text->font_specification.value);
+ }
+
+ if (texts == 0 || !style_res->text->font_specification.set)
+ return QUERY_STYLE_NOTHING;
+
+ if (texts > 1) {
+ if (different) {
+ return QUERY_STYLE_MULTIPLE_DIFFERENT;
+ } else {
+ return QUERY_STYLE_MULTIPLE_SAME;
+ }
+ } else {
+ return QUERY_STYLE_SINGLE;
+ }
+}
+
+int
objects_query_blend (GSList *objects, SPStyle *style_res)
{
const int empty_prev = -2;
@@ -1221,7 +1274,9 @@ sp_desktop_query_style_from_list (GSList *list, SPStyle *style, int property)
} else if (property == QUERY_STYLE_PROPERTY_MASTEROPACITY) {
return objects_query_opacity (list, style);
-
+
+ } else if (property == QUERY_STYLE_PROPERTY_FONT_SPECIFICATION) {
+ return objects_query_fontspecification (list, style);
} else if (property == QUERY_STYLE_PROPERTY_FONTFAMILY) {
return objects_query_fontfamily (list, style);
} else if (property == QUERY_STYLE_PROPERTY_FONTSTYLE) {
diff --git a/src/desktop-style.h b/src/desktop-style.h
index 3f201aa28..b99f12fde 100644
--- a/src/desktop-style.h
+++ b/src/desktop-style.h
@@ -43,6 +43,7 @@ enum { // which property was queried (add when you need more)
QUERY_STYLE_PROPERTY_STROKEJOIN, // stroke join
QUERY_STYLE_PROPERTY_STROKECAP, // stroke cap
QUERY_STYLE_PROPERTY_STROKESTYLE, // markers, dasharray, miterlimit, stroke-width, stroke-cap, stroke-join
+ QUERY_STYLE_PROPERTY_FONT_SPECIFICATION, //-inkscape-font-specification
QUERY_STYLE_PROPERTY_FONTFAMILY, // font-family
QUERY_STYLE_PROPERTY_FONTSTYLE, // font style
QUERY_STYLE_PROPERTY_FONTNUMBERS, // size, spacings
diff --git a/src/dialogs/text-edit.cpp b/src/dialogs/text-edit.cpp
index 279c5b5e7..d96583f85 100644
--- a/src/dialogs/text-edit.cpp
+++ b/src/dialogs/text-edit.cpp
@@ -527,7 +527,11 @@ sp_get_text_dialog_style ()
font_instance *font = sp_font_selector_get_font (SP_FONT_SELECTOR (fontsel));
if ( font ) {
+ Glib::ustring fontName = font_factory::Default()->ConstructFontSpecification(font);
+ sp_repr_css_set_property (css, "-inkscape-font-specification", fontName.c_str());
+
gchar c[256];
+
font->Family(c, 256);
sp_repr_css_set_property (css, "font-family", c);
@@ -736,12 +740,15 @@ sp_text_edit_dialog_read_selection ( GtkWidget *dlg,
// create temporary style
SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT);
// query style from desktop into it. This returns a result flag and fills query with the style of subselection, if any, or selection
- int result_family = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTFAMILY);
- int result_style = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTSTYLE);
+ int result_fontspec = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONT_SPECIFICATION);
+ int result_family = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTFAMILY);
+ int result_style = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTSTYLE);
int result_numbers = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
// If querying returned nothing, read the style from the text tool prefs (default style for new texts)
- if (result_family == QUERY_STYLE_NOTHING || result_style == QUERY_STYLE_NOTHING || result_numbers == QUERY_STYLE_NOTHING) {
+ // (Ok to not get a font specification - must just rely on the family and style in that case)
+ if (result_family == QUERY_STYLE_NOTHING || result_style == QUERY_STYLE_NOTHING
+ || result_numbers == QUERY_STYLE_NOTHING) {
repr = inkscape_get_repr (INKSCAPE, "tools.text");
if (repr) {
gtk_widget_set_sensitive (notebook, TRUE);
@@ -752,7 +759,11 @@ sp_text_edit_dialog_read_selection ( GtkWidget *dlg,
}
// FIXME: process result_family/style == QUERY_STYLE_MULTIPLE_DIFFERENT by showing "Many" in the lists
- font_instance *font = (font_factory::Default())->Face ( query->text->font_family.value, font_style_to_pos(*query) );
+
+ // Get a font_instance using the font-specification attribute stored in SPStyle if available
+ font_instance *font = font_factory::Default()->FaceFromStyle(query);
+
+
if (font) {
// the font is oversized, so we need to pass the true size separately
sp_font_selector_set_font (SP_FONT_SELECTOR (fontsel), font, query->font_size.computed);
diff --git a/src/extension/internal/pdf-cairo.cpp b/src/extension/internal/pdf-cairo.cpp
index 4baab1740..ae17a6edd 100644
--- a/src/extension/internal/pdf-cairo.cpp
+++ b/src/extension/internal/pdf-cairo.cpp
@@ -830,7 +830,7 @@ PrintCairoPDF::text(Inkscape::Extension::Print *mod, char const *text, NR::Point
}
// create font instance from style and use it
- font_instance *tf = (font_factory::Default())->Face(style->text->font_family.value, font_style_to_pos(*style));
+ font_instance *tf = font_factory::Default()->FaceFromStyle(style);
if (tf == NULL) { // do something
g_printf("Warning: trouble getting font_instance\n");
tf = (font_factory::Default())->Face("sans", font_style_to_pos(*style));
diff --git a/src/extension/internal/pdfinput/svg-builder.cpp b/src/extension/internal/pdfinput/svg-builder.cpp
index 3d96991a6..076f12906 100644
--- a/src/extension/internal/pdfinput/svg-builder.cpp
+++ b/src/extension/internal/pdfinput/svg-builder.cpp
@@ -1169,7 +1169,14 @@ void SvgBuilder::_flushText() {
break;
} else {
tspan_node = _xml_doc->createElement("svg:tspan");
- tspan_node->setAttribute("inkscape:font-specification", glyph.font_specification);
+
+ ///////
+ // Create a font specification string and save the attribute in the style
+ PangoFontDescription *descr = pango_font_description_from_string(glyph.font_specification);
+ 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
diff --git a/src/extension/internal/ps.cpp b/src/extension/internal/ps.cpp
index fedde86a2..6cc27988d 100644
--- a/src/extension/internal/ps.cpp
+++ b/src/extension/internal/ps.cpp
@@ -913,7 +913,7 @@ PrintPS::image(Inkscape::Extension::Print *mod, guchar *px, unsigned int w, unsi
char const *
PrintPS::PSFontName(SPStyle const *style)
{
- font_instance *tf = (font_factory::Default())->Face(style->text->font_family.value, font_style_to_pos(*style));
+ font_instance *tf = font_factory::Default()->FaceFromStyle(style);
char const *n;
char name_buf[256];
@@ -1273,7 +1273,8 @@ PrintPS::text(Inkscape::Extension::Print *mod, char const *text, NR::Point p,
* that's why using PSFontName() method just to get the PS fontname
* is not enough and not appropriate
*/
- font_instance *tf = (font_factory::Default())->Face(style->text->font_family.value, font_style_to_pos(*style));
+ font_instance *tf = font_factory::Default()->FaceFromStyle(style);
+
const gchar *fn = NULL;
char name_buf[256];
diff --git a/src/libnrtype/FontFactory.cpp b/src/libnrtype/FontFactory.cpp
index 32f71aed0..2d56a1a41 100644
--- a/src/libnrtype/FontFactory.cpp
+++ b/src/libnrtype/FontFactory.cpp
@@ -11,6 +11,8 @@
#include "FontFactory.h"
#include <libnrtype/font-instance.h>
+#include <glibmm.h>
+
#ifdef HAVE_CONFIG_H
# include "config.h"
@@ -202,8 +204,8 @@ is_swash(char const *s)
* Q: Shouldn't this include the other tests such as is_outline, etc.?
* Q: Is there a problem with strcasecmp on Win32? Should it use stricmp?
*/
-static int
-style_name_compare(void const *aa, void const *bb)
+int
+style_name_compare(char const *aa, char const *bb)
{
char const *a = (char const *) aa;
char const *b = (char const *) bb;
@@ -254,8 +256,8 @@ static void font_factory_style_list_destructor(NRStyleList *list)
/**
* On Win32 performs a stricmp(a,b), otherwise does a strcasecmp(a,b)
*/
-static int
-family_name_compare(void const *a, void const *b)
+int
+family_name_compare(char const *a, char const *b)
{
#ifndef WIN32
return strcasecmp((*((char const **) a)), (*((char const **) b)));
@@ -323,6 +325,349 @@ font_factory::~font_factory(void)
//pango_ft2_shutdown_display();
#endif
//g_object_unref(fontContext);
+
+ // Delete the pango font pointers in the string to instance map
+ PangoStringToDescrMap::iterator it = fontInstanceMap.begin();
+ while (it != fontInstanceMap.end()) {
+ pango_font_description_free((*it).second);
+ it++;
+ }
+}
+
+
+Glib::ustring font_factory::ConstructFontSpecification(PangoFontDescription *font)
+{
+ Glib::ustring pangoString;
+
+ g_assert(font);
+
+ if (font) {
+ // Once the format for the font specification is decided, it must be
+ // kept.. if it is absolutely necessary to change it, the attribute
+ // it is written to needs to have a new version so the legacy files
+ // can be read.
+
+ PangoFontDescription *copy = pango_font_description_copy(font);
+
+ pango_font_description_unset_fields (copy, PANGO_FONT_MASK_SIZE);
+ pangoString = Glib::ustring(pango_font_description_to_string(copy));
+
+ pango_font_description_free(copy);
+
+ }
+
+ return pangoString;
+}
+
+Glib::ustring font_factory::ConstructFontSpecification(font_instance *font)
+{
+ Glib::ustring pangoString;
+
+ g_assert(font);
+
+ if (font) {
+ pangoString = ConstructFontSpecification(font->descr);
+ }
+
+ return pangoString;
+}
+
+Glib::ustring font_factory::GetUIFamilyString(PangoFontDescription const *fontDescr)
+{
+ Glib::ustring family;
+
+ g_assert(fontDescr);
+
+ if (fontDescr) {
+ // For now, keep it as family name taken from pango
+ family = pango_font_description_get_family(fontDescr);
+ }
+
+ return family;
+}
+
+Glib::ustring font_factory::GetUIStyleString(PangoFontDescription const *fontDescr)
+{
+ Glib::ustring style;
+
+ g_assert(fontDescr);
+
+ if (fontDescr) {
+ PangoFontDescription *fontDescrCopy = pango_font_description_copy(fontDescr);
+
+ pango_font_description_unset_fields(fontDescrCopy, PANGO_FONT_MASK_FAMILY);
+ pango_font_description_unset_fields(fontDescrCopy, PANGO_FONT_MASK_SIZE);
+
+ // For now, keep it as style name taken from pango
+ style = pango_font_description_to_string(fontDescrCopy);
+
+ pango_font_description_free(fontDescrCopy);
+ }
+
+ return style;
+}
+
+Glib::ustring font_factory::ReplaceFontSpecificationFamily(const Glib::ustring & fontSpec, const Glib::ustring & newFamily)
+{
+ Glib::ustring newFontSpec;
+
+ // Although we are using the string from pango_font_description_to_string for the
+ // font specification, we definitely cannot just set the new family in the
+ // PangoFontDescription structure and ask for a new string. This is because
+ // what constitutes a "family" in our own UI may be different from how Pango
+ // sees it.
+
+ // Find the PangoFontDescription associated to this fontSpec
+ PangoStringToDescrMap::iterator it = fontInstanceMap.find(fontSpec);
+
+ g_assert(it != fontInstanceMap.end());
+
+ if (it != fontInstanceMap.end()) {
+ PangoFontDescription *descr = pango_font_description_copy((*it).second);
+
+ // Grab the UI Family string from the descr
+ Glib::ustring uiFamily = GetUIFamilyString(descr);
+
+ // Replace the UI Family name with the new family name
+ std::size_t found = fontSpec.find(uiFamily);
+ if (found != Glib::ustring::npos) {
+ newFontSpec = fontSpec;
+ newFontSpec.erase(found, uiFamily.size());
+ newFontSpec.insert(found, newFamily);
+
+ // If the new font specification does not exist in the reference maps,
+ // search for the next best match for the faces in that style
+ it = fontInstanceMap.find(newFontSpec);
+ if (it == fontInstanceMap.end()) {
+
+ PangoFontDescription *newFontDescr = pango_font_description_from_string(newFontSpec.c_str());
+
+ PangoFontDescription *bestMatchForNewDescr = NULL;
+ Glib::ustring bestMatchFontDescription;
+
+ bool setFirstFamilyMatch = false;
+ for (it = fontInstanceMap.begin(); it != fontInstanceMap.end(); it++) {
+
+ Glib::ustring currentFontSpec = (*it).first;
+
+ // Save some time by only looking at the right family
+ if (currentFontSpec.find(newFamily) != Glib::ustring::npos) {
+ if (!setFirstFamilyMatch) {
+ // This ensures that the closest match is at least within the correct
+ // family rather than the first font in the list
+ bestMatchForNewDescr = pango_font_description_copy((*it).second);
+ bestMatchFontDescription = currentFontSpec;
+ setFirstFamilyMatch = true;
+ } else {
+ // Get the font description that corresponds, and
+ // then see if we've found a better match
+ PangoFontDescription *possibleMatch = pango_font_description_copy((*it).second);
+
+ if (pango_font_description_better_match(
+ newFontDescr, bestMatchForNewDescr, possibleMatch)) {
+
+ pango_font_description_free(bestMatchForNewDescr);
+ bestMatchForNewDescr = possibleMatch;
+ bestMatchFontDescription = currentFontSpec;
+ } else {
+ pango_font_description_free(possibleMatch);
+ }
+ }
+ }
+ }
+
+ newFontSpec = bestMatchFontDescription;
+
+ pango_font_description_free(newFontDescr);
+ pango_font_description_free(bestMatchForNewDescr);
+ }
+ }
+
+ pango_font_description_free(descr);
+ }
+
+ return newFontSpec;
+}
+
+Glib::ustring font_factory::FontSpecificationSetItalic(const Glib::ustring & fontSpec, bool turnOn)
+{
+ Glib::ustring newFontSpec;
+
+ // Find the PangoFontDesecription that goes with this font specification string
+ PangoStringToDescrMap::iterator it = fontInstanceMap.find(fontSpec);
+
+ g_assert(it != fontInstanceMap.end());
+
+ if (it != fontInstanceMap.end()) {
+ // If we did find one, make a copy and set/unset the italic as needed
+ PangoFontDescription *descr = pango_font_description_copy((*it).second);
+
+ PangoStyle style;
+ if (turnOn) {
+ style = PANGO_STYLE_ITALIC;
+ } else {
+ style = PANGO_STYLE_NORMAL;
+ }
+ pango_font_description_set_style(descr, style);
+
+ newFontSpec = ConstructFontSpecification(descr);
+ if (fontInstanceMap.find(newFontSpec) == fontInstanceMap.end()) {
+ // If the new font does not have an italic face, don't
+ // allow italics to be set!
+ newFontSpec = fontSpec;
+ }
+
+ pango_font_description_free(descr);
+ }
+
+ return newFontSpec;
+}
+
+Glib::ustring font_factory::FontSpecificationSetBold(const Glib::ustring & fontSpec, bool turnOn)
+{
+ Glib::ustring newFontSpec;
+
+ // Find the PangoFontDesecription that goes with this font specification string
+ PangoStringToDescrMap::iterator it = fontInstanceMap.find(fontSpec);
+
+ if (it != fontInstanceMap.end()) {
+ // If we did find one, make a copy and set/unset the bold as needed
+ PangoFontDescription *descr = pango_font_description_copy((*it).second);
+
+ PangoWeight weight;
+ if (turnOn) {
+ weight = PANGO_WEIGHT_BOLD;
+ } else {
+ weight = PANGO_WEIGHT_NORMAL;
+ }
+ pango_font_description_set_weight(descr, weight);
+
+ newFontSpec = ConstructFontSpecification(descr);
+ if (fontInstanceMap.find(newFontSpec) == fontInstanceMap.end()) {
+ // If the new font does not have a bold face, don't
+ // allow bold to be set!
+ newFontSpec = fontSpec;
+ }
+
+ pango_font_description_free(descr);
+ }
+
+ return newFontSpec;
+}
+
+/////
+
+static bool StyleNameCompareInternal(Glib::ustring style1, Glib::ustring style2)
+{
+ return (style_name_compare(style1.c_str(), style2.c_str()) < 0);
+}
+
+void font_factory::GetUIFamiliesAndStyles(FamilyToStylesMap *map)
+{
+ g_assert(map);
+
+ if (map) {
+
+ // Gather the family names as listed by Pango
+ PangoFontFamily** families = NULL;
+ int numFamilies = 0;
+ pango_font_map_list_families(fontServer, &families, &numFamilies);
+
+ for (int currentFamily=0; currentFamily < numFamilies; currentFamily++) {
+
+ // Gather the styles for this family
+ PangoFontFace** faces = NULL;
+ int numFaces = 0;
+ pango_font_family_list_faces(families[currentFamily], &faces, &numFaces);
+
+ for (int currentFace=0; currentFace < numFaces; currentFace++) {
+
+ // If the face has a name, describe it, and then use the
+ // description to get the UI family and face strings
+
+ if (pango_font_face_get_face_name(faces[currentFace]) == NULL) {
+ continue;
+ }
+
+ PangoFontDescription *faceDescr = pango_font_face_describe(faces[currentFace]);
+ if (faceDescr) {
+ Glib::ustring familyUIName = GetUIFamilyString(faceDescr);
+ Glib::ustring styleUIName = GetUIStyleString(faceDescr);
+
+ if (!familyUIName.empty() && !styleUIName.empty()) {
+ // Find the right place to put the style information, adding
+ // a map entry for the family name if it doesn't yet exist
+
+ FamilyToStylesMap::iterator iter = map->find(familyUIName);
+
+ if (iter == map->end()) {
+ map->insert(std::make_pair(familyUIName, std::list<Glib::ustring>()));
+ }
+
+ // Insert into the style list and save the info in the reference maps
+ // only if the style does not yet exist
+
+ bool exists = false;
+ std::list<Glib::ustring> &styleList = (*map)[familyUIName];
+
+ for (std::list<Glib::ustring>::iterator it=styleList.begin();
+ it != styleList.end();
+ it++) {
+ if (*it == styleUIName) {
+ exists = true;
+ break;
+ }
+ }
+
+ if (!exists) {
+ styleList.push_back(styleUIName);
+
+ // Add the string info needed in the reference maps
+ fontStringMap.insert(
+ std::make_pair(
+ Glib::ustring(familyUIName) + Glib::ustring(styleUIName),
+ ConstructFontSpecification(faceDescr)));
+ fontInstanceMap.insert(
+ std::make_pair(ConstructFontSpecification(faceDescr), faceDescr));
+ } else {
+ pango_font_description_free(faceDescr);
+ }
+ } else {
+ pango_font_description_free(faceDescr);
+ }
+ }
+ }
+ }
+
+ // Sort the style lists
+ for (FamilyToStylesMap::iterator iter = map->begin() ; iter != map->end(); iter++) {
+ (*iter).second.sort(StyleNameCompareInternal);
+ }
+ }
+}
+
+font_instance* font_factory::FaceFromStyle(SPStyle const *style)
+{
+ font_instance *font = NULL;
+
+ g_assert(style);
+
+ if (style) {
+ // First try to use the font specification if it is set
+ if (style->text->font_specification.set
+ && style->text->font_specification.value
+ && *style->text->font_specification.value) {
+
+ font = FaceFromFontSpecification(style->text->font_specification.value);
+ }
+
+ // If that failed, try using the CSS information in the style
+ if (!font) {
+ font = Face(style->text->font_family.value, font_style_to_pos(*style));
+ }
+ }
+
+ return font;
}
font_instance *font_factory::FaceFromDescr(char const *family, char const *style)
@@ -334,6 +679,81 @@ font_instance *font_factory::FaceFromDescr(char const *family, char const *style
return res;
}
+font_instance* font_factory::FaceFromUIStrings(char const *uiFamily, char const *uiStyle)
+{
+ font_instance *fontInstance = NULL;
+
+ g_assert(uiFamily && uiStyle);
+ if (uiFamily && uiStyle) {
+ Glib::ustring uiString = Glib::ustring(uiFamily) + Glib::ustring(uiStyle);
+
+ UIStringToPangoStringMap::iterator uiToPangoIter = fontStringMap.find(uiString);
+
+ if (uiToPangoIter != fontStringMap.end ()) {
+ PangoStringToDescrMap::iterator pangoToDescrIter = fontInstanceMap.find((*uiToPangoIter).second);
+ if (pangoToDescrIter != fontInstanceMap.end()) {
+ // We found the pango description - now we can make a font_instance
+ PangoFontDescription *tempDescr = pango_font_description_copy((*pangoToDescrIter).second);
+ fontInstance = Face(tempDescr);
+ pango_font_description_free(tempDescr);
+ }
+ }
+ }
+
+ return fontInstance;
+}
+
+font_instance* font_factory::FaceFromPangoString(char const *pangoString)
+{
+ font_instance *fontInstance = NULL;
+
+ g_assert(pangoString);
+
+ if (pangoString) {
+ PangoFontDescription *descr = NULL;
+
+ // First attempt to find the font specification in the reference map
+ PangoStringToDescrMap::iterator it = fontInstanceMap.find(Glib::ustring(pangoString));
+ if (it != fontInstanceMap.end()) {
+ descr = pango_font_description_copy((*it).second);
+ }
+
+ // Or create a font description from the string - this may fail or
+ // produce unexpected results if the string does not have a good format
+ if (!descr) {
+ descr = pango_font_description_from_string(pangoString);
+ }
+
+ if (descr && (pango_font_description_get_family(descr) != NULL)) {
+ fontInstance = Face(descr);
+ }
+
+ if (descr) {
+ pango_font_description_free(descr);
+ }
+ }
+
+ return fontInstance;
+}
+
+font_instance* font_factory::FaceFromFontSpecification(char const *fontSpecification)
+{
+ font_instance *font = NULL;
+
+ g_assert(fontSpecification);
+
+ if (fontSpecification) {
+ // How the string is used to reconstruct a font depends on how it
+ // was constructed in ConstructFontSpecification. As it stands,
+ // the font specification is a pango-created string
+ font = FaceFromPangoString(fontSpecification);
+ }
+
+ return font;
+}
+
+
+
font_instance *font_factory::Face(PangoFontDescription *descr, bool canFail)
{
#ifdef USE_PANGO_WIN32
@@ -487,106 +907,6 @@ void font_factory::UnrefFace(font_instance *who)
}
}
-NRNameList *font_factory::Families(NRNameList *flist)
-{
- PangoFontFamily** fams = NULL;
- int nbFam = 0;
- pango_font_map_list_families(fontServer, &fams, &nbFam);
-
- PANGO_DEBUG("got %d families\n", nbFam);
-
- flist->length = nbFam;
- flist->names = (guchar **)g_malloc(nbFam*sizeof(guchar*));
- flist->destructor = font_factory_name_list_destructor;
-
- for (int i = 0;i < nbFam;i++) {
-// Note: on Windows, pango_font_family_get_name always returns lowercase name.
-// As a result the list of fonts in the dialog is lowercase.
-// We could work around by loading the font and taking pango_font_description_get_family from its descr (that gives correct case),
-// but this is slow, and it's better to fix Pango instead.
- flist->names[i]=(guchar*)strdup(pango_font_family_get_name(fams[i]));
- }
-
- qsort(flist->names, nbFam, sizeof(guchar *), family_name_compare);
-
- g_free(fams);
-
- return flist;
-}
-
-NRStyleList *font_factory::Styles(gchar const *family, NRStyleList *slist)
-{
- PangoFontFamily *theFam = NULL;
-
- // search available families
- {
- PangoFontFamily** fams = NULL;
- int nbFam = 0;
- pango_font_map_list_families(fontServer, &fams, &nbFam);
-
- for (int i = 0;i < nbFam;i++) {
- char const *fname = pango_font_family_get_name(fams[i]);
- if ( fname && strcmp(family,fname) == 0 ) {
- theFam = fams[i];
- break;
- }
- }
-
- g_free(fams);
- }
-
- // nothing found
- if ( theFam == NULL ) {
- slist->length = 0;
- slist->records = NULL;
- slist->destructor = NULL;
- return slist;
- }
-
- // search faces in the found family
- PangoFontFace** faces = NULL;
- int nFaces = 0;
- pango_font_family_list_faces(theFam, &faces, &nFaces);
-
- slist->records = (NRStyleRecord *) g_malloc(nFaces * sizeof(NRStyleRecord));
- slist->destructor = font_factory_style_list_destructor;
-
- int nr = 0;
- for (int i = 0; i < nFaces; i++) {
-
- // no unnamed faces
- if (pango_font_face_get_face_name(faces[i]) == NULL)
- continue;
- PangoFontDescription *nd = pango_font_face_describe(faces[i]);
- if (nd == NULL)
- continue;
- char const *descr = pango_font_description_to_string(nd);
- if (descr == NULL) {
- pango_font_description_free(nd);
- continue;
- }
-
- char const *name = g_strdup(pango_font_face_get_face_name(faces[i]));
- pango_font_description_free(nd);
-
- slist->records[nr].name = name;
- slist->records[nr].descr = descr;
- nr ++;
- }
-
- slist->length = nr;
-
- qsort(slist->records, slist->length, sizeof(NRStyleRecord), style_record_compare);
- /* effic: Consider doing strdown and all the is_italic etc. tests once off and store the
- * results in a table, rather than having the sort invoke multiple is_italic tests per
- * record.
- */
-
- g_free(faces);
-
- return slist;
-}
-
void font_factory::AddInCache(font_instance *who)
{
if ( who == NULL ) return;
diff --git a/src/libnrtype/FontFactory.h b/src/libnrtype/FontFactory.h
index ba0010246..9f4b31a2e 100644
--- a/src/libnrtype/FontFactory.h
+++ b/src/libnrtype/FontFactory.h
@@ -7,6 +7,8 @@
#ifndef my_font_factory
#define my_font_factory
+//#include <glibmm/ustring.h>
+
#include <functional>
#include <algorithm>
#include <ext/hash_map>
@@ -21,7 +23,9 @@
#include <pango/pango.h>
#include "nr-type-primitives.h"
#include "nr-type-pos-def.h"
+#include "font-style-to-pos.h"
#include <libnrtype/nrtype-forward.h>
+#include "../style.h"
/* Freetype */
#ifdef USE_PANGO_WIN32
@@ -31,6 +35,11 @@
#include <freetype/freetype.h>
#endif
+namespace Glib
+{
+ class ustring;
+}
+
// the font_factory keeps a hashmap of all the loaded font_instances, and uses the PangoFontDescription
// as index (nota: since pango already does that, using the PangoFont could work too)
struct font_descr_hash : public std::unary_function<PangoFontDescription*,size_t> {
@@ -40,6 +49,13 @@ struct font_descr_equal : public std::binary_function<PangoFontDescription*, Pan
bool operator()(PangoFontDescription *const &a, PangoFontDescription *const &b);
};
+// Comparison functions for style names
+int style_name_compare(char const *aa, char const *bb);
+int family_name_compare(char const *a, char const *b);
+
+// Map type for gathering UI family and style strings
+typedef std::map<Glib::ustring, std::list<Glib::ustring> > FamilyToStylesMap;
+
class font_factory {
public:
static font_factory *lUsine; /**< The default font_factory; i cannot think of why we would
@@ -75,9 +91,32 @@ public:
/// Returns the default font_factory.
static font_factory* Default();
+
+ /// Constructs a pango string for use with the fontStringMap (see below)
+ Glib::ustring ConstructFontSpecification(PangoFontDescription *font);
+ Glib::ustring ConstructFontSpecification(font_instance *font);
+
+ /// Returns strings to be used in the UI for family and face (or "style" as the column is labeled)
+ Glib::ustring GetUIFamilyString(PangoFontDescription const *fontDescr);
+ Glib::ustring GetUIStyleString(PangoFontDescription const *fontDescr);
+
+ /// Modifiers for the font specification (returns new font specification)
+ Glib::ustring ReplaceFontSpecificationFamily(const Glib::ustring & fontSpec, const Glib::ustring & newFamily);
+ Glib::ustring FontSpecificationSetItalic(const Glib::ustring & fontSpec, bool turnOn);
+ Glib::ustring FontSpecificationSetBold(const Glib::ustring & fontSpec, bool turnOn);
+
+ // Gathers all strings needed for UI while storing pango information in
+ // fontInstanceMap and fontStringMap
+ void GetUIFamiliesAndStyles(FamilyToStylesMap *map);
+
+ /// Retrieve a font_instance from a style object, first trying to use the font-specification, the CSS information
+ font_instance* FaceFromStyle(SPStyle const *style);
// Various functions to get a font_instance from different descriptions.
font_instance* FaceFromDescr(char const *family, char const *style);
+ font_instance* FaceFromUIStrings(char const *uiFamily, char const *uiStyle);
+ font_instance* FaceFromPangoString(char const *pangoString);
+ font_instance* FaceFromFontSpecification(char const *fontSpecification);
font_instance* Face(PangoFontDescription *descr, bool canFail=true);
font_instance* Face(char const *family,
int variant=PANGO_VARIANT_NORMAL, int style=PANGO_STYLE_NORMAL,
@@ -88,12 +127,23 @@ public:
/// Semi-private: tells the font_factory taht the font_instance 'who' has died and should be removed from loadedFaces
void UnrefFace(font_instance* who);
- // Queries for the font-selector.
- NRNameList* Families(NRNameList *flist);
- NRStyleList* Styles(const gchar *family, NRStyleList *slist);
-
// internal
void AddInCache(font_instance *who);
+
+private:
+ // These two maps are used for translating between what's in the UI and a pango
+ // font description. This is necessary because Pango cannot always
+ // reproduce these structures from the names it gave us in the first place.
+
+ // Key: A string produced by font_factory::ConstructFontSpecification
+ // Value: The associated PangoFontDescription
+ typedef std::map<Glib::ustring, PangoFontDescription *> PangoStringToDescrMap;
+ PangoStringToDescrMap fontInstanceMap;
+
+ // Key: Family name in UI + Style name in UI
+ // Value: The associated string that should be produced with font_factory::ConstructFontSpecification
+ typedef std::map<Glib::ustring, Glib::ustring> UIStringToPangoStringMap;
+ UIStringToPangoStringMap fontStringMap;
};
diff --git a/src/libnrtype/FontInstance.cpp b/src/libnrtype/FontInstance.cpp
index 0b37b14ec..228a34f83 100644
--- a/src/libnrtype/FontInstance.cpp
+++ b/src/libnrtype/FontInstance.cpp
@@ -278,8 +278,10 @@ unsigned int font_instance::Attribute(const gchar *key, gchar *str, unsigned int
res="normal";
} else if ( v <= PANGO_WEIGHT_BOLD ) {
res="bold";
- } else {
- res="800";
+ } else if ( v <= PANGO_WEIGHT_ULTRABOLD ) {
+ res="800";
+ } else { // HEAVY
+ res="900";
}
free_res=false;
} else if ( strcmp(key,"stretch") == 0 ) {
diff --git a/src/libnrtype/font-lister.cpp b/src/libnrtype/font-lister.cpp
index 1a2f6d9c8..a7160f5f0 100644
--- a/src/libnrtype/font-lister.cpp
+++ b/src/libnrtype/font-lister.cpp
@@ -15,46 +15,63 @@
#include <gtkmm/liststore.h>
#include "font-lister.h"
+#include "FontFactory.h"
namespace Inkscape
{
- FontLister::FontLister ()
- {
- font_list_store = Gtk::ListStore::create (FontList);
-
- if (font_factory::Default()->Families(&families))
- {
- for (unsigned int i = 0; i < families.length; ++i)
- {
- Gtk::TreeModel::iterator iter = font_list_store->append();
- (*iter)[FontList.font] = reinterpret_cast<const char*>(families.names[i]);
-
- NRStyleList styles;
- if (font_factory::Default()->Styles (reinterpret_cast<const char*>(families.names[i]), &styles));
-
- GList *Styles=0;
- for (unsigned int n = 0; n < styles.length; ++n)
- {
- NRStyleRecord style_record = styles.records[n];
- Styles = g_list_append (Styles, strdup(style_record.name));
- }
-
- (*iter)[FontList.styles] = Styles;
-
- font_list_store_iter_map.insert (std::make_pair (reinterpret_cast<const char*>(families.names[i]), Gtk::TreePath (iter)));
- }
- }
-
+ FontLister::FontLister ()
+ {
+ font_list_store = Gtk::ListStore::create (FontList);
+
+ FamilyToStylesMap familyStyleMap;
+ font_factory::Default()->GetUIFamiliesAndStyles(&familyStyleMap);
+
+ // Grab the family names into a list and then sort them
+ std::list<Glib::ustring> familyList;
+ for (FamilyToStylesMap::iterator iter = familyStyleMap.begin();
+ iter != familyStyleMap.end();
+ iter++) {
+ familyList.push_back((*iter).first);
+ }
+ familyList.sort();
+
+ // Traverse through the family names and set up the list store (note that
+ // the styles list that are the map's values are already sorted)
+ while (!familyList.empty()) {
+ Glib::ustring familyName = familyList.front();
+ familyList.pop_front();
+
+ if (!familyName.empty()) {
+ Gtk::TreeModel::iterator treeModelIter = font_list_store->append();
+ (*treeModelIter)[FontList.font] = reinterpret_cast<const char*>(g_strdup(familyName.c_str()));
+
+ // Now go through the styles
+ GList *styles = NULL;
+ std::list<Glib::ustring> &styleStrings = familyStyleMap[familyName];
+ for (std::list<Glib::ustring>::iterator it=styleStrings.begin();
+ it != styleStrings.end();
+ it++) {
+ styles = g_list_append(styles, g_strdup((*it).c_str()));
}
+
+ (*treeModelIter)[FontList.styles] = styles;
+
+ font_list_store_iter_map.insert(std::make_pair(familyName, Gtk::TreePath(treeModelIter)));
+ }
+ }
+ }
- FontLister::~FontLister ()
- {
- };
+ FontLister::~FontLister ()
+ {
+ };
- const Glib::RefPtr<Gtk::ListStore>
- FontLister::get_font_list () const
- {
- return font_list_store;
- }
+ const Glib::RefPtr<Gtk::ListStore>
+ FontLister::get_font_list () const
+ {
+ return font_list_store;
+ }
}
+
+
+
diff --git a/src/libnrtype/font-lister.h b/src/libnrtype/font-lister.h
index 39953c11c..b2d2a3ecf 100644
--- a/src/libnrtype/font-lister.h
+++ b/src/libnrtype/font-lister.h
@@ -45,7 +45,7 @@ namespace Inkscape
public:
/** Column containing the family name
*/
- Gtk::TreeModelColumn<std::string> font;
+ Gtk::TreeModelColumn<Glib::ustring> font;
/** Column containing an std::vector<std::string> with style names
* for the corresponding family
@@ -60,7 +60,7 @@ namespace Inkscape
};
FontListClass FontList;
- typedef std::map<std::string, Gtk::TreePath> IterMapType;
+ typedef std::map<Glib::ustring, Gtk::TreePath> IterMapType;
/** Returns the ListStore with the font names
*
@@ -79,7 +79,7 @@ namespace Inkscape
}
Gtk::TreePath
- get_row_for_font (std::string family)
+ get_row_for_font (Glib::ustring family)
{
IterMapType::iterator iter = font_list_store_iter_map.find (family);
if (iter == font_list_store_iter_map.end ()) throw FAMILY_NOT_FOUND;
diff --git a/src/persp3d.cpp b/src/persp3d.cpp
index 1029516f7..27701c80d 100644
--- a/src/persp3d.cpp
+++ b/src/persp3d.cpp
@@ -329,7 +329,7 @@ persp3d_toggle_VPs (std::set<Persp3D *> p, Proj::Axis axis) {
void
persp3d_set_VP_state (Persp3D *persp, Proj::Axis axis, Proj::VPState state) {
- if (persp3d_VP_is_finite(persp, axis) != (state == Proj::FINITE)) {
+ if (persp3d_VP_is_finite(persp, axis) != (state == Proj::VP_FINITE)) {
persp3d_toggle_VP(persp, axis);
}
}
diff --git a/src/sp-text.cpp b/src/sp-text.cpp
index 1609afa92..5d1abbb3a 100644
--- a/src/sp-text.cpp
+++ b/src/sp-text.cpp
@@ -402,8 +402,8 @@ sp_text_description(SPItem *item)
SPText *text = (SPText *) item;
SPStyle *style = SP_OBJECT_STYLE(text);
- font_instance *tf = (font_factory::Default())->Face(style->text->font_family.value,
- font_style_to_pos(*style));
+ font_instance *tf = font_factory::Default()->FaceFromStyle(style);
+
char name_buf[256];
char *n;
if (tf) {
diff --git a/src/style.cpp b/src/style.cpp
index 068550878..357fe5f0e 100644
--- a/src/style.cpp
+++ b/src/style.cpp
@@ -715,6 +715,17 @@ sp_style_read(SPStyle *style, SPObject *object, Inkscape::XML::Node *repr)
style->stroke_dashoffset_set = FALSE;
}
}
+
+ /* -inkscape-font-specification */
+ if (!style->text_private || !style->text->font_specification.set) {
+ val = repr->attribute("-inkscape-font-specification");
+ if (val) {
+ if (!style->text_private) sp_style_privatize_text(style);
+ gchar *val_unquoted = attribute_unquote(val);
+ sp_style_read_istring(&style->text->font_specification, val_unquoted);
+ if (val_unquoted) g_free (val_unquoted);
+ }
+ }
/* font-family */
if (!style->text_private || !style->text->font_family.set) {
@@ -817,6 +828,14 @@ sp_style_merge_property(SPStyle *style, gint id, gchar const *val)
g_return_if_fail(val != NULL);
switch (id) {
+ case SP_PROP_INKSCAPE_FONT_SPEC:
+ if (!style->text_private) sp_style_privatize_text(style);
+ if (!style->text->font_specification.set) {
+ gchar *val_unquoted = attribute_unquote(val);
+ sp_style_read_istring(&style->text->font_specification, val_unquoted);
+ if (val_unquoted) g_free (val_unquoted);
+ }
+ break;
/* CSS2 */
/* Font */
case SP_PROP_FONT_FAMILY:
@@ -1500,6 +1519,13 @@ sp_style_merge_from_parent(SPStyle *const style, SPStyle const *const parent)
}
}
+ if (style->text && parent->text) {
+ if (!style->text->font_specification.set || style->text->font_specification.inherit) {
+ g_free(style->text->font_specification.value);
+ style->text->font_specification.value = g_strdup(parent->text->font_specification.value);
+ }
+ }
+
/* Markers - Free the old value and make copy of the new */
for (unsigned i = SP_MARKER_LOC; i < SP_MARKER_LOC_QTY; i++) {
if (!style->marker[i].set || style->marker[i].inherit) {
@@ -1885,10 +1911,14 @@ sp_style_merge_from_dying_parent(SPStyle *const style, SPStyle const *const pare
/* Font */
if (style->text && parent->text) {
+ sp_style_merge_string_prop_from_dying_parent(style->text->font_specification,
+ parent->text->font_specification);
+
sp_style_merge_string_prop_from_dying_parent(style->text->font_family,
parent->text->font_family);
}
+
/* Properties that don't inherit by default. Most of these need special handling. */
{
/*
@@ -2453,7 +2483,7 @@ sp_style_clear(SPStyle *style)
style->text = text;
style->text_private = text_private;
- /* fixme: */
+ style->text->font_specification.set = FALSE;
style->text->font.set = FALSE;
style->text->font_family.set = FALSE;
@@ -2633,6 +2663,7 @@ sp_text_style_new()
ts->refcount = 1;
sp_text_style_clear(ts);
+ ts->font_specification.value = g_strdup("Bitstream Vera Sans");
ts->font.value = g_strdup("Bitstream Vera Sans");
ts->font_family.value = g_strdup("Bitstream Vera Sans");
@@ -2646,6 +2677,7 @@ sp_text_style_new()
static void
sp_text_style_clear(SPTextStyle *ts)
{
+ ts->font_specification.set = FALSE;
ts->font.set = FALSE;
ts->font_family.set = FALSE;
}
@@ -2661,6 +2693,7 @@ sp_text_style_unref(SPTextStyle *st)
st->refcount -= 1;
if (st->refcount < 1) {
+ g_free(st->font_specification.value);
g_free(st->font.value);
g_free(st->font_family.value);
g_free(st);
@@ -2680,6 +2713,7 @@ sp_text_style_duplicate_unset(SPTextStyle *st)
SPTextStyle *nt = g_new0(SPTextStyle, 1);
nt->refcount = 1;
+ nt->font_specification.value = g_strdup(st->font_specification.value);
nt->font.value = g_strdup(st->font.value);
nt->font_family.value = g_strdup(st->font_family.value);
@@ -2701,6 +2735,7 @@ sp_text_style_write(gchar *p, guint const len, SPTextStyle const *const st, guin
flags = SP_STYLE_FLAG_IFSET;
d += sp_style_write_istring(p + d, len - d, "font-family", &st->font_family, NULL, flags);
+ d += sp_style_write_istring(p + d, len - d, "-inkscape-font-specification", &st->font_specification, NULL, flags);
return d;
}
@@ -3797,6 +3832,9 @@ sp_style_unset_property_attrs(SPObject *o)
if (style->stroke_dashoffset_set) {
repr->setAttribute("stroke-dashoffset", NULL);
}
+ if (style->text_private && style->text->font_specification.set) {
+ repr->setAttribute("-inkscape-font-specification", NULL);
+ }
if (style->text_private && style->text->font_family.set) {
repr->setAttribute("font-family", NULL);
}
@@ -3856,6 +3894,7 @@ SPCSSAttr *
sp_css_attr_unset_text(SPCSSAttr *css)
{
sp_repr_css_set_property(css, "font", NULL); // not implemented yet
+ sp_repr_css_set_property(css, "-inkscape-font-specification", NULL);
sp_repr_css_set_property(css, "font-size", NULL);
sp_repr_css_set_property(css, "font-size-adjust", NULL); // not implemented yet
sp_repr_css_set_property(css, "font-style", NULL);
diff --git a/src/style.h b/src/style.h
index 6e62187bc..47ba6955e 100644
--- a/src/style.h
+++ b/src/style.h
@@ -538,6 +538,9 @@ struct SPTextStyle {
/* CSS font properties */
SPIString font_family;
+ /* Full font name, as font_factory::ConstructFontSpecification would give */
+ SPIString font_specification;
+
/** \todo fixme: The 'font' property is ugly, and not working (lauris) */
SPIString font;
};
diff --git a/src/widgets/font-selector.cpp b/src/widgets/font-selector.cpp
index c9e5d0bbb..9da48d0e6 100644
--- a/src/widgets/font-selector.cpp
+++ b/src/widgets/font-selector.cpp
@@ -353,7 +353,7 @@ static void sp_font_selector_emit_set (SPFontSelector *fsel)
if ((!family) || (!style)) return;
- font = (font_factory::Default())->FaceFromDescr (family, style);
+ font = (font_factory::Default())->FaceFromUIStrings (family, style);
// FIXME: when a text object uses non-available font, font==NULL and we can't set size
// (and the size shown in the widget is invalid). To fix, here we must always get some
@@ -386,73 +386,103 @@ GtkWidget *sp_font_selector_new()
void sp_font_selector_set_font (SPFontSelector *fsel, font_instance *font, double size)
{
if (font)
- {
- gchar family[256];
- font->Family (family, 256);
-
- Gtk::TreePath path;
+ {
+ Gtk::TreePath path;
+ font_instance *tempFont = NULL;
+
+ Glib::ustring family = font_factory::Default()->GetUIFamilyString(font->descr);
+
+ try {
+ path = Inkscape::FontLister::get_instance()->get_row_for_font (family);
+ } catch (...) {
+ return;
+ }
- try {
- path = Inkscape::FontLister::get_instance()->get_row_for_font (family);
- } catch (...) {
- return;
+ fsel->block_emit = TRUE;
+ gtk_tree_selection_select_path (gtk_tree_view_get_selection (GTK_TREE_VIEW (fsel->family_treeview)), path.gobj());
+ gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (fsel->family_treeview), path.gobj(), NULL, TRUE, 0.5, 0.5);
+ fsel->block_emit = FALSE;
+
+ GList *list = 0;
+ GtkTreeIter iter;
+ GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW(fsel->family_treeview));
+ gtk_tree_model_get_iter (model, &iter, path.gobj());
+ gtk_tree_model_get (model, &iter, 1, &list, -1);
+
+ unsigned int currentStyleNumber = 0;
+ unsigned int bestStyleNumber = 0;
+
+ PangoFontDescription *incomingFont = pango_font_description_copy(font->descr);
+ pango_font_description_unset_fields(incomingFont, PANGO_FONT_MASK_SIZE);
+
+ char *incomingFontString = pango_font_description_to_string(incomingFont);
+
+ tempFont = (font_factory::Default())->FaceFromUIStrings(family.c_str(), (char*)list->data);
+
+ PangoFontDescription *bestMatchForFont = NULL;
+ if (tempFont) {
+ bestMatchForFont = pango_font_description_copy(tempFont->descr);
+ tempFont->Unref();
+ tempFont = NULL;
+ }
+
+ pango_font_description_unset_fields(bestMatchForFont, PANGO_FONT_MASK_SIZE);
+
+ list = list->next;
+
+ while (list) {
+ currentStyleNumber++;
+
+ tempFont = font_factory::Default()->FaceFromUIStrings(family.c_str(), (char*)list->data);
+
+ PangoFontDescription *currentMatchForFont = NULL;
+ if (tempFont) {
+ currentMatchForFont = pango_font_description_copy(tempFont->descr);
+ tempFont->Unref();
+ tempFont = NULL;
}
-
- fsel->block_emit = TRUE;
- gtk_tree_selection_select_path (gtk_tree_view_get_selection (GTK_TREE_VIEW (fsel->family_treeview)), path.gobj());
- gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (fsel->family_treeview), path.gobj(), NULL, TRUE, 0.5, 0.5);
- fsel->block_emit = FALSE;
-
- GList *list = 0;
- GtkTreeIter iter;
- GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW(fsel->family_treeview));
- gtk_tree_model_get_iter (model, &iter, path.gobj());
- gtk_tree_model_get (model, &iter, 1, &list, -1);
-
- gchar descr[256];
- font->Name(descr, 256);
- std::string descr_best (family);
- descr_best += " ";
- descr_best += ((char*)list->data);
-
- PangoFontDescription *descr_ = pango_font_description_from_string(descr);
- PangoFontDescription *best_ = pango_font_description_from_string(descr_best.c_str());
-
- unsigned int i = 0;
- unsigned int best_i = 0;
-
- // try to find best match with style description (i.e. bold, italic ?)
- for (list = list->next ; list ; list = list->next)
- {
- i++;
- std::string descr_try (family);
- descr_try += " ";
- descr_try += ((char*)list->data);
- PangoFontDescription *try_ = pango_font_description_from_string(descr_try.c_str());
- if (pango_font_description_better_match (descr_, best_, try_))
- {
- pango_font_description_free (best_);
- best_ = pango_font_description_from_string (descr_try.c_str ());
- best_i = i;
+
+ if (currentMatchForFont) {
+ pango_font_description_unset_fields(currentMatchForFont, PANGO_FONT_MASK_SIZE);
+
+ char *currentMatchString = pango_font_description_to_string(currentMatchForFont);
+
+ if (!strcmp(incomingFontString, currentMatchString)
+ || pango_font_description_better_match(incomingFont, bestMatchForFont, currentMatchForFont)) {
+ // Found a better match for the font we are looking for
+ pango_font_description_free(bestMatchForFont);
+ bestMatchForFont = pango_font_description_copy(currentMatchForFont);
+ bestStyleNumber = currentStyleNumber;
}
- pango_font_description_free(try_);
- }
- pango_font_description_free(descr_);
- pango_font_description_free(best_);
-
- GtkTreePath *path_c = gtk_tree_path_new ();
- gtk_tree_path_append_index (path_c, best_i);
- gtk_tree_selection_select_path (gtk_tree_view_get_selection (GTK_TREE_VIEW (fsel->style_treeview)), path_c);
- gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (fsel->style_treeview), path_c, NULL, TRUE, 0.5, 0.5);
-
- if (size != fsel->fontsize)
- {
- gchar s[8];
- g_snprintf (s, 8, "%.5g", size); // UI, so printf is ok
- gtk_entry_set_text (GTK_ENTRY (GTK_BIN(fsel->size)->child), s);
- fsel->fontsize = size;
+
+ g_free(currentMatchString);
+
+ pango_font_description_free(currentMatchForFont);
}
+
+ list = list->next;
+ }
+
+ if (bestMatchForFont)
+ pango_font_description_free(bestMatchForFont);
+ if (incomingFont)
+ pango_font_description_free(incomingFont);
+ g_free(incomingFontString);
+
+ GtkTreePath *path_c = gtk_tree_path_new ();
+ gtk_tree_path_append_index (path_c, bestStyleNumber);
+ gtk_tree_selection_select_path (gtk_tree_view_get_selection (GTK_TREE_VIEW (fsel->style_treeview)), path_c);
+ gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (fsel->style_treeview), path_c, NULL, TRUE, 0.5, 0.5);
+
+ if (size != fsel->fontsize)
+ {
+ gchar s[8];
+ g_snprintf (s, 8, "%.5g", size); // UI, so printf is ok
+ gtk_entry_set_text (GTK_ENTRY (GTK_BIN(fsel->size)->child), s);
+ fsel->fontsize = size;
+ }
}
+
}
font_instance* sp_font_selector_get_font(SPFontSelector *fsel)
diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp
index 9e9686e77..81eedaeb8 100644
--- a/src/widgets/toolbox.cpp
+++ b/src/widgets/toolbox.cpp
@@ -76,6 +76,7 @@
#include "document-private.h"
#include "desktop-style.h"
#include "../libnrtype/font-lister.h"
+#include "../libnrtype/font-instance.h"
#include "../connection-pool.h"
#include "../prefs-utils.h"
#include "../inkscape-stock.h"
@@ -2360,7 +2361,7 @@ static void box3d_toggle_vp_changed (GtkToggleAction *act, GObject *dataKludge,
// in turn, prevent listener from responding
g_object_set_data(dataKludge, "freeze", GINT_TO_POINTER(TRUE));
- persp3d_set_VP_state(persp, axis, gtk_toggle_action_get_active(act) ? Proj::INFINITE : Proj::FINITE);
+ persp3d_set_VP_state(persp, axis, (gtk_toggle_action_get_active(act) ? Proj::VP_INFINITE : Proj::VP_FINITE));
// FIXME: Can we merge this functionality with the one in box3d_persp_tb_event_attr_changed()?
gchar *str;
@@ -3948,6 +3949,9 @@ sp_text_toolbox_selection_changed (Inkscape::Selection */*selection*/, GObject *
{
SPStyle *query =
sp_style_new (SP_ACTIVE_DOCUMENT);
+
+ int result_fontspec =
+ sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONT_SPECIFICATION);
int result_family =
sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTFAMILY);
@@ -3981,15 +3985,27 @@ sp_text_toolbox_selection_changed (Inkscape::Selection */*selection*/, GObject *
GtkWidget *entry = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "family-entry"));
gtk_entry_set_text (GTK_ENTRY (entry), "");
- } else if (query->text->font_family.value) {
+ } else if (query->text->font_specification.value || query->text->font_family.value) {
GtkWidget *entry = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "family-entry"));
- gtk_entry_set_text (GTK_ENTRY (entry), query->text->font_family.value);
+
+ // Get the font that corresponds
+ Glib::ustring familyName;
+
+ font_instance * font = font_factory::Default()->FaceFromStyle(query);
+ if (font) {
+ familyName = font_factory::Default()->GetUIFamilyString(font->descr);
+ font->Unref();
+ font = NULL;
+ }
+
+ gtk_entry_set_text (GTK_ENTRY (entry), familyName.c_str());
Gtk::TreePath path;
try {
- path = Inkscape::FontLister::get_instance()->get_row_for_font (query->text->font_family.value);
+ path = Inkscape::FontLister::get_instance()->get_row_for_font (familyName);
} catch (...) {
+ g_warning("Family name %s does not have an entry in the font lister.", familyName.c_str());
return;
}
@@ -4142,14 +4158,46 @@ sp_text_toolbox_family_changed (GtkTreeSelection *selection,
SPStyle *query =
sp_style_new (SP_ACTIVE_DOCUMENT);
- int result_numbers =
- sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
-
+ int result_fontspec =
+ sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONT_SPECIFICATION);
+
SPCSSAttr *css = sp_repr_css_attr_new ();
- sp_repr_css_set_property (css, "font-family", family);
+
+ std::string fontSpec = query->text->font_specification.value;
+ if (!fontSpec.empty()) {
+ Glib::ustring newFontSpec = font_factory::Default()->ReplaceFontSpecificationFamily(fontSpec, family);
+ if (!newFontSpec.empty() && fontSpec != newFontSpec) {
+ font_instance *font = font_factory::Default()->FaceFromFontSpecification(newFontSpec.c_str());
+ if (font) {
+ sp_repr_css_set_property (css, "-inkscape-font-specification", newFontSpec.c_str());
+
+ // Set all the these just in case they were altered when finding the best
+ // match for the new family and old style...
+
+ gchar c[256];
+
+ font->Family(c, 256);
+ sp_repr_css_set_property (css, "font-family", c);
+
+ font->Attribute( "weight", c, 256);
+ sp_repr_css_set_property (css, "font-weight", c);
+
+ font->Attribute("style", c, 256);
+ sp_repr_css_set_property (css, "font-style", c);
+
+ font->Attribute("stretch", c, 256);
+ sp_repr_css_set_property (css, "font-stretch", c);
+
+ font->Attribute("variant", c, 256);
+ sp_repr_css_set_property (css, "font-variant", c);
+
+ font->Unref();
+ }
+ }
+ }
// If querying returned nothing, read the style from the text tool prefs (default style for new texts)
- if (result_numbers == QUERY_STYLE_NOTHING)
+ if (result_fontspec == QUERY_STYLE_NOTHING)
{
sp_repr_css_change (inkscape_get_repr (INKSCAPE, "tools.text"), css, "style");
sp_text_edit_dialog_default_set_insensitive (); //FIXME: Replace trough a verb
@@ -4264,29 +4312,45 @@ sp_text_toolbox_style_toggled (GtkToggleButton *button,
int prop = GPOINTER_TO_INT(data);
bool active = gtk_toggle_button_get_active (button);
+ SPStyle *query =
+ sp_style_new (SP_ACTIVE_DOCUMENT);
+ int result_fontspec =
+ sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONT_SPECIFICATION);
+
+ Glib::ustring fontSpec = query->text->font_specification.value;
+ Glib::ustring newFontSpec;
switch (prop)
{
case 0:
{
- sp_repr_css_set_property (css, "font-weight", active ? "bold" : "normal" );
+ if (!fontSpec.empty()) {
+ newFontSpec = font_factory::Default()->FontSpecificationSetBold(fontSpec, active);
+ }
+ if (fontSpec != newFontSpec) {
+ sp_repr_css_set_property (css, "font-weight", active ? "bold" : "normal" );
+ }
break;
}
case 1:
{
- sp_repr_css_set_property (css, "font-style", active ? "italic" : "normal");
+ if (!fontSpec.empty()) {
+ newFontSpec = font_factory::Default()->FontSpecificationSetItalic(fontSpec, active);
+ }
+ if (fontSpec != newFontSpec) {
+ sp_repr_css_set_property (css, "font-style", active ? "italic" : "normal");
+ }
break;
}
}
- SPStyle *query =
- sp_style_new (SP_ACTIVE_DOCUMENT);
- int result_numbers =
- sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS);
+ if (!fontSpec.empty()) {
+ sp_repr_css_set_property (css, "-inkscape-font-specification", fontSpec.c_str());
+ }
// If querying returned nothing, read the style from the text tool prefs (default style for new texts)
- if (result_numbers == QUERY_STYLE_NOTHING)
+ if (result_fontspec == QUERY_STYLE_NOTHING)
{
sp_repr_css_change (inkscape_get_repr (INKSCAPE, "tools.text"), css, "style");
}
@@ -5200,3 +5264,5 @@ static void sp_paintbucket_toolbox_prep(SPDesktop *desktop, GtkActionGroup* main
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+
+
diff --git a/src/xml/repr-css.cpp b/src/xml/repr-css.cpp
index d3c39e5a2..ec5848366 100644
--- a/src/xml/repr-css.cpp
+++ b/src/xml/repr-css.cpp
@@ -155,7 +155,9 @@ sp_repr_css_write_string(SPCSSAttr *css)
buffer.append(g_quark_to_string(iter->key));
buffer.push_back(':');
- if (!strcmp(g_quark_to_string(iter->key), "font-family")) { // we only quote font-family, as SPStyle does
+ if (!strcmp(g_quark_to_string(iter->key), "font-family")
+ || !strcmp(g_quark_to_string(iter->key), "-inkscape-font-specification")) {
+ // we only quote font-family/font-specification, as SPStyle does
gchar *t = g_strdup (iter->value);
g_free (t);
gchar *val_quoted = css2_escape_quote (iter->value);