summaryrefslogtreecommitdiffstats
path: root/src/libnrtype
diff options
context:
space:
mode:
authorTed Gould <ted@gould.cx>2010-05-15 18:08:17 +0000
committerTed Gould <ted@gould.cx>2010-05-15 18:08:17 +0000
commit2d8c2dfd832ce207aef3895e702bff4098ab7136 (patch)
tree642a37c6e3ca05d5e991ffe868f03c9cc58e51bc /src/libnrtype
parentMerge from trunk (diff)
parentMinor tweaks to text toolbar. (diff)
downloadinkscape-2d8c2dfd832ce207aef3895e702bff4098ab7136.tar.gz
inkscape-2d8c2dfd832ce207aef3895e702bff4098ab7136.zip
Updating to trunk
(bzr r8254.1.54)
Diffstat (limited to 'src/libnrtype')
-rw-r--r--src/libnrtype/FontFactory.cpp242
-rw-r--r--src/libnrtype/FontFactory.h2
-rw-r--r--src/libnrtype/FontInstance.cpp801
-rw-r--r--src/libnrtype/Layout-TNG-Input.cpp21
-rw-r--r--src/libnrtype/Layout-TNG-Output.cpp21
5 files changed, 637 insertions, 450 deletions
diff --git a/src/libnrtype/FontFactory.cpp b/src/libnrtype/FontFactory.cpp
index 06fb93f2d..067254b9e 100644
--- a/src/libnrtype/FontFactory.cpp
+++ b/src/libnrtype/FontFactory.cpp
@@ -22,6 +22,13 @@
#include "libnrtype/font-instance.h"
#include "util/unordered-containers.h"
+#if !PANGO_VERSION_CHECK(1,24,0)
+#define PANGO_WEIGHT_THIN static_cast<PangoWeight>(100)
+#define PANGO_WEIGHT_BOOK static_cast<PangoWeight>(380)
+#define PANGO_WEIGHT_MEDIUM static_cast<PangoWeight>(500)
+#define PANGO_WEIGHT_ULTRAHEAVY static_cast<PangoWeight>(1000)
+#endif
+
typedef INK_UNORDERED_MAP<PangoFontDescription*, font_instance*, font_descr_hash, font_descr_equal> FaceMapType;
// need to avoid using the size field
@@ -421,6 +428,14 @@ Glib::ustring font_factory::GetUIStyleString(PangoFontDescription const *fontDes
return style;
}
+/**
+ Replace font family leaving style alone (if possible).
+ @param fontSpec the given font
+ @param newFamily
+ @return the changed fontspec, if the property can not be set return an empty string
+ The routine first searches for an exact match.
+ If no exact match found, calls FontSpecificationBestMatch().
+*/
Glib::ustring font_factory::ReplaceFontSpecificationFamily(const Glib::ustring & fontSpec, const Glib::ustring & newFamily)
{
Glib::ustring newFontSpec;
@@ -431,10 +446,14 @@ Glib::ustring font_factory::ReplaceFontSpecificationFamily(const Glib::ustring &
// what constitutes a "family" in our own UI may be different from how Pango
// sees it.
- // Find the PangoFontDescription associated to this fontSpec
+ // Find the PangoFontDescription associated with the font specification string.
PangoStringToDescrMap::iterator it = fontInstanceMap.find(fontSpec);
+
if (it != fontInstanceMap.end()) {
+ // Description found!
+
+ // Make copy
PangoFontDescription *descr = pango_font_description_copy((*it).second);
// Grab the UI Family string from the descr
@@ -452,46 +471,9 @@ Glib::ustring font_factory::ReplaceFontSpecificationFamily(const Glib::ustring &
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;
+ // Search for best match, empty string returned if not found.
+ newFontSpec = FontSpecificationBestMatch( newFontSpec );
- pango_font_description_free(newFontDescr);
- pango_font_description_free(bestMatchForNewDescr);
}
}
@@ -502,92 +484,182 @@ Glib::ustring font_factory::ReplaceFontSpecificationFamily(const Glib::ustring &
}
/**
- apply style property to the given font
+ Apply style property to the given font
@param fontSpec the given font
@param turnOn true to set italic style
@return the changed fontspec, if the property can not be set return an empty string
+ The routine first searches for an exact match to "FontFamily Italic" or
+ "Font Family Oblique" (turnOn is true) or "FontFamily" (turnOn is false).
+ If no exact match found, calls FontSpecificationBestMatch().
*/
Glib::ustring font_factory::FontSpecificationSetItalic(const Glib::ustring & fontSpec, bool turnOn)
{
Glib::ustring newFontSpec;
- // Find the PangoFontDesecription that goes with this font specification string
+ // Find the PangoFontDescription associated with the 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 italic as needed
+ // Description found!
+
+ // Make copy.
PangoFontDescription *descr = pango_font_description_copy((*it).second);
PangoStyle style;
if (turnOn) {
- style = PANGO_STYLE_ITALIC;
+ // First try Oblique, we'll try Italic later
+ style = PANGO_STYLE_OBLIQUE;
} else {
style = PANGO_STYLE_NORMAL;
}
+
pango_font_description_set_style(descr, style);
newFontSpec = ConstructFontSpecification(descr);
+
+ bool exactMatchFound = true;
if (fontInstanceMap.find(newFontSpec) == fontInstanceMap.end()) {
- if(turnOn) {
- // there is no PANGO_STYLE_ITALIC let's test for PANGO_STYLE_OBLIQUE
- style = PANGO_STYLE_OBLIQUE;
+
+ exactMatchFound = false;
+ if (turnOn) {
+ // Next try Italic
+ style = PANGO_STYLE_ITALIC;
pango_font_description_set_style(descr, style);
- newFontSpec = ConstructFontSpecification(descr);
+ exactMatchFound = true;
if (fontInstanceMap.find(newFontSpec) == fontInstanceMap.end()) {
- // If the new font does not have even an oblique face, don't
- // allow italics to be set!
- newFontSpec = Glib::ustring("");
+ exactMatchFound = false;
}
-
- } else {
- // If the new font does not have an italic face, don't
- // allow italics to be set!
- newFontSpec = Glib::ustring("");
}
}
+ // Search for best match, empty string returned if not found.
+ if( !exactMatchFound ) {
+ newFontSpec = FontSpecificationBestMatch( newFontSpec );
+ }
+
pango_font_description_free(descr);
}
- return newFontSpec;
+ return newFontSpec; // Empty if not found.
}
/**
- apply width property to the given font
+ Apply weight property to the given font
@param fontSpec the given font
@param turnOn true to set bold
@return the changed fontspec, if the property can not be set return an empty string
+ This routine first searches for an exact match, if none found
+ it calls FontSpecificationBestMatch().
*/
Glib::ustring font_factory::FontSpecificationSetBold(const Glib::ustring & fontSpec, bool turnOn)
{
Glib::ustring newFontSpec;
- // Find the PangoFontDesecription that goes with this font specification string
+ // Find the PangoFontDescription associated with the 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
+ // Description found!
+
+ // Make copy.
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 = Glib::ustring("");
+ // Search for best match, empty string returned if not found.
+ newFontSpec = FontSpecificationBestMatch( newFontSpec );
}
pango_font_description_free(descr);
}
+ return newFontSpec; // Empty if not found.
+}
+
+/**
+ Use pango_font_description_better_match() to find best font match.
+ This handles cases like Century Schoolbook L where the "normal"
+ font is Century Schoolbook L Medium so just removing Italic
+ from the font name doesn't yield the correct name.
+ @param fontSpec the given font
+ @return the changed fontspec, if the property can not be set return an empty string
+*/
+// http://library.gnome.org/devel/pango/1.28/pango-Fonts.html#pango-font-description-better-match
+Glib::ustring font_factory::FontSpecificationBestMatch(const Glib::ustring & fontSpec )
+{
+
+ Glib::ustring newFontSpec;
+
+ // Look for exact match
+ PangoStringToDescrMap::iterator it = fontInstanceMap.find(fontSpec);
+
+ // If there is no exact match, look for the best match.
+ if (it != fontInstanceMap.end()) {
+
+ newFontSpec = fontSpec;
+
+ } else {
+
+ PangoFontDescription *fontDescr = pango_font_description_from_string(fontSpec.c_str());
+ PangoFontDescription *bestMatchDescr = NULL;
+
+ // Grab the UI Family string from the descr
+ Glib::ustring family = GetUIFamilyString(fontDescr);
+ Glib::ustring bestMatchDescription;
+
+ bool setFirstFamilyMatch = false;
+ for (it = fontInstanceMap.begin(); it != fontInstanceMap.end(); it++) {
+
+ Glib::ustring currentFontSpec = (*it).first;
+ Glib::ustring currentFamily = GetUIFamilyString((*it).second);
+
+ // Save some time by only looking at the right family.
+ // Must use family name rather than fontSpec
+ // (otherwise DejaVu Sans matches DejaVu Sans Mono).
+ if (currentFamily == family) {
+ if (!setFirstFamilyMatch) {
+ // This ensures that the closest match is at least within the correct
+ // family rather than the first font in the list
+ bestMatchDescr = pango_font_description_copy((*it).second);
+ bestMatchDescription = 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(
+ fontDescr, bestMatchDescr, possibleMatch)) {
+
+ pango_font_description_free(bestMatchDescr);
+ bestMatchDescr = possibleMatch;
+ bestMatchDescription = currentFontSpec;
+ } else {
+ pango_font_description_free(possibleMatch);
+ }
+ }
+ }
+ } // for
+
+ newFontSpec = bestMatchDescription; // If NULL, then no match found
+
+ pango_font_description_free(fontDescr);
+ pango_font_description_free(bestMatchDescr);
+
+ }
+
return newFontSpec;
}
@@ -689,6 +761,7 @@ font_instance* font_factory::FaceFromStyle(SPStyle const *style)
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
@@ -699,7 +772,16 @@ font_instance* font_factory::FaceFromStyle(SPStyle const *style)
// 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));
+
+ // That was a hatchet job... so we need to check if this font exists!!
+ Glib::ustring fontSpec = font_factory::Default()->ConstructFontSpecification(font);
+ Glib::ustring newFontSpec = FontSpecificationBestMatch( fontSpec );
+ if( fontSpec != newFontSpec ) {
+ font->Unref();
+ font = FaceFromFontSpecification( newFontSpec.c_str() );
+ }
}
}
@@ -899,12 +981,20 @@ font_instance *font_factory::Face(char const *family, NRTypePosDef apos)
pango_font_description_set_style(temp_descr, PANGO_STYLE_NORMAL);
}
- if ( apos.weight <= NR_POS_WEIGHT_ULTRA_LIGHT ) {
+ if ( apos.weight <= NR_POS_WEIGHT_THIN ) {
+ pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_THIN);
+ } else if ( apos.weight <= NR_POS_WEIGHT_ULTRA_LIGHT ) {
pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_ULTRALIGHT);
} else if ( apos.weight <= NR_POS_WEIGHT_LIGHT ) {
pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_LIGHT);
+ } else if ( apos.weight <= NR_POS_WEIGHT_BOOK ) {
+ pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_BOOK);
} else if ( apos.weight <= NR_POS_WEIGHT_NORMAL ) {
pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_NORMAL);
+ } else if ( apos.weight <= NR_POS_WEIGHT_MEDIUM ) {
+ pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_MEDIUM);
+ } else if ( apos.weight <= NR_POS_WEIGHT_SEMIBOLD ) {
+ pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_SEMIBOLD);
} else if ( apos.weight <= NR_POS_WEIGHT_BOLD ) {
pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_BOLD);
} else if ( apos.weight <= NR_POS_WEIGHT_ULTRA_BOLD ) {
@@ -912,6 +1002,7 @@ font_instance *font_factory::Face(char const *family, NRTypePosDef apos)
} else {
pango_font_description_set_weight(temp_descr, PANGO_WEIGHT_HEAVY);
}
+ // PANGO_WIEGHT_ULTRAHEAVY not used (not CSS2)
if ( apos.stretch <= NR_POS_STRETCH_ULTRA_CONDENSED ) {
pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_EXTRA_CONDENSED);
@@ -919,7 +1010,7 @@ font_instance *font_factory::Face(char const *family, NRTypePosDef apos)
pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_CONDENSED);
} else if ( apos.stretch <= NR_POS_STRETCH_SEMI_CONDENSED ) {
pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_SEMI_CONDENSED);
- } else if ( apos.stretch <= NR_POS_WEIGHT_NORMAL ) {
+ } else if ( apos.stretch <= NR_POS_STRETCH_NORMAL ) {
pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_NORMAL);
} else if ( apos.stretch <= NR_POS_STRETCH_SEMI_EXPANDED ) {
pango_font_description_set_stretch(temp_descr, PANGO_STRETCH_SEMI_EXPANDED);
@@ -946,7 +1037,7 @@ void font_factory::UnrefFace(font_instance *who)
g_free(tc);
} else {
loadedFaces.erase(loadedFaces.find(who->descr));
- // printf("unrefFace %p: success\n",who);
+ // printf("unrefFace %p: success\n",who);
}
}
}
@@ -957,7 +1048,7 @@ void font_factory::AddInCache(font_instance *who)
for (int i = 0;i < nbEnt;i++) ents[i].age *= 0.9;
for (int i = 0;i < nbEnt;i++) {
if ( ents[i].f == who ) {
- // printf("present\n");
+ // printf("present\n");
ents[i].age += 1.0;
return;
}
@@ -984,6 +1075,23 @@ void font_factory::AddInCache(font_instance *who)
nbEnt++;
}
+/*
+ {
+ std::cout << " Printing out fontInstanceMap: " << std::endl;
+ PangoStringToDescrMap::iterator it = fontInstanceMap.begin();
+ while (it != fontInstanceMap.end()) {
+
+ PangoFontDescription *descr = pango_font_description_copy((*it).second);
+
+ // Grab the UI Family string from the descr
+ Glib::ustring uiFamily = GetUIFamilyString(descr);
+ Glib::ustring uiStyle = GetUIStyleString(descr);
+ std::cout << " " << uiFamily << " " << uiStyle << std::endl;
+
+ it++;
+ }
+ }
+*/
/*
Local Variables:
diff --git a/src/libnrtype/FontFactory.h b/src/libnrtype/FontFactory.h
index 0118c862d..632ea565f 100644
--- a/src/libnrtype/FontFactory.h
+++ b/src/libnrtype/FontFactory.h
@@ -102,6 +102,8 @@ public:
Glib::ustring FontSpecificationSetItalic(const Glib::ustring & fontSpec, bool turnOn);
Glib::ustring FontSpecificationSetBold(const Glib::ustring & fontSpec, bool turnOn);
+ Glib::ustring FontSpecificationBestMatch(const Glib::ustring& fontSpec );
+
// Gathers all strings needed for UI while storing pango information in
// fontInstanceMap and fontStringMap
void GetUIFamiliesAndStyles(FamilyToStylesMap *map);
diff --git a/src/libnrtype/FontInstance.cpp b/src/libnrtype/FontInstance.cpp
index be5eb86c8..b958e899d 100644
--- a/src/libnrtype/FontInstance.cpp
+++ b/src/libnrtype/FontInstance.cpp
@@ -28,6 +28,13 @@
#include "livarot/Path.h"
#include "util/unordered-containers.h"
+#if !PANGO_VERSION_CHECK(1,24,0)
+#define PANGO_WEIGHT_THIN static_cast<PangoWeight>(100)
+#define PANGO_WEIGHT_BOOK static_cast<PangoWeight>(380)
+#define PANGO_WEIGHT_MEDIUM static_cast<PangoWeight>(500)
+#define PANGO_WEIGHT_ULTRAHEAVY static_cast<PangoWeight>(1000)
+#endif
+
struct font_style_hash : public std::unary_function<font_style, size_t> {
size_t operator()(font_style const &x) const;
@@ -39,57 +46,59 @@ struct font_style_equal : public std::binary_function<font_style, font_style, bo
typedef INK_UNORDERED_MAP<font_style, raster_font*, font_style_hash, font_style_equal> StyleMap;
-
-
-size_t font_style_hash::operator()(const font_style &x) const {
- int h=0,n;
- n=(int)floor(100*x.stroke_width);
- h*=12186;
- h+=n;
- n=(x.vertical)?1:0;
- h*=12186;
- h+=n;
- if ( x.stroke_width >= 0.01 ) {
- n=x.stroke_cap*10+x.stroke_join+(int)(x.stroke_miter_limit*100);
- h*=12186;
- h+=n;
- if ( x.nbDash > 0 ) {
- n=x.nbDash;
- h*=12186;
- h+=n;
- n=(int)floor(100*x.dash_offset);
- h*=12186;
- h+=n;
- for (int i=0;i<x.nbDash;i++) {
- n=(int)floor(100*x.dashes[i]);
- h*=12186;
- h+=n;
- }
- }
- }
- return h;
+static const double STROKE_WIDTH_THREASHOLD = 0.01;
+
+
+
+size_t font_style_hash::operator()(const font_style &x) const {
+ int h = 0;
+ int n = static_cast<int>(floor(100 * x.stroke_width));
+ h *= 12186;
+ h += n;
+ n = (x.vertical) ? 1:0;
+ h *= 12186;
+ h += n;
+ if ( x.stroke_width >= STROKE_WIDTH_THREASHOLD ) {
+ n = x.stroke_cap * 10 + x.stroke_join + static_cast<int>(x.stroke_miter_limit * 100);
+ h *= 12186;
+ h += n;
+ if ( x.nbDash > 0 ) {
+ n = x.nbDash;
+ h *= 12186;
+ h += n;
+ n = static_cast<int>(floor(100 * x.dash_offset));
+ h *= 12186;
+ h += n;
+ for (int i = 0; i < x.nbDash; i++) {
+ n = static_cast<int>(floor(100 * x.dashes[i]));
+ h *= 12186;
+ h += n;
+ }
+ }
+ }
+ return h;
}
-bool font_style_equal::operator()(const font_style &a,const font_style &b) const {
- for (int i=0;i<6;i++) {
- if ( (int)(100*a.transform[i]) != (int)(100*b.transform[i]) ) return false;
- }
- if ( a.vertical && b.vertical == false ) return false;
- if ( a.vertical == false && b.vertical ) return false;
- if ( a.stroke_width > 0.01 && b.stroke_width <= 0.01 ) return false;
- if ( a.stroke_width <= 0.01 && b.stroke_width > 0.01 ) return false;
- if ( a.stroke_width <= 0.01 && b.stroke_width <= 0.01 ) return true;
-
- if ( a.stroke_cap != b.stroke_cap ) return false;
- if ( a.stroke_join != b.stroke_join ) return false;
- if ( (int)(a.stroke_miter_limit*100) != (int)(b.stroke_miter_limit*100) ) return false;
- if ( a.nbDash != b.nbDash ) return false;
- if ( a.nbDash <= 0 ) return true;
- if ( (int)floor(100*a.dash_offset) != (int)floor(100*b.dash_offset) ) return false;
- for (int i=0;i<a.nbDash;i++) {
- if ( (int)floor(100*a.dashes[i]) != (int)floor(100*b.dashes[i]) ) return false;
- }
- return true;
+bool font_style_equal::operator()(const font_style &a,const font_style &b) const {
+ bool same = true;
+ for (int i = 0; (i < 6) && same; i++) {
+ same = ( static_cast<int>(100 * a.transform[i]) == static_cast<int>(100 * b.transform[i]) );
+ }
+ same &= ( a.vertical == b.vertical )
+ && ( a.stroke_width > STROKE_WIDTH_THREASHOLD ) == ( b.stroke_width > STROKE_WIDTH_THREASHOLD );
+ if ( same && ( a.stroke_width > STROKE_WIDTH_THREASHOLD ) ) {
+ same = ( a.stroke_cap == b.stroke_cap )
+ && ( a.stroke_join == b.stroke_join )
+ && ( static_cast<int>(a.stroke_miter_limit * 100) == static_cast<int>(b.stroke_miter_limit * 100) )
+ && ( a.nbDash == b.nbDash );
+ if ( same && ( a.nbDash > 0 ) ) {
+ same = ( static_cast<int>(floor(100 * a.dash_offset)) == static_cast<int>(floor(100 * b.dash_offset)) );
+ for (int i = 0; (i < a.nbDash) && same; i++) {
+ same = ( static_cast<int>(floor(100 * a.dashes[i])) == static_cast<int>(floor(100 * b.dashes[i])) );
+ }
+ }
+ }
+ return same;
}
#ifndef USE_PANGO_WIN32
@@ -97,9 +106,9 @@ bool font_style_equal::operator()(const font_style &a,const font_style &b) cons
* Outline extraction
*/
typedef struct ft2_to_liv {
- Path* theP;
- double scale;
- Geom::Point last;
+ Path* theP;
+ double scale;
+ Geom::Point last;
} ft2_to_liv;
// Note: Freetype 2.2.1 redefined function signatures for functions to be placed in an
@@ -116,46 +125,46 @@ typedef FT_Vector FREETYPE_VECTOR;
// outline as returned by freetype -> livarot Path
// see nr-type-ft2.cpp for the freetype -> artBPath on which this code is based
static int ft2_move_to(FREETYPE_VECTOR *to, void * i_user) {
- ft2_to_liv* user=(ft2_to_liv*)i_user;
- Geom::Point p(user->scale*to->x,user->scale*to->y);
- // printf("m t=%f %f\n",p[0],p[1]);
- user->theP->MoveTo(p);
- user->last=p;
- return 0;
+ ft2_to_liv* user=(ft2_to_liv*)i_user;
+ Geom::Point p(user->scale*to->x,user->scale*to->y);
+ // printf("m t=%f %f\n",p[0],p[1]);
+ user->theP->MoveTo(p);
+ user->last=p;
+ return 0;
}
static int ft2_line_to(FREETYPE_VECTOR *to, void *i_user)
{
- ft2_to_liv* user=(ft2_to_liv*)i_user;
- Geom::Point p(user->scale*to->x,user->scale*to->y);
- // printf("l t=%f %f\n",p[0],p[1]);
- user->theP->LineTo(p);
- user->last=p;
- return 0;
+ ft2_to_liv* user=(ft2_to_liv*)i_user;
+ Geom::Point p(user->scale*to->x,user->scale*to->y);
+ // printf("l t=%f %f\n",p[0],p[1]);
+ user->theP->LineTo(p);
+ user->last=p;
+ return 0;
}
static int ft2_conic_to(FREETYPE_VECTOR *control, FREETYPE_VECTOR *to, void *i_user)
{
- ft2_to_liv* user=(ft2_to_liv*)i_user;
- Geom::Point p(user->scale*to->x,user->scale*to->y),c(user->scale*control->x,user->scale*control->y);
- // printf("b c=%f %f t=%f %f\n",c[0],c[1],p[0],p[1]);
- user->theP->BezierTo(p);
- user->theP->IntermBezierTo(c);
- user->theP->EndBezierTo();
- user->last=p;
- return 0;
+ ft2_to_liv* user=(ft2_to_liv*)i_user;
+ Geom::Point p(user->scale*to->x,user->scale*to->y),c(user->scale*control->x,user->scale*control->y);
+ // printf("b c=%f %f t=%f %f\n",c[0],c[1],p[0],p[1]);
+ user->theP->BezierTo(p);
+ user->theP->IntermBezierTo(c);
+ user->theP->EndBezierTo();
+ user->last=p;
+ return 0;
}
static int ft2_cubic_to(FREETYPE_VECTOR *control1, FREETYPE_VECTOR *control2, FREETYPE_VECTOR *to, void *i_user)
{
- ft2_to_liv* user=(ft2_to_liv*)i_user;
- Geom::Point p(user->scale*to->x,user->scale*to->y),
- c1(user->scale*control1->x,user->scale*control1->y),
- c2(user->scale*control2->x,user->scale*control2->y);
- // printf("c c1=%f %f c2=%f %f t=%f %f\n",c1[0],c1[1],c2[0],c2[1],p[0],p[1]);
- user->theP->CubicTo(p,3*(c1-user->last),3*(p-c2));
- user->last=p;
- return 0;
+ ft2_to_liv* user=(ft2_to_liv*)i_user;
+ Geom::Point p(user->scale*to->x,user->scale*to->y);
+ Geom::Point c1(user->scale*control1->x,user->scale*control1->y);
+ Geom::Point c2(user->scale*control2->x,user->scale*control2->y);
+ // printf("c c1=%f %f c2=%f %f t=%f %f\n",c1[0],c1[1],c2[0],c2[1],p[0],p[1]);
+ user->theP->CubicTo(p,3*(c1-user->last),3*(p-c2));
+ user->last=p;
+ return 0;
}
#endif
@@ -203,7 +212,7 @@ font_instance::~font_instance(void)
descr = 0;
}
- // if ( theFace ) FT_Done_Face(theFace); // owned by pFont. don't touch
+ // if ( theFace ) FT_Done_Face(theFace); // owned by pFont. don't touch
theFace = 0;
for (int i=0;i<nbGlyph;i++) {
@@ -224,56 +233,60 @@ font_instance::~font_instance(void)
void font_instance::Ref(void)
{
- refCount++;
- //char *tc=pango_font_description_to_string(descr);
- //printf("font %x %s ref'd %i\n",this,tc,refCount);
- //free(tc);
+ refCount++;
+ //char *tc=pango_font_description_to_string(descr);
+ //printf("font %x %s ref'd %i\n",this,tc,refCount);
+ //free(tc);
}
void font_instance::Unref(void)
{
- refCount--;
- //char *tc=pango_font_description_to_string(descr);
- //printf("font %x %s unref'd %i\n",this,tc,refCount);
- //free(tc);
- if ( refCount <= 0 ) {
- if ( daddy ) daddy->UnrefFace(this);
- daddy=NULL;
- delete this;
- }
+ refCount--;
+ //char *tc=pango_font_description_to_string(descr);
+ //printf("font %x %s unref'd %i\n",this,tc,refCount);
+ //free(tc);
+ if ( refCount <= 0 ) {
+ if ( daddy ) {
+ daddy->UnrefFace(this);
+ }
+ daddy=NULL;
+ delete this;
+ }
}
unsigned int font_instance::Name(gchar *str, unsigned int size)
{
- return Attribute("name", str, size);
+ return Attribute("name", str, size);
}
unsigned int font_instance::Family(gchar *str, unsigned int size)
{
- return Attribute("family", str, size);
+ return Attribute("family", str, size);
}
unsigned int font_instance::PSName(gchar *str, unsigned int size)
{
- return Attribute("psname", str, size);
+ return Attribute("psname", str, size);
}
unsigned int font_instance::Attribute(const gchar *key, gchar *str, unsigned int size)
{
- if ( descr == NULL ) {
- if ( size > 0 ) str[0]=0;
- return 0;
- }
- char* res=NULL;
- bool free_res=false;
-
- if ( strcmp(key,"name") == 0 ) {
- PangoFontDescription* td=pango_font_description_copy(descr);
- pango_font_description_unset_fields (td, PANGO_FONT_MASK_SIZE);
- res=pango_font_description_to_string (td);
- pango_font_description_free(td);
- free_res=true;
- } else if ( strcmp(key,"psname") == 0 ) {
+ if ( descr == NULL ) {
+ if ( size > 0 ) {
+ str[0]=0;
+ }
+ return 0;
+ }
+ char* res=NULL;
+ bool free_res=false;
+
+ if ( strcmp(key,"name") == 0 ) {
+ PangoFontDescription* td=pango_font_description_copy(descr);
+ pango_font_description_unset_fields (td, PANGO_FONT_MASK_SIZE);
+ res=pango_font_description_to_string (td);
+ pango_font_description_free(td);
+ free_res=true;
+ } else if ( strcmp(key,"psname") == 0 ) {
#ifndef USE_PANGO_WIN32
res = (char *) FT_Get_Postscript_Name (theFace); // that's the main method, seems to always work
#endif
@@ -292,81 +305,97 @@ unsigned int font_instance::Attribute(const gchar *key, gchar *str, unsigned int
(i) ? "Italic" : ((o) ? "Oblique" : "") );
free_res = true;
}
- } else if ( strcmp(key,"family") == 0 ) {
- res=(char*)pango_font_description_get_family(descr);
- free_res=false;
- } else if ( strcmp(key,"style") == 0 ) {
- PangoStyle v=pango_font_description_get_style(descr);
- if ( v == PANGO_STYLE_ITALIC ) {
- res=(char*)"italic";
- } else if ( v == PANGO_STYLE_OBLIQUE ) {
- res=(char*)"oblique";
- } else {
- res=(char*)"normal";
- }
- free_res=false;
- } else if ( strcmp(key,"weight") == 0 ) {
- PangoWeight v=pango_font_description_get_weight(descr);
- if ( v <= PANGO_WEIGHT_ULTRALIGHT ) {
- res=(char*)"200";
- } else if ( v <= PANGO_WEIGHT_LIGHT ) {
- res=(char*)"300";
- } else if ( v <= PANGO_WEIGHT_NORMAL ) {
- res=(char*)"normal";
- } else if ( v <= PANGO_WEIGHT_BOLD ) {
- res=(char*)"bold";
- } else if ( v <= PANGO_WEIGHT_ULTRABOLD ) {
- res=(char*)"800";
- } else { // HEAVY
- res=(char*)"900";
- }
- free_res=false;
- } else if ( strcmp(key,"stretch") == 0 ) {
- PangoStretch v=pango_font_description_get_stretch(descr);
- if ( v <= PANGO_STRETCH_EXTRA_CONDENSED ) {
- res=(char*)"extra-condensed";
- } else if ( v <= PANGO_STRETCH_CONDENSED ) {
- res=(char*)"condensed";
- } else if ( v <= PANGO_STRETCH_SEMI_CONDENSED ) {
- res=(char*)"semi-condensed";
- } else if ( v <= PANGO_STRETCH_NORMAL ) {
- res=(char*)"normal";
- } else if ( v <= PANGO_STRETCH_SEMI_EXPANDED ) {
- res=(char*)"semi-expanded";
- } else if ( v <= PANGO_STRETCH_EXPANDED ) {
- res=(char*)"expanded";
- } else {
- res=(char*)"extra-expanded";
- }
- free_res=false;
- } else if ( strcmp(key,"variant") == 0 ) {
- PangoVariant v=pango_font_description_get_variant(descr);
- if ( v == PANGO_VARIANT_SMALL_CAPS ) {
- res=(char*)"small-caps";
- } else {
- res=(char*)"normal";
- }
- free_res=false;
- } else {
- res = NULL;
- free_res=false;
- }
- if ( res == NULL ) {
- if ( size > 0 ) str[0]=0;
- return 0;
- }
-
- if (res) {
- unsigned int len=strlen(res);
- unsigned int rlen=(size-1<len)?size-1:len;
- if ( str ) {
- if ( rlen > 0 ) memcpy(str,res,rlen);
- if ( size > 0 ) str[rlen]=0;
- }
- if (free_res) free(res);
- return len;
- }
- return 0;
+ } else if ( strcmp(key,"family") == 0 ) {
+ res=(char*)pango_font_description_get_family(descr);
+ free_res=false;
+ } else if ( strcmp(key,"style") == 0 ) {
+ PangoStyle v=pango_font_description_get_style(descr);
+ if ( v == PANGO_STYLE_ITALIC ) {
+ res=(char*)"italic";
+ } else if ( v == PANGO_STYLE_OBLIQUE ) {
+ res=(char*)"oblique";
+ } else {
+ res=(char*)"normal";
+ }
+ free_res=false;
+ } else if ( strcmp(key,"weight") == 0 ) {
+ PangoWeight v=pango_font_description_get_weight(descr);
+ if ( v <= PANGO_WEIGHT_THIN ) {
+ res=(char*)"100";
+ } else if ( v <= PANGO_WEIGHT_ULTRALIGHT ) {
+ res=(char*)"200";
+ } else if ( v <= PANGO_WEIGHT_LIGHT ) {
+ res=(char*)"300";
+ } else if ( v <= PANGO_WEIGHT_BOOK ) {
+ res=(char*)"380";
+ } else if ( v <= PANGO_WEIGHT_NORMAL ) {
+ res=(char*)"normal";
+ } else if ( v <= PANGO_WEIGHT_MEDIUM ) {
+ res=(char*)"500";
+ } else if ( v <= PANGO_WEIGHT_SEMIBOLD ) {
+ res=(char*)"600";
+ } else if ( v <= PANGO_WEIGHT_BOLD ) {
+ res=(char*)"bold";
+ } else if ( v <= PANGO_WEIGHT_ULTRABOLD ) {
+ res=(char*)"800";
+ } else { // HEAVY NB: Pango defines ULTRAHEAVY = 1000 but not CSS2
+ res=(char*)"900";
+ }
+ free_res=false;
+ } else if ( strcmp(key,"stretch") == 0 ) {
+ PangoStretch v=pango_font_description_get_stretch(descr);
+ if ( v <= PANGO_STRETCH_EXTRA_CONDENSED ) {
+ res=(char*)"extra-condensed";
+ } else if ( v <= PANGO_STRETCH_CONDENSED ) {
+ res=(char*)"condensed";
+ } else if ( v <= PANGO_STRETCH_SEMI_CONDENSED ) {
+ res=(char*)"semi-condensed";
+ } else if ( v <= PANGO_STRETCH_NORMAL ) {
+ res=(char*)"normal";
+ } else if ( v <= PANGO_STRETCH_SEMI_EXPANDED ) {
+ res=(char*)"semi-expanded";
+ } else if ( v <= PANGO_STRETCH_EXPANDED ) {
+ res=(char*)"expanded";
+ } else {
+ res=(char*)"extra-expanded";
+ }
+ free_res=false;
+ } else if ( strcmp(key,"variant") == 0 ) {
+ PangoVariant v=pango_font_description_get_variant(descr);
+ if ( v == PANGO_VARIANT_SMALL_CAPS ) {
+ res=(char*)"small-caps";
+ } else {
+ res=(char*)"normal";
+ }
+ free_res=false;
+ } else {
+ res = NULL;
+ free_res=false;
+ }
+ if ( res == NULL ) {
+ if ( size > 0 ) {
+ str[0] = 0;
+ }
+ return 0;
+ }
+
+ if (res) {
+ unsigned int len=strlen(res);
+ unsigned int rlen=(size-1<len)?size-1:len;
+ if ( str ) {
+ if ( rlen > 0 ) {
+ memcpy(str, res, rlen);
+ }
+ if ( size > 0 ) {
+ str[rlen] = 0;
+ }
+ }
+ if (free_res) {
+ free(res);
+ }
+ return len;
+ }
+ return 0;
}
void font_instance::InitTheFace()
@@ -383,9 +412,10 @@ void font_instance::InitTheFace()
SetGraphicsMode(daddy->hScreenDC, GM_COMPATIBLE);
SelectObject(daddy->hScreenDC,theFace);
#else
- theFace=pango_ft2_font_get_face(pFont);
- if ( theFace )
+ theFace=pango_ft2_font_get_face(pFont);
+ if ( theFace ) {
FT_Select_Charmap(theFace,ft_encoding_unicode) && FT_Select_Charmap(theFace,ft_encoding_symbol);
+ }
#endif
}
@@ -400,46 +430,52 @@ void font_instance::FreeTheFace()
void font_instance::InstallFace(PangoFont* iFace)
{
- if ( !iFace )
- return;
- pFont=iFace;
+ if ( !iFace ) {
+ return;
+ }
+ pFont=iFace;
InitTheFace();
- if ( pFont && IsOutlineFont() == false ) {
+ if ( pFont && IsOutlineFont() == false ) {
FreeTheFace();
- if ( pFont ) g_object_unref(pFont);
- pFont=NULL;
- }
+ if ( pFont ) {
+ g_object_unref(pFont);
+ }
+ pFont=NULL;
+ }
}
-bool font_instance::IsOutlineFont(void)
+bool font_instance::IsOutlineFont(void)
{
- if ( pFont == NULL ) return false;
+ if ( pFont == NULL ) {
+ return false;
+ }
InitTheFace();
#ifdef USE_PANGO_WIN32
TEXTMETRIC tm;
return GetTextMetrics(daddy->hScreenDC,&tm) && tm.tmPitchAndFamily&(TMPF_TRUETYPE|TMPF_DEVICE);
#else
- return FT_IS_SCALABLE(theFace);
+ return FT_IS_SCALABLE(theFace);
#endif
}
int font_instance::MapUnicodeChar(gunichar c)
{
- if ( pFont == NULL ) return 0;
+ int res = 0;
+ if ( pFont ) {
#ifdef USE_PANGO_WIN32
- return pango_win32_font_get_glyph_index(pFont,c);
+ res = pango_win32_font_get_glyph_index(pFont, c);
#else
- int res=0;
- theFace=pango_ft2_font_get_face(pFont);
- if ( c > 0xf0000 ) {
- res=CLAMP(c,0xf0000,0x1fffff)-0xf0000;
- } else {
- res=FT_Get_Char_Index(theFace, c);
- }
- return res;
+ theFace = pango_ft2_font_get_face(pFont);
+ if ( c > 0xf0000 ) {
+ res = CLAMP(c, 0xf0000, 0x1fffff) - 0xf0000;
+ } else {
+ res = FT_Get_Char_Index(theFace, c);
+ }
#endif
+ }
+ return res;
}
@@ -453,22 +489,26 @@ static inline Geom::Point pointfx_to_nrpoint(const POINTFX &p, double scale)
void font_instance::LoadGlyph(int glyph_id)
{
- if ( pFont == NULL ) return;
+ if ( pFont == NULL ) {
+ return;
+ }
InitTheFace();
#ifndef USE_PANGO_WIN32
- if ( !FT_IS_SCALABLE(theFace) ) return; // bitmap font
+ if ( !FT_IS_SCALABLE(theFace) ) {
+ return; // bitmap font
+ }
#endif
- if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
- if ( nbGlyph >= maxGlyph ) {
- maxGlyph=2*nbGlyph+1;
- glyphs=(font_glyph*)realloc(glyphs,maxGlyph*sizeof(font_glyph));
- }
- font_glyph n_g;
- n_g.outline=NULL;
+ if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
+ if ( nbGlyph >= maxGlyph ) {
+ maxGlyph=2*nbGlyph+1;
+ glyphs=(font_glyph*)realloc(glyphs,maxGlyph*sizeof(font_glyph));
+ }
+ font_glyph n_g;
+ n_g.outline=NULL;
n_g.pathvector=NULL;
- n_g.bbox[0]=n_g.bbox[1]=n_g.bbox[2]=n_g.bbox[3]=0;
- bool doAdd=false;
+ n_g.bbox[0]=n_g.bbox[1]=n_g.bbox[2]=n_g.bbox[3]=0;
+ bool doAdd=false;
#ifdef USE_PANGO_WIN32
@@ -493,15 +533,15 @@ void font_instance::LoadGlyph(int glyph_id)
// character has no visual representation, but is valid (eg whitespace)
doAdd=true;
} else {
- std::auto_ptr<char> buffer(new char[bufferSize]);
- if ( GetGlyphOutline (daddy->hScreenDC, glyph_id, GGO_GLYPH_INDEX | GGO_NATIVE | GGO_UNHINTED, &metrics, bufferSize, buffer.get(), &identity) <= 0 ) {
+ char *buffer = new char[bufferSize];
+ if ( GetGlyphOutline (daddy->hScreenDC, glyph_id, GGO_GLYPH_INDEX | GGO_NATIVE | GGO_UNHINTED, &metrics, bufferSize, buffer, &identity) <= 0 ) {
// shit happened
} else {
// Platform SDK is rubbish, read KB87115 instead
n_g.outline=new Path;
DWORD polyOffset=0;
while ( polyOffset < bufferSize ) {
- TTPOLYGONHEADER const *polyHeader=(TTPOLYGONHEADER const *)(buffer.get()+polyOffset);
+ TTPOLYGONHEADER const *polyHeader=(TTPOLYGONHEADER const *)(buffer+polyOffset);
if (polyOffset+polyHeader->cb > bufferSize) break;
if (polyHeader->dwType == TT_POLYGON_TYPE) {
@@ -509,7 +549,7 @@ void font_instance::LoadGlyph(int glyph_id)
DWORD curveOffset=polyOffset+sizeof(TTPOLYGONHEADER);
while ( curveOffset < polyOffset+polyHeader->cb ) {
- TTPOLYCURVE const *polyCurve=(TTPOLYCURVE const *)(buffer.get()+curveOffset);
+ TTPOLYCURVE const *polyCurve=(TTPOLYCURVE const *)(buffer+curveOffset);
POINTFX const *p=polyCurve->apfx;
POINTFX const *endp=p+polyCurve->cpfx;
@@ -526,15 +566,15 @@ void font_instance::LoadGlyph(int glyph_id)
Geom::Point this_mid=pointfx_to_nrpoint(p[0], scale);
while ( p != endp ) {
Geom::Point next_mid=pointfx_to_nrpoint(p[1], scale);
- n_g.outline->BezierTo((next_mid+this_mid)/2);
- n_g.outline->IntermBezierTo(this_mid);
- n_g.outline->EndBezierTo();
+ n_g.outline->BezierTo((next_mid+this_mid)/2);
+ n_g.outline->IntermBezierTo(this_mid);
+ n_g.outline->EndBezierTo();
++p;
this_mid=next_mid;
}
- n_g.outline->BezierTo(pointfx_to_nrpoint(p[1], scale));
- n_g.outline->IntermBezierTo(this_mid);
- n_g.outline->EndBezierTo();
+ n_g.outline->BezierTo(pointfx_to_nrpoint(p[1], scale));
+ n_g.outline->IntermBezierTo(this_mid);
+ n_g.outline->EndBezierTo();
break;
}
@@ -554,75 +594,84 @@ void font_instance::LoadGlyph(int glyph_id)
}
doAdd=true;
}
+ delete [] buffer;
}
#else
- if (FT_Load_Glyph (theFace, glyph_id, FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP)) {
- // shit happened
- } else {
- if ( FT_HAS_HORIZONTAL(theFace) ) {
- n_g.h_advance=((double)theFace->glyph->metrics.horiAdvance)/((double)theFace->units_per_EM);
- n_g.h_width=((double)theFace->glyph->metrics.width)/((double)theFace->units_per_EM);
- } else {
- n_g.h_width=n_g.h_advance=((double)(theFace->bbox.xMax-theFace->bbox.xMin))/((double)theFace->units_per_EM);
- }
- if ( FT_HAS_VERTICAL(theFace) ) {
- n_g.v_advance=((double)theFace->glyph->metrics.vertAdvance)/((double)theFace->units_per_EM);
- n_g.v_width=((double)theFace->glyph->metrics.height)/((double)theFace->units_per_EM);
- } else {
- n_g.v_width=n_g.v_advance=((double)theFace->height)/((double)theFace->units_per_EM);
- }
- if ( theFace->glyph->format == ft_glyph_format_outline ) {
- FT_Outline_Funcs ft2_outline_funcs = {
- ft2_move_to,
- ft2_line_to,
- ft2_conic_to,
- ft2_cubic_to,
- 0, 0
- };
- n_g.outline=new Path;
- ft2_to_liv tData;
- tData.theP=n_g.outline;
- tData.scale=1.0/((double)theFace->units_per_EM);
- tData.last=Geom::Point(0,0);
- FT_Outline_Decompose (&theFace->glyph->outline, &ft2_outline_funcs, &tData);
- }
- doAdd=true;
- }
+ if (FT_Load_Glyph (theFace, glyph_id, FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP)) {
+ // shit happened
+ } else {
+ if ( FT_HAS_HORIZONTAL(theFace) ) {
+ n_g.h_advance=((double)theFace->glyph->metrics.horiAdvance)/((double)theFace->units_per_EM);
+ n_g.h_width=((double)theFace->glyph->metrics.width)/((double)theFace->units_per_EM);
+ } else {
+ n_g.h_width=n_g.h_advance=((double)(theFace->bbox.xMax-theFace->bbox.xMin))/((double)theFace->units_per_EM);
+ }
+ if ( FT_HAS_VERTICAL(theFace) ) {
+ n_g.v_advance=((double)theFace->glyph->metrics.vertAdvance)/((double)theFace->units_per_EM);
+ n_g.v_width=((double)theFace->glyph->metrics.height)/((double)theFace->units_per_EM);
+ } else {
+ n_g.v_width=n_g.v_advance=((double)theFace->height)/((double)theFace->units_per_EM);
+ }
+ if ( theFace->glyph->format == ft_glyph_format_outline ) {
+ FT_Outline_Funcs ft2_outline_funcs = {
+ ft2_move_to,
+ ft2_line_to,
+ ft2_conic_to,
+ ft2_cubic_to,
+ 0, 0
+ };
+ n_g.outline=new Path;
+ ft2_to_liv tData;
+ tData.theP=n_g.outline;
+ tData.scale=1.0/((double)theFace->units_per_EM);
+ tData.last=Geom::Point(0,0);
+ FT_Outline_Decompose (&theFace->glyph->outline, &ft2_outline_funcs, &tData);
+ }
+ doAdd=true;
+ }
#endif
- if ( doAdd ) {
- if ( n_g.outline ) {
- n_g.outline->FastBBox(n_g.bbox[0],n_g.bbox[1],n_g.bbox[2],n_g.bbox[3]);
+ if ( doAdd ) {
+ if ( n_g.outline ) {
+ n_g.outline->FastBBox(n_g.bbox[0],n_g.bbox[1],n_g.bbox[2],n_g.bbox[3]);
n_g.pathvector=n_g.outline->MakePathVector();
- }
- glyphs[nbGlyph]=n_g;
- id_to_no[glyph_id]=nbGlyph;
- nbGlyph++;
- }
+ }
+ glyphs[nbGlyph]=n_g;
+ id_to_no[glyph_id]=nbGlyph;
+ nbGlyph++;
+ }
} else {
}
}
bool font_instance::FontMetrics(double &ascent,double &descent,double &leading)
{
- if ( pFont == NULL ) return false;
+ if ( pFont == NULL ) {
+ return false;
+ }
InitTheFace();
- if ( theFace == NULL ) return false;
+ if ( theFace == NULL ) {
+ return false;
+ }
#ifdef USE_PANGO_WIN32
OUTLINETEXTMETRIC otm;
- if ( !GetOutlineTextMetrics(daddy->hScreenDC,sizeof(otm),&otm) ) return false;
+ if ( !GetOutlineTextMetrics(daddy->hScreenDC,sizeof(otm),&otm) ) {
+ return false;
+ }
double scale=1.0/daddy->fontSize;
ascent=fabs(otm.otmAscent*scale);
descent=fabs(otm.otmDescent*scale);
leading=fabs(otm.otmLineGap*scale);
#else
- if ( theFace->units_per_EM == 0 ) return false; // bitmap font
- ascent=fabs(((double)theFace->ascender)/((double)theFace->units_per_EM));
- descent=fabs(((double)theFace->descender)/((double)theFace->units_per_EM));
- leading=fabs(((double)theFace->height)/((double)theFace->units_per_EM));
- leading-=ascent+descent;
+ if ( theFace->units_per_EM == 0 ) {
+ return false; // bitmap font
+ }
+ ascent=fabs(((double)theFace->ascender)/((double)theFace->units_per_EM));
+ descent=fabs(((double)theFace->descender)/((double)theFace->units_per_EM));
+ leading=fabs(((double)theFace->height)/((double)theFace->units_per_EM));
+ leading-=ascent+descent;
#endif
- return true;
+ return true;
}
bool font_instance::FontSlope(double &run, double &rise)
@@ -630,9 +679,13 @@ bool font_instance::FontSlope(double &run, double &rise)
run = 0.0;
rise = 1.0;
- if ( pFont == NULL ) return false;
+ if ( pFont == NULL ) {
+ return false;
+ }
InitTheFace();
- if ( theFace == NULL ) return false;
+ if ( theFace == NULL ) {
+ return false;
+ }
#ifdef USE_PANGO_WIN32
OUTLINETEXTMETRIC otm;
@@ -640,59 +693,63 @@ bool font_instance::FontSlope(double &run, double &rise)
run=otm.otmsCharSlopeRun;
rise=otm.otmsCharSlopeRise;
#else
- if ( !FT_IS_SCALABLE(theFace) ) return false; // bitmap font
+ if ( !FT_IS_SCALABLE(theFace) ) {
+ return false; // bitmap font
+ }
TT_HoriHeader *hhea = (TT_HoriHeader*)FT_Get_Sfnt_Table(theFace, ft_sfnt_hhea);
- if (hhea == NULL) return false;
+ if (hhea == NULL) {
+ return false;
+ }
run = hhea->caret_Slope_Run;
rise = hhea->caret_Slope_Rise;
#endif
- return true;
+ return true;
}
Geom::OptRect font_instance::BBox(int glyph_id)
{
- int no=-1;
- if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
- LoadGlyph(glyph_id);
- if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
- // didn't load
- } else {
- no=id_to_no[glyph_id];
- }
- } else {
- no=id_to_no[glyph_id];
- }
- if ( no < 0 ) {
- return Geom::OptRect();
+ int no = -1;
+ if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
+ LoadGlyph(glyph_id);
+ if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
+ // didn't load
} else {
- Geom::Point rmin(glyphs[no].bbox[0],glyphs[no].bbox[1]);
- Geom::Point rmax(glyphs[no].bbox[2],glyphs[no].bbox[3]);
- return Geom::Rect(rmin, rmax);
+ no = id_to_no[glyph_id];
}
+ } else {
+ no = id_to_no[glyph_id];
+ }
+ if ( no < 0 ) {
+ return Geom::OptRect();
+ } else {
+ Geom::Point rmin(glyphs[no].bbox[0],glyphs[no].bbox[1]);
+ Geom::Point rmax(glyphs[no].bbox[2],glyphs[no].bbox[3]);
+ return Geom::Rect(rmin, rmax);
+ }
}
Path* font_instance::Outline(int glyph_id,Path* copyInto)
{
- int no=-1;
- if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
- LoadGlyph(glyph_id);
- if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
- // didn't load
- } else {
- no=id_to_no[glyph_id];
- }
- } else {
- no=id_to_no[glyph_id];
- }
- if ( no < 0 ) return NULL;
- Path* src_o=glyphs[no].outline;
- if ( copyInto ) {
- copyInto->Reset();
- copyInto->Copy(src_o);
- return copyInto;
- }
- return src_o;
+ int no = -1;
+ if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
+ LoadGlyph(glyph_id);
+ if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
+ // didn't load
+ } else {
+ no = id_to_no[glyph_id];
+ }
+ } else {
+ no = id_to_no[glyph_id];
+ }
+ if ( no < 0 ) return NULL;
+ Path *src_o = glyphs[no].outline;
+ if ( copyInto ) {
+ copyInto->Reset();
+ copyInto->Copy(src_o);
+ return copyInto;
+ }
+ return src_o;
}
Geom::PathVector* font_instance::PathVector(int glyph_id)
@@ -714,70 +771,74 @@ Geom::PathVector* font_instance::PathVector(int glyph_id)
double font_instance::Advance(int glyph_id,bool vertical)
{
- int no=-1;
- if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
- LoadGlyph(glyph_id);
- if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
- // didn't load
- } else {
- no=id_to_no[glyph_id];
- }
- } else {
- no=id_to_no[glyph_id];
- }
- if ( no >= 0 ) {
- if ( vertical ) {
- return glyphs[no].v_advance;
- } else {
- return glyphs[no].h_advance;
- }
- }
- return 0;
+ int no = -1;
+ if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
+ LoadGlyph(glyph_id);
+ if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
+ // didn't load
+ } else {
+ no=id_to_no[glyph_id];
+ }
+ } else {
+ no = id_to_no[glyph_id];
+ }
+ if ( no >= 0 ) {
+ if ( vertical ) {
+ return glyphs[no].v_advance;
+ } else {
+ return glyphs[no].h_advance;
+ }
+ }
+ return 0;
}
raster_font* font_instance::RasterFont(const Geom::Matrix &trs, double stroke_width, bool vertical, JoinType stroke_join, ButtType stroke_cap, float /*miter_limit*/)
{
- font_style nStyle;
- nStyle.transform=trs;
- nStyle.vertical=vertical;
- nStyle.stroke_width=stroke_width;
- nStyle.stroke_cap=stroke_cap;
- nStyle.stroke_join=stroke_join;
- nStyle.nbDash=0;
- nStyle.dash_offset=0;
- nStyle.dashes=NULL;
- return RasterFont(nStyle);
+ font_style nStyle;
+ nStyle.transform=trs;
+ nStyle.vertical=vertical;
+ nStyle.stroke_width=stroke_width;
+ nStyle.stroke_cap=stroke_cap;
+ nStyle.stroke_join=stroke_join;
+ nStyle.nbDash=0;
+ nStyle.dash_offset=0;
+ nStyle.dashes=NULL;
+ return RasterFont(nStyle);
}
raster_font* font_instance::RasterFont(const font_style &inStyle)
{
- raster_font *res=NULL;
- double *savDashes=NULL;
- font_style nStyle=inStyle;
+ raster_font *res=NULL;
+ double *savDashes=NULL;
+ font_style nStyle=inStyle;
// for some evil reason font_style doesn't have a copy ctor, so the
// stuff that should be done there is done here instead (because the
// raster_font ctor copies nStyle).
- if ( nStyle.stroke_width > 0 && nStyle.nbDash > 0 && nStyle.dashes ) {
- savDashes=nStyle.dashes;
- nStyle.dashes=(double*)malloc(nStyle.nbDash*sizeof(double));
- memcpy(nStyle.dashes,savDashes,nStyle.nbDash*sizeof(double));
- }
- StyleMap& loadedStyles = *static_cast<StyleMap*>(loadedPtr);
- if ( loadedStyles.find(nStyle) == loadedStyles.end() ) {
- raster_font *nR = new raster_font(nStyle);
- nR->Ref();
- nR->daddy=this;
- loadedStyles[nStyle]=nR;
- res=nR;
- if ( res ) Ref();
- } else {
- res=loadedStyles[nStyle];
- res->Ref();
- if ( nStyle.dashes ) free(nStyle.dashes); // since they're not taken by a new rasterfont
- }
- nStyle.dashes=savDashes;
- return res;
+ if ( (nStyle.stroke_width > 0) && (nStyle.nbDash > 0) && nStyle.dashes ) {
+ savDashes=nStyle.dashes;
+ nStyle.dashes=(double*)malloc(nStyle.nbDash*sizeof(double));
+ memcpy(nStyle.dashes,savDashes,nStyle.nbDash*sizeof(double));
+ }
+ StyleMap& loadedStyles = *static_cast<StyleMap*>(loadedPtr);
+ if ( loadedStyles.find(nStyle) == loadedStyles.end() ) {
+ raster_font *nR = new raster_font(nStyle);
+ nR->Ref();
+ nR->daddy=this;
+ loadedStyles[nStyle]=nR;
+ res=nR;
+ if ( res ) {
+ Ref();
+ }
+ } else {
+ res=loadedStyles[nStyle];
+ res->Ref();
+ if ( nStyle.dashes ) {
+ free(nStyle.dashes); // since they're not taken by a new rasterfont
+ }
+ }
+ nStyle.dashes=savDashes;
+ return res;
}
void font_instance::RemoveRasterFont(raster_font* who)
diff --git a/src/libnrtype/Layout-TNG-Input.cpp b/src/libnrtype/Layout-TNG-Input.cpp
index fb2769edc..d16c6457d 100644
--- a/src/libnrtype/Layout-TNG-Input.cpp
+++ b/src/libnrtype/Layout-TNG-Input.cpp
@@ -19,6 +19,13 @@
#include "sp-string.h"
#include "FontFactory.h"
+#if !PANGO_VERSION_CHECK(1,24,0)
+#define PANGO_WEIGHT_THIN static_cast<PangoWeight>(100)
+#define PANGO_WEIGHT_BOOK static_cast<PangoWeight>(380)
+#define PANGO_WEIGHT_MEDIUM static_cast<PangoWeight>(500)
+#define PANGO_WEIGHT_ULTRAHEAVY static_cast<PangoWeight>(1000)
+#endif
+
namespace Inkscape {
namespace Text {
@@ -237,18 +244,16 @@ static const Layout::EnumConversionItem enum_convert_spstyle_style_to_pango_styl
{SP_CSS_FONT_STYLE_OBLIQUE, PANGO_STYLE_OBLIQUE}};
static const Layout::EnumConversionItem enum_convert_spstyle_weight_to_pango_weight[] = {
+ // NB: The Pango web page calls 500 "the normal font" but both CSS2 and the Pango
+ // enumeration define 400 as normal.
{SP_CSS_FONT_WEIGHT_NORMAL, PANGO_WEIGHT_NORMAL},
- {SP_CSS_FONT_WEIGHT_100, PANGO_WEIGHT_ULTRALIGHT},
+ {SP_CSS_FONT_WEIGHT_BOLD,PANGO_WEIGHT_BOLD},
+ {SP_CSS_FONT_WEIGHT_100, PANGO_WEIGHT_THIN},
{SP_CSS_FONT_WEIGHT_200, PANGO_WEIGHT_ULTRALIGHT},
{SP_CSS_FONT_WEIGHT_300, PANGO_WEIGHT_LIGHT},
{SP_CSS_FONT_WEIGHT_400, PANGO_WEIGHT_NORMAL},
-#if GTK_CHECK_VERSION(2,6,0)
- {SP_CSS_FONT_WEIGHT_500, PANGO_WEIGHT_SEMIBOLD},
-#else
- {SP_CSS_FONT_WEIGHT_500, PANGO_WEIGHT_NORMAL},
-#endif
- {SP_CSS_FONT_WEIGHT_600, PANGO_WEIGHT_BOLD},
- {SP_CSS_FONT_WEIGHT_BOLD,PANGO_WEIGHT_BOLD},
+ {SP_CSS_FONT_WEIGHT_500, PANGO_WEIGHT_MEDIUM},
+ {SP_CSS_FONT_WEIGHT_600, PANGO_WEIGHT_SEMIBOLD},
{SP_CSS_FONT_WEIGHT_700, PANGO_WEIGHT_BOLD},
{SP_CSS_FONT_WEIGHT_800, PANGO_WEIGHT_ULTRABOLD},
{SP_CSS_FONT_WEIGHT_900, PANGO_WEIGHT_HEAVY}};
diff --git a/src/libnrtype/Layout-TNG-Output.cpp b/src/libnrtype/Layout-TNG-Output.cpp
index d6b68ab40..f34b93d6e 100644
--- a/src/libnrtype/Layout-TNG-Output.cpp
+++ b/src/libnrtype/Layout-TNG-Output.cpp
@@ -24,6 +24,13 @@
#include "display/curve.h"
#include <2geom/pathvector.h>
+#if !PANGO_VERSION_CHECK(1,24,0)
+#define PANGO_WEIGHT_THIN static_cast<PangoWeight>(100)
+#define PANGO_WEIGHT_BOOK static_cast<PangoWeight>(380)
+#define PANGO_WEIGHT_MEDIUM static_cast<PangoWeight>(500)
+#define PANGO_WEIGHT_ULTRAHEAVY static_cast<PangoWeight>(1000)
+#endif
+
namespace Inkscape {
namespace Extension {
namespace Internal {
@@ -117,10 +124,10 @@ void Layout::getBoundingBox(NRRect *bounding_box, Geom::Matrix const &transform,
Geom::Matrix total_transform = glyph_matrix;
total_transform *= transform;
if(_glyphs[glyph_index].span(this).font) {
- Geom::OptRect glyph_rect = _glyphs[glyph_index].span(this).font->BBox(_glyphs[glyph_index].glyph);
+ Geom::OptRect glyph_rect = _glyphs[glyph_index].span(this).font->BBox(_glyphs[glyph_index].glyph);
if (glyph_rect) {
- Geom::Point bmi = glyph_rect->min(), bma = glyph_rect->max();
- Geom::Point tlp(bmi[0],bmi[1]), trp(bma[0],bmi[1]), blp(bmi[0],bma[1]), brp(bma[0],bma[1]);
+ Geom::Point bmi = glyph_rect->min(), bma = glyph_rect->max();
+ Geom::Point tlp(bmi[0],bmi[1]), trp(bma[0],bmi[1]), blp(bmi[0],bma[1]), brp(bma[0],bma[1]);
tlp *= total_transform;
trp *= total_transform;
blp *= total_transform;
@@ -133,7 +140,7 @@ void Layout::getBoundingBox(NRRect *bounding_box, Geom::Matrix const &transform,
if ( (glyph_rect->min())[1] < bounding_box->y0 ) bounding_box->y0=(glyph_rect->min())[1];
if ( (glyph_rect->max())[1] > bounding_box->y1 ) bounding_box->y1=(glyph_rect->max())[1];
}
- }
+ }
}
}
@@ -333,13 +340,17 @@ static char const *style_to_text(PangoStyle s)
static char const *weight_to_text(PangoWeight w)
{
switch (w) {
+ case PANGO_WEIGHT_THIN : return "thin";
case PANGO_WEIGHT_ULTRALIGHT: return "ultralight";
case PANGO_WEIGHT_LIGHT : return "light";
- case PANGO_WEIGHT_SEMIBOLD : return "semibold";
+ case PANGO_WEIGHT_BOOK : return "book";
case PANGO_WEIGHT_NORMAL : return "normalweight";
+ case PANGO_WEIGHT_MEDIUM : return "medium";
+ case PANGO_WEIGHT_SEMIBOLD : return "semibold";
case PANGO_WEIGHT_BOLD : return "bold";
case PANGO_WEIGHT_ULTRABOLD : return "ultrabold";
case PANGO_WEIGHT_HEAVY : return "heavy";
+ case PANGO_WEIGHT_ULTRAHEAVY: return "ultraheavy";
}
return "???";
}