diff options
| author | Arcadie M. Cracan <acracan@gmail.com> | 2009-12-27 11:31:36 +0000 |
|---|---|---|
| committer | Arcadie M. Cracan <acracan@gmail.com> | 2009-12-27 11:31:36 +0000 |
| commit | 30eaa4a74569f4fc5ee802ee3883201379c18235 (patch) | |
| tree | af9d0af2df52735f67a9f4af1a821f6d2fe2f242 /src/libnrtype | |
| parent | Connector tool: make connectors avoid the convex hull of shapes. (diff) | |
| parent | Warning cleanup (diff) | |
| download | inkscape-30eaa4a74569f4fc5ee802ee3883201379c18235.tar.gz inkscape-30eaa4a74569f4fc5ee802ee3883201379c18235.zip | |
Connector tool: make connectors avoid the convex hull of shapes.
(bzr r8857.1.2)
Diffstat (limited to 'src/libnrtype')
| -rw-r--r-- | src/libnrtype/FontFactory.cpp | 63 | ||||
| -rw-r--r-- | src/libnrtype/FontFactory.h | 21 | ||||
| -rw-r--r-- | src/libnrtype/FontInstance.cpp | 114 | ||||
| -rw-r--r-- | src/libnrtype/Layout-TNG-Input.cpp | 69 | ||||
| -rw-r--r-- | src/libnrtype/Layout-TNG-OutIter.cpp | 29 | ||||
| -rw-r--r-- | src/libnrtype/Layout-TNG.h | 6 | ||||
| -rw-r--r-- | src/libnrtype/font-instance.h | 58 |
7 files changed, 256 insertions, 104 deletions
diff --git a/src/libnrtype/FontFactory.cpp b/src/libnrtype/FontFactory.cpp index fec9316b9..1f85ee5ca 100644 --- a/src/libnrtype/FontFactory.cpp +++ b/src/libnrtype/FontFactory.cpp @@ -26,6 +26,10 @@ /* Freetype2 */ # include <pango/pangoft2.h> +#include <ext/hash_map> + + +typedef __gnu_cxx::hash_map<PangoFontDescription*, font_instance*, font_descr_hash, font_descr_equal> FaceMapType; // need to avoid using the size field size_t font_descr_hash::operator()( PangoFontDescription *const &x) const { @@ -299,20 +303,25 @@ font_factory *font_factory::Default(void) return lUsine; } -font_factory::font_factory(void) -{ - fontSize = 512; - nbEnt = 0; - maxEnt = 32; - ents = (font_entry*)g_malloc(maxEnt*sizeof(font_entry)); +font_factory::font_factory(void) : + nbEnt(0), + maxEnt(32), + ents(static_cast<font_entry*>(g_malloc(maxEnt*sizeof(font_entry)))), #ifdef USE_PANGO_WIN32 - hScreenDC = pango_win32_get_dc(); - fontServer = pango_win32_font_map_for_display(); - fontContext = pango_win32_get_context(); - pangoFontCache = pango_win32_font_map_get_font_cache(fontServer); + fontServer(pango_win32_font_map_for_display()), + fontContext(pango_win32_get_context()), + pangoFontCache(pango_win32_font_map_get_font_cache(fontServer)), + hScreenDC(pango_win32_get_dc()), +#else + fontServer(pango_ft2_font_map_new()), + fontContext(0), +#endif + fontSize(512), + loadedPtr(new FaceMapType()) +{ +#ifdef USE_PANGO_WIN32 #else - fontServer = pango_ft2_font_map_new(); pango_ft2_font_map_set_resolution((PangoFT2FontMap*)fontServer, 72, 72); fontContext = pango_ft2_font_map_create_context((PangoFT2FontMap*)fontServer); pango_ft2_font_map_set_default_substitute((PangoFT2FontMap*)fontServer,FactorySubstituteFunc,this,NULL); @@ -321,6 +330,11 @@ font_factory::font_factory(void) font_factory::~font_factory(void) { + if (loadedPtr) { + FaceMapType* tmp = static_cast<FaceMapType*>(loadedPtr); + loadedPtr = 0; + } + for (int i = 0;i < nbEnt;i++) ents[i].f->Unref(); if ( ents ) g_free(ents); @@ -793,6 +807,7 @@ font_instance *font_factory::Face(PangoFontDescription *descr, bool canFail) font_instance *res = NULL; + FaceMapType& loadedFaces = *static_cast<FaceMapType*>(loadedPtr); if ( loadedFaces.find(descr) == loadedFaces.end() ) { // not yet loaded PangoFont *nFace = NULL; @@ -849,8 +864,9 @@ font_instance *font_factory::Face(PangoFontDescription *descr, bool canFail) res->Ref(); AddInCache(res); } - if(res) - res->InitTheFace(); + if (res) { + res->InitTheFace(); + } return res; } @@ -924,15 +940,18 @@ font_instance *font_factory::Face(char const *family, NRTypePosDef apos) void font_factory::UnrefFace(font_instance *who) { - if ( who == NULL ) return; - if ( loadedFaces.find(who->descr) == loadedFaces.end() ) { - // not found - char *tc = pango_font_description_to_string(who->descr); - g_warning("unrefFace %p=%s: failed\n",who,tc); - g_free(tc); - } else { - loadedFaces.erase(loadedFaces.find(who->descr)); - // printf("unrefFace %p: success\n",who); + if ( who ) { + FaceMapType& loadedFaces = *static_cast<FaceMapType*>(loadedPtr); + + if ( loadedFaces.find(who->descr) == loadedFaces.end() ) { + // not found + char *tc = pango_font_description_to_string(who->descr); + g_warning("unrefFace %p=%s: failed\n",who,tc); + g_free(tc); + } else { + loadedFaces.erase(loadedFaces.find(who->descr)); + // printf("unrefFace %p: success\n",who); + } } } diff --git a/src/libnrtype/FontFactory.h b/src/libnrtype/FontFactory.h index 9f4b31a2e..8d85bcf3e 100644 --- a/src/libnrtype/FontFactory.h +++ b/src/libnrtype/FontFactory.h @@ -11,7 +11,6 @@ #include <functional> #include <algorithm> -#include <ext/hash_map> #ifdef HAVE_CONFIG_H # include <config.h> @@ -84,31 +83,29 @@ public: double fontSize; /**< The huge fontsize used as workaround for hinting. * Different between freetype and win32. */ - __gnu_cxx::hash_map<PangoFontDescription*, font_instance*, font_descr_hash, font_descr_equal> loadedFaces; - font_factory(); virtual ~font_factory(); /// Returns the default font_factory. static font_factory* Default(); - + /// Constructs a pango string for use with the fontStringMap (see below) Glib::ustring ConstructFontSpecification(PangoFontDescription *font); Glib::ustring ConstructFontSpecification(font_instance *font); - + /// Returns strings to be used in the UI for family and face (or "style" as the column is labeled) Glib::ustring GetUIFamilyString(PangoFontDescription const *fontDescr); Glib::ustring GetUIStyleString(PangoFontDescription const *fontDescr); - + /// Modifiers for the font specification (returns new font specification) Glib::ustring ReplaceFontSpecificationFamily(const Glib::ustring & fontSpec, const Glib::ustring & newFamily); Glib::ustring FontSpecificationSetItalic(const Glib::ustring & fontSpec, bool turnOn); Glib::ustring FontSpecificationSetBold(const Glib::ustring & fontSpec, bool turnOn); - + // Gathers all strings needed for UI while storing pango information in // fontInstanceMap and fontStringMap void GetUIFamiliesAndStyles(FamilyToStylesMap *map); - + /// Retrieve a font_instance from a style object, first trying to use the font-specification, the CSS information font_instance* FaceFromStyle(SPStyle const *style); @@ -129,17 +126,19 @@ public: // internal void AddInCache(font_instance *who); - + private: + void* loadedPtr; + // These two maps are used for translating between what's in the UI and a pango // font description. This is necessary because Pango cannot always // reproduce these structures from the names it gave us in the first place. - + // Key: A string produced by font_factory::ConstructFontSpecification // Value: The associated PangoFontDescription typedef std::map<Glib::ustring, PangoFontDescription *> PangoStringToDescrMap; PangoStringToDescrMap fontInstanceMap; - + // Key: Family name in UI + Style name in UI // Value: The associated string that should be produced with font_factory::ConstructFontSpecification typedef std::map<Glib::ustring, Glib::ustring> UIStringToPangoStringMap; diff --git a/src/libnrtype/FontInstance.cpp b/src/libnrtype/FontInstance.cpp index e1413b46e..f34a230c1 100644 --- a/src/libnrtype/FontInstance.cpp +++ b/src/libnrtype/FontInstance.cpp @@ -29,6 +29,22 @@ # include FT_TRUETYPE_TABLES_H # include <pango/pangoft2.h> +#include <ext/hash_map> + + +// the various raster_font in use at a given time are held in a hash_map whose indices are the +// styles, hence the 2 following 'classes' +struct font_style_hash : public std::unary_function<font_style, size_t> { + size_t operator()(font_style const &x) const; +}; + +struct font_style_equal : public std::binary_function<font_style, font_style, bool> { + bool operator()(font_style const &a, font_style const &b); +}; + + +typedef __gnu_cxx::hash_map<font_style, raster_font*, font_style_hash, font_style_equal> StyleMap; + size_t font_style_hash::operator()(const font_style &x) const { @@ -155,36 +171,61 @@ static int ft2_cubic_to(FREETYPE_VECTOR *control1, FREETYPE_VECTOR *control2, FR * */ -font_instance::font_instance(void) +font_instance::font_instance(void) : + pFont(0), + descr(0), + refCount(0), + daddy(0), + nbGlyph(0), + maxGlyph(0), + glyphs(0), + loadedPtr(new StyleMap()), + theFace(0) { - //printf("font instance born\n"); - descr=NULL; - pFont=NULL; - refCount=0; - daddy=NULL; - nbGlyph=maxGlyph=0; - glyphs=NULL; - theFace=NULL; + //printf("font instance born\n"); } font_instance::~font_instance(void) { - if ( daddy ) daddy->UnrefFace(this); - //printf("font instance death\n"); - if ( pFont ) g_object_unref(pFont); - pFont=NULL; - if ( descr ) pango_font_description_free(descr); - descr=NULL; - // if ( theFace ) FT_Done_Face(theFace); // owned by pFont. don't touch - theFace=NULL; - - for (int i=0;i<nbGlyph;i++) { - if ( glyphs[i].outline ) delete glyphs[i].outline; - if ( glyphs[i].pathvector ) delete glyphs[i].pathvector; - } - if ( glyphs ) free(glyphs); - nbGlyph=maxGlyph=0; - glyphs=NULL; + if ( loadedPtr ) { + StyleMap* tmp = static_cast<StyleMap*>(loadedPtr); + delete tmp; + loadedPtr = 0; + } + + if ( daddy ) { + daddy->UnrefFace(this); + daddy = 0; + } + + //printf("font instance death\n"); + if ( pFont ) { + g_object_unref(pFont); + pFont = 0; + } + + if ( descr ) { + pango_font_description_free(descr); + descr = 0; + } + + // if ( theFace ) FT_Done_Face(theFace); // owned by pFont. don't touch + theFace = 0; + + for (int i=0;i<nbGlyph;i++) { + if ( glyphs[i].outline ) { + delete glyphs[i].outline; + } + if ( glyphs[i].pathvector ) { + delete glyphs[i].pathvector; + } + } + if ( glyphs ) { + free(glyphs); + glyphs = 0; + } + nbGlyph = 0; + maxGlyph = 0; } void font_instance::Ref(void) @@ -728,7 +769,8 @@ raster_font* font_instance::RasterFont(const font_style &inStyle) nStyle.dashes=(double*)malloc(nStyle.nbDash*sizeof(double)); memcpy(nStyle.dashes,savDashes,nStyle.nbDash*sizeof(double)); } - if ( loadedStyles.find(nStyle) == loadedStyles.end() ) { + StyleMap& loadedStyles = *static_cast<StyleMap*>(loadedPtr); + if ( loadedStyles.find(nStyle) == loadedStyles.end() ) { raster_font *nR = new raster_font(nStyle); nR->Ref(); nR->daddy=this; @@ -746,15 +788,17 @@ raster_font* font_instance::RasterFont(const font_style &inStyle) void font_instance::RemoveRasterFont(raster_font* who) { - if ( who == NULL ) return; - if ( loadedStyles.find(who->style) == loadedStyles.end() ) { - //g_print("RemoveRasterFont failed \n"); - // not found - } else { - loadedStyles.erase(loadedStyles.find(who->style)); - //g_print("RemoveRasterFont\n"); - Unref(); - } + if ( who ) { + StyleMap& loadedStyles = *static_cast<StyleMap*>(loadedPtr); + if ( loadedStyles.find(who->style) == loadedStyles.end() ) { + //g_print("RemoveRasterFont failed \n"); + // not found + } else { + loadedStyles.erase(loadedStyles.find(who->style)); + //g_print("RemoveRasterFont\n"); + Unref(); + } + } } diff --git a/src/libnrtype/Layout-TNG-Input.cpp b/src/libnrtype/Layout-TNG-Input.cpp index 2ee0051a4..33371ab10 100644 --- a/src/libnrtype/Layout-TNG-Input.cpp +++ b/src/libnrtype/Layout-TNG-Input.cpp @@ -16,8 +16,11 @@ #include "style.h" #include "svg/svg-length.h" #include "sp-object.h" +#include "sp-string.h" #include "FontFactory.h" +#include "text-editing.h" // for inputTruncated() + namespace Inkscape { namespace Text { @@ -321,5 +324,71 @@ Layout::InputStreamTextSource::~InputStreamTextSource() sp_style_unref(style); } +bool +Layout::inputTruncated() const +{ + if (!inputExists()) + return false; + + // Find out the SPObject to which the last visible character corresponds: + Layout::iterator last = end(); + if (last == begin()) { + // FIXME: this returns a wrong "not truncated" when a flowtext is entirely + // truncated, so there are no visible characters. But how can I find out the + // originator SPObject without having anything to do getSourceOfCharacter + // from? + return false; + } + last.prevCharacter(); + void *source; + Glib::ustring::iterator offset; + getSourceOfCharacter(last, &source, &offset); + SPObject *obj = SP_OBJECT(source); + + // if that is SPString, see if it has further characters beyond the last visible + if (obj && SP_IS_STRING(obj)) { + Glib::ustring::iterator offset_next = offset; + offset_next ++; + if (offset_next != SP_STRING(obj)->string.end()) { + // truncated: source SPString has next char + return true; + } + } + + // otherwise, see if the SPObject at end() or any of its text-tree ancestors + // (excluding top-level SPText or SPFlowText) have a text-tree next sibling with + // visible text + if (obj) { + for (SPObject *ascend = obj; + ascend && (is_part_of_text_subtree (ascend) && !is_top_level_text_object(ascend)); + ascend = SP_OBJECT_PARENT(ascend)) { + if (SP_OBJECT_NEXT(ascend)) { + SPObject *next = SP_OBJECT_NEXT(ascend); + if (next && is_part_of_text_subtree(next) && has_visible_text(next)) { + // truncated: source text object has next text sibling + return true; + } + } + } + } + + // the above works for flowed text, but not for text on path. + // so now, we also check if the last of the _characters, if coming from a TEXT_SOURCE, + // has in_glyph different from -1 + unsigned last_char = _characters.size() - 1; + unsigned span_index = _characters[last_char].in_span; + Glib::ustring::const_iterator iter_char = _spans[span_index].input_stream_first_character; + + if (_input_stream[_spans[span_index].in_input_stream_item]->Type() == TEXT_SOURCE) { + if (_characters[last_char].in_glyph == -1) { + //truncated: last char has no glyph + return true; + } + } + + // not truncated + return false; +} + }//namespace Text }//namespace Inkscape diff --git a/src/libnrtype/Layout-TNG-OutIter.cpp b/src/libnrtype/Layout-TNG-OutIter.cpp index 0fc061bfc..f4e8e4031 100644 --- a/src/libnrtype/Layout-TNG-OutIter.cpp +++ b/src/libnrtype/Layout-TNG-OutIter.cpp @@ -221,6 +221,31 @@ Geom::Point Layout::characterAnchorPoint(iterator const &it) const } } +boost::optional<Geom::Point> Layout::baselineAnchorPoint() const +{ + iterator pos = this->begin(); + Geom::Point left_pt = this->characterAnchorPoint(pos); + pos.thisEndOfLine(); + Geom::Point right_pt = this->characterAnchorPoint(pos); + Geom::Point mid_pt = (left_pt + right_pt)/2; + + switch (this->paragraphAlignment(pos)) { + case LEFT: + case FULL: + return left_pt; + break; + case CENTER: + return mid_pt; + break; + case RIGHT: + return right_pt; + break; + default: + return boost::optional<Geom::Point>(); + break; + } +} + Geom::Point Layout::chunkAnchorPoint(iterator const &it) const { unsigned chunk_index; @@ -705,7 +730,7 @@ bool Layout::iterator::nextLineCursor(int n) unsigned line_index = _parent_layout->_characters[_char_index].chunk(_parent_layout).in_line; if (line_index == _parent_layout->_lines.size() - 1) return false; // nowhere to go - else + else n = MIN (n, static_cast<int>(_parent_layout->_lines.size() - 1 - line_index)); if (_parent_layout->_lines[line_index + n].in_shape != _parent_layout->_lines[line_index].in_shape) { // switching between shapes: adjust the stored x to compensate @@ -728,7 +753,7 @@ bool Layout::iterator::prevLineCursor(int n) line_index = _parent_layout->_characters[_char_index].chunk(_parent_layout).in_line; if (line_index == 0) return false; // nowhere to go - else + else n = MIN (n, static_cast<int>(line_index)); if (_parent_layout->_lines[line_index - n].in_shape != _parent_layout->_lines[line_index].in_shape) { // switching between shapes: adjust the stored x to compensate diff --git a/src/libnrtype/Layout-TNG.h b/src/libnrtype/Layout-TNG.h index 19680b140..05b5103fc 100644 --- a/src/libnrtype/Layout-TNG.h +++ b/src/libnrtype/Layout-TNG.h @@ -212,6 +212,8 @@ public: bool inputExists() const {return !_input_stream.empty();} + bool inputTruncated() const; + /** adds a new piece of text to the end of the current list of text to be processed. This method can only add text of a consistent style. To add lots of different styles, call it lots of times. @@ -480,6 +482,10 @@ public: /** For latin text, the left side of the character, on the baseline */ Geom::Point characterAnchorPoint(iterator const &it) const; + /** For left aligned text, the leftmost end of the baseline + For rightmost text, the rightmost... you probably got it by now ;-)*/ + boost::optional<Geom::Point> baselineAnchorPoint() const; + /** This is that value to apply to the x,y attributes of tspan role=line elements, and hence it takes alignment into account. */ Geom::Point chunkAnchorPoint(iterator const &it) const; diff --git a/src/libnrtype/font-instance.h b/src/libnrtype/font-instance.h index 4209a20af..521c9a424 100644 --- a/src/libnrtype/font-instance.h +++ b/src/libnrtype/font-instance.h @@ -1,7 +1,6 @@ #ifndef SEEN_LIBNRTYPE_FONT_INSTANCE_H #define SEEN_LIBNRTYPE_FONT_INSTANCE_H -#include <ext/hash_map> #include <map> #include <pango/pango-types.h> #include <pango/pango-font.h> @@ -16,33 +15,21 @@ #include <2geom/d2.h> // the font_instance are the template of several raster_font; they provide metrics and outlines -// that are drawn by the raster_font, so the raster_font needs info relative to the way the +// that are drawn by the raster_font, so the raster_font needs info relative to the way the // font need to be drawn. note that fontsize is a scale factor in the transform matrix // of the style -// the various raster_font in use at a given time are held in a hash_map whose indices are the -// styles, hence the 2 following 'classes' -struct font_style_hash : public std::unary_function<font_style, size_t> { - size_t operator()(font_style const &x) const; -}; - -struct font_style_equal : public std::binary_function<font_style, font_style, bool> { - bool operator()(font_style const &a, font_style const &b); -}; - class font_instance { public: - // hashmap to get the raster_font for a given style - __gnu_cxx::hash_map<font_style, raster_font*, font_style_hash, font_style_equal> loadedStyles; - // the real source of the font + // the real source of the font PangoFont* pFont; - // depending on the rendering backend, different temporary data + // depending on the rendering backend, different temporary data - // that's the font's fingerprint; this particular PangoFontDescription gives the entry at which this font_instance - // resides in the font_factory loadedFaces hash_map + // that's the font's fingerprint; this particular PangoFontDescription gives the entry at which this font_instance + // resides in the font_factory loadedFaces hash_map PangoFontDescription* descr; - // refcount + // refcount int refCount; - // font_factory owning this font_instance + // font_factory owning this font_instance font_factory* daddy; // common glyph definitions for all the rasterfonts @@ -58,38 +45,38 @@ public: bool IsOutlineFont(void); // utility void InstallFace(PangoFont* iFace); // utility; should reset the pFont field if loading failed - // in case the PangoFont is a bitmap font, for example. that way, the calling function - // will be able to check the validity of the font before installing it in loadedFaces + // in case the PangoFont is a bitmap font, for example. that way, the calling function + // will be able to check the validity of the font before installing it in loadedFaces void InitTheFace(); int MapUnicodeChar(gunichar c); // calls the relevant unicode->glyph index function void LoadGlyph(int glyph_id); // the main backend-dependent function - // loads the given glyph's info - - // nota: all coordinates returned by these functions are on a [0..1] scale; you need to multiply - // by the fontsize to get the real sizes + // loads the given glyph's info + + // nota: all coordinates returned by these functions are on a [0..1] scale; you need to multiply + // by the fontsize to get the real sizes Path* Outline(int glyph_id, Path *copyInto=NULL); - // queries the outline of the glyph (in livarot Path form), and copies it into copyInto instead - // of allocating a new Path if copyInto != NULL + // queries the outline of the glyph (in livarot Path form), and copies it into copyInto instead + // of allocating a new Path if copyInto != NULL Geom::PathVector* PathVector(int glyph_id); // returns the 2geom-type pathvector for this glyph. no refcounting needed, it's deallocated when the font_instance dies double Advance(int glyph_id, bool vertical); - // nominal advance of the font. + // nominal advance of the font. bool FontMetrics(double &ascent, double &descent, double &leading); bool FontSlope(double &run, double &rise); // for generating slanted cursors for oblique fonts Geom::OptRect BBox(int glyph_id); - // creates a rasterfont for the given style + // creates a rasterfont for the given style raster_font* RasterFont(Geom::Matrix const &trs, double stroke_width, bool vertical = false, JoinType stroke_join = join_straight, ButtType stroke_cap = butt_straight, float miter_limit = 4.0); - // the dashes array in iStyle is copied + // the dashes array in iStyle is copied raster_font* RasterFont(font_style const &iStyle); - // private use: tells the font_instance that the raster_font 'who' has died + // private use: tells the font_instance that the raster_font 'who' has died void RemoveRasterFont(raster_font *who); - // attribute queries + // attribute queries unsigned Name(gchar *str, unsigned size); unsigned PSName(gchar *str, unsigned size); unsigned Family(gchar *str, unsigned size); @@ -98,10 +85,13 @@ public: private: void FreeTheFace(); + // hashmap to get the raster_font for a given style + void* loadedPtr; // Pointer to a hash_map. Moved into .cpp to not expose use of __gnu_cxx extension. + #ifdef USE_PANGO_WIN32 HFONT theFace; #else - FT_Face theFace; + FT_Face theFace; // it's a pointer in fact; no worries to ref/unref it, pango does its magic // as long as pFont is valid, theFace is too #endif |
