diff options
| author | Ted Gould <ted@gould.cx> | 2010-05-15 18:08:17 +0000 |
|---|---|---|
| committer | Ted Gould <ted@gould.cx> | 2010-05-15 18:08:17 +0000 |
| commit | 2d8c2dfd832ce207aef3895e702bff4098ab7136 (patch) | |
| tree | 642a37c6e3ca05d5e991ffe868f03c9cc58e51bc /src/libnrtype | |
| parent | Merge from trunk (diff) | |
| parent | Minor tweaks to text toolbar. (diff) | |
| download | inkscape-2d8c2dfd832ce207aef3895e702bff4098ab7136.tar.gz inkscape-2d8c2dfd832ce207aef3895e702bff4098ab7136.zip | |
Updating to trunk
(bzr r8254.1.54)
Diffstat (limited to 'src/libnrtype')
| -rw-r--r-- | src/libnrtype/FontFactory.cpp | 242 | ||||
| -rw-r--r-- | src/libnrtype/FontFactory.h | 2 | ||||
| -rw-r--r-- | src/libnrtype/FontInstance.cpp | 801 | ||||
| -rw-r--r-- | src/libnrtype/Layout-TNG-Input.cpp | 21 | ||||
| -rw-r--r-- | src/libnrtype/Layout-TNG-Output.cpp | 21 |
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 "???"; } |
