From 7a77adc9fc73f43544bc23f300d2abd382fda67c Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Wed, 1 Jun 2016 14:21:37 +0200 Subject: Use CSS 'strut' as minimum value of CSS line box height. (bzr r14935) --- src/libnrtype/Layout-TNG-Compute.cpp | 76 ++++++++++++++---------------------- src/libnrtype/Layout-TNG.h | 3 ++ 2 files changed, 32 insertions(+), 47 deletions(-) (limited to 'src/libnrtype') diff --git a/src/libnrtype/Layout-TNG-Compute.cpp b/src/libnrtype/Layout-TNG-Compute.cpp index 337d2a656..6b1aba53f 100644 --- a/src/libnrtype/Layout-TNG-Compute.cpp +++ b/src/libnrtype/Layout-TNG-Compute.cpp @@ -243,8 +243,11 @@ static void dumpUnbrokenSpans(ParagraphInfo *para){ bool _goToNextWrapShape(); - bool _findChunksForLine(ParagraphInfo const ¶, UnbrokenSpanPosition *start_span_pos, - std::vector *chunk_info, FontMetrics *line_box_height); + bool _findChunksForLine(ParagraphInfo const ¶, + UnbrokenSpanPosition *start_span_pos, + std::vector *chunk_info, + FontMetrics *line_box_height, + FontMetrics const *strut_height); static inline PangoLogAttr const &_charAttributes(ParagraphInfo const ¶, UnbrokenSpanPosition const &span_pos) @@ -1138,31 +1141,17 @@ void Layout::Calculator::_buildPangoItemizationForPara(ParagraphInfo *para) con */ double Layout::Calculator::_computeFontLineHeight( SPStyle const *style ) { - // yet another borked SPStyle member that we're going to have to fix ourselves - // We shouldn't need to climb the element tree... - for ( ; ; ) { - if (style->line_height.set && !style->line_height.inherit) { - if (style->line_height.normal) - break; - switch (style->line_height.unit) { - case SP_CSS_UNIT_NONE: - return style->line_height.computed; - case SP_CSS_UNIT_EX: - return style->line_height.value * 0.5; - // 0.5 is an approximation of the x-height. Fixme. - case SP_CSS_UNIT_EM: - case SP_CSS_UNIT_PERCENT: - return style->line_height.value; - default: // absolute values - return style->line_height.computed / style->font_size.computed; - } - break; - } - if (style->object == NULL || style->object->parent == NULL) break; - style = style->object->parent->style; - if (style == NULL) break; + // This is a bit backwards... we should be returning the absolute height + // but as the code expects line_height_multiplier we return that. + if (style->line_height.normal) { + return (LINE_HEIGHT_NORMAL); + } else if (style->line_height.unit == SP_CSS_UNIT_NONE) { + // Special case per CSS, computed value is multiplier + return style->line_height.computed; + } else { + // Normal case, computed value is absolute height. Turn it into multiplier. + return style->line_height.computed / style->font_size.computed; } - return (LINE_HEIGHT_NORMAL); } bool compareGlyphWidth(const PangoGlyphInfo &a, const PangoGlyphInfo &b) @@ -1449,35 +1438,25 @@ bool Layout::Calculator::_goToNextWrapShape() * line to #_flow. Returns with \a start_span_pos set to the end of the * text that was fitted, \a chunk_info completely filled out and * \a line_box_height set with the largest ascent and the largest - * descent (individually per CSS) on the line. The return + * descent (individually per CSS) on the line. The line_box_height + * can never be smaller than the line_box_strut (which is determined + * by the block level value of line_height). The return * value is false only if we've run out of shapes to wrap inside (and * hence couldn't create any chunks). */ bool Layout::Calculator::_findChunksForLine(ParagraphInfo const ¶, UnbrokenSpanPosition *start_span_pos, std::vector *chunk_info, - FontMetrics *line_box_height) + FontMetrics *line_box_height, + FontMetrics const *strut_height) { TRACE((" begin _findChunksForLine: chunks: %lu, em size: %f\n", chunk_info->size(), line_box_height->emSize() )); - // CSS 2.1 dictates that the minimum line height (i.e. the strut height) is found from the block element. This, - // however, is not what the browsers seem to be doing. Instead, find the height from the first text source. - InputStreamTextSource const *text_source = static_cast(_flow._input_stream.front()); - font_instance *font = text_source->styleGetFontInstance(); - if (font) { - double multiplier = _computeFontLineHeight(text_source->style); - line_box_height->set( font ); - *line_box_height *= text_source->style->font_size.computed; - font->Unref(); - line_box_height->computeEffective( multiplier ); - } else { - std::cerr << "Layout::Calculator::_findChunksForLine: Font not found." << std::endl; - } + // CSS 2.1 dictates that the minimum line height (i.e. the strut height) + // is found from the block element. + *line_box_height = *strut_height; TRACE((" initial line_box_height (em size): %f\n", line_box_height->emSize() )); - // Save strut height for use when recalculating line height after backing out chunks that don't fit. - FontMetrics strut_height = *line_box_height; - UnbrokenSpanPosition span_pos; for( ; ; ) { std::vector scan_runs; @@ -1495,7 +1474,7 @@ bool Layout::Calculator::_findChunksForLine(ParagraphInfo const ¶, unsigned scan_run_index; span_pos = *start_span_pos; for (scan_run_index = 0 ; scan_run_index < scan_runs.size() ; scan_run_index++) { - if (!_buildChunksInScanRun(para, span_pos, scan_runs[scan_run_index], chunk_info, line_box_height, &strut_height)) + if (!_buildChunksInScanRun(para, span_pos, scan_runs[scan_run_index], chunk_info, line_box_height, strut_height)) break; if (!chunk_info->empty() && !chunk_info->back().broken_spans.empty()) span_pos = chunk_info->back().broken_spans.back().end; @@ -1568,6 +1547,7 @@ bool Layout::Calculator::_buildChunksInScanRun(ParagraphInfo const ¶, // see if this span is too tall to fit on the current line FontMetrics new_span_height = new_span.start.iter_span->line_height; new_span_height.computeEffective( new_span.start.iter_span->line_height_multiplier ); + /* floating point 80-bit/64-bit rounding problems require epsilon. See discussion http://inkscape.gristle.org/2005-03-16.txt around 22:00 */ if ( new_span_height.ascent > line_height->ascent + std::numeric_limits::epsilon() || @@ -1705,11 +1685,13 @@ bool Layout::Calculator::calculate() pango_context_set_base_gravity(_pango_context, PANGO_GRAVITY_AUTO); } + // Minimum line box height determined by block container. + FontMetrics strut_height = _flow.strut; _y_offset = 0.0; _createFirstScanlineMaker(); ParagraphInfo para; - FontMetrics line_box_height; // needs to be maintained across paragraphs to be able to deal with blank paras + FontMetrics line_box_height; // Current value of line box height for line. for(para.first_input_index = 0 ; para.first_input_index < _flow._input_stream.size() ; ) { // jump to the next wrap shape if this is a SHAPE_BREAK control code if (_flow._input_stream[para.first_input_index]->Type() == CONTROL_CODE) { @@ -1749,7 +1731,7 @@ bool Layout::Calculator::calculate() do { // for each line in the paragraph TRACE(("begin line\n")); std::vector line_chunk_info; - if (!_findChunksForLine(para, &span_pos, &line_chunk_info, &line_box_height)) + if (!_findChunksForLine(para, &span_pos, &line_chunk_info, &line_box_height, &strut_height )) break; // out of shapes to wrap in to _outputLine(para, line_box_height, line_chunk_info); diff --git a/src/libnrtype/Layout-TNG.h b/src/libnrtype/Layout-TNG.h index 97a05bde8..8b46758f0 100644 --- a/src/libnrtype/Layout-TNG.h +++ b/src/libnrtype/Layout-TNG.h @@ -671,6 +671,9 @@ public: }; // End FontMetrics + /** The strut is the minimum value used in calculating line height. */ + FontMetrics strut; + /// see _enum_converter() struct EnumConversionItem { int input, output; -- cgit v1.2.3 From d1947e768272c703674129d5c583204ff2b59251 Mon Sep 17 00:00:00 2001 From: Adrian Boguszewski Date: Wed, 13 Jul 2016 13:36:19 +0200 Subject: Second part of new SPObject children list (bzr r14954.1.19) --- src/libnrtype/font-lister.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/libnrtype') diff --git a/src/libnrtype/font-lister.cpp b/src/libnrtype/font-lister.cpp index 568a7c8cc..937d67895 100644 --- a/src/libnrtype/font-lister.cpp +++ b/src/libnrtype/font-lister.cpp @@ -298,8 +298,8 @@ void FontLister::update_font_list_recursive(SPObject *r, std::listpush_back(Glib::ustring(font_family)); } - for (SPObject *child = r->firstChild(); child; child = child->getNext()) { - update_font_list_recursive(child, l); + for (auto& child: r->_children) { + update_font_list_recursive(&child, l); } } -- cgit v1.2.3 From 24d3f50003ca3cec6a03a7f5267cc4fe5588c69f Mon Sep 17 00:00:00 2001 From: Adrian Boguszewski Date: Thu, 14 Jul 2016 13:17:21 +0200 Subject: Renamed children list in SPObject (bzr r14954.1.21) --- src/libnrtype/font-lister.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libnrtype') diff --git a/src/libnrtype/font-lister.cpp b/src/libnrtype/font-lister.cpp index 937d67895..4deae821a 100644 --- a/src/libnrtype/font-lister.cpp +++ b/src/libnrtype/font-lister.cpp @@ -298,7 +298,7 @@ void FontLister::update_font_list_recursive(SPObject *r, std::listpush_back(Glib::ustring(font_family)); } - for (auto& child: r->_children) { + for (auto& child: r->children) { update_font_list_recursive(&child, l); } } -- cgit v1.2.3 From e471a664f923f517b68071f2e33fbb6ce070f8b7 Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Mon, 8 Aug 2016 13:56:40 +0100 Subject: Remove deprecated Autotools and btool files. Please use CMake instead (bzr r15046) --- src/libnrtype/Makefile_insert | 28 ---------------------------- 1 file changed, 28 deletions(-) delete mode 100644 src/libnrtype/Makefile_insert (limited to 'src/libnrtype') diff --git a/src/libnrtype/Makefile_insert b/src/libnrtype/Makefile_insert deleted file mode 100644 index ab9465daa..000000000 --- a/src/libnrtype/Makefile_insert +++ /dev/null @@ -1,28 +0,0 @@ -## Makefile.am fragment sourced by src/Makefile.am. - -ink_common_sources += \ - libnrtype/boundary-type.h \ - libnrtype/font-glyph.h \ - libnrtype/font-instance.h \ - libnrtype/font-style.h \ - libnrtype/nr-type-primitives.cpp \ - libnrtype/nr-type-primitives.h \ - libnrtype/FontFactory.cpp \ - libnrtype/FontFactory.h \ - libnrtype/FontInstance.cpp \ - libnrtype/font-lister.h \ - libnrtype/font-lister.cpp \ - libnrtype/one-box.h \ - libnrtype/one-glyph.h \ - libnrtype/one-para.h \ - libnrtype/text-boundary.h \ - libnrtype/TextWrapper.cpp \ - libnrtype/TextWrapper.h \ - libnrtype/Layout-TNG-Compute.cpp \ - libnrtype/Layout-TNG-Input.cpp \ - libnrtype/Layout-TNG-OutIter.cpp \ - libnrtype/Layout-TNG-Output.cpp \ - libnrtype/Layout-TNG-Scanline-Maker.h \ - libnrtype/Layout-TNG-Scanline-Makers.cpp \ - libnrtype/Layout-TNG.cpp \ - libnrtype/Layout-TNG.h -- cgit v1.2.3 From 7f779f28e67eac1653e0f7751bb3f224b67894c7 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Mon, 15 Aug 2016 22:55:21 +0200 Subject: Fix a bunch of errors as reported at http://www.viva64.com/en/b/0419/ (bzr r15059) --- src/libnrtype/FontFactory.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/libnrtype') diff --git a/src/libnrtype/FontFactory.cpp b/src/libnrtype/FontFactory.cpp index 65eb62dda..35d584840 100644 --- a/src/libnrtype/FontFactory.cpp +++ b/src/libnrtype/FontFactory.cpp @@ -702,8 +702,8 @@ font_instance *font_factory::Face(PangoFontDescription *descr, bool canFail) PangoOTTag* features = pango_ot_info_list_features( info, PANGO_OT_TABLE_GSUB, 0, i, j ); - if( features[0] != 0 ) - // std::cout << " features: " << std::endl; + // if( features[0] != 0 ) + // std::cout << " features: " << std::endl; for( unsigned k = 0; features[k] != 0; ++k ) { // dump_tag( &features[k], " feature: "); -- cgit v1.2.3 From 5b4f5eea12a4ee758114c3b18d95962bd87b4a19 Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Tue, 30 Aug 2016 12:38:29 +0100 Subject: Use HarfBuzz instead of deprecated Pango OT Fixed bugs: - https://launchpad.net/bugs/1488159 (bzr r15094) --- src/libnrtype/FontFactory.cpp | 125 ++++++++++++++++++++---------------------- 1 file changed, 58 insertions(+), 67 deletions(-) (limited to 'src/libnrtype') diff --git a/src/libnrtype/FontFactory.cpp b/src/libnrtype/FontFactory.cpp index 35d584840..1fbdce036 100644 --- a/src/libnrtype/FontFactory.cpp +++ b/src/libnrtype/FontFactory.cpp @@ -24,6 +24,9 @@ #include "util/unordered-containers.h" #include +#include +#include + typedef INK_UNORDERED_MAP FaceMapType; // need to avoid using the size field @@ -99,7 +102,6 @@ font_factory::font_factory(void) : fontSize(512), loadedPtr(new FaceMapType()) { - // std::cout << pango_version_string() << std::endl; #ifdef USE_PANGO_WIN32 #else pango_ft2_font_map_set_resolution(PANGO_FT2_FONT_MAP(fontServer), @@ -593,13 +595,15 @@ font_instance* font_factory::FaceFromFontSpecification(char const *fontSpecifica return font; } -void dump_tag( guint32 *tag, Glib::ustring prefix = "" ) { +void dump_tag( guint32 *tag, Glib::ustring prefix = "", bool lf=true ) { std::cout << prefix << ((char)((*tag & 0xff000000)>>24)) << ((char)((*tag & 0x00ff0000)>>16)) << ((char)((*tag & 0x0000ff00)>>8)) - << ((char)((*tag & 0x000000ff)>>0)) - << std::endl; + << ((char)((*tag & 0x000000ff)>>0)); + if( lf ) { + std::cout << std::endl; + } } Glib::ustring extract_tag( guint32 *tag ) { @@ -677,74 +681,61 @@ font_instance *font_factory::Face(PangoFontDescription *descr, bool canFail) } // Extract which OpenType tables are in the font. We'll make a list of all tables - // regardless of which script and langauge they are in. These functions are deprecated but - // will eventually be replaced by newer functions (according to Behdad). - PangoOTInfo* info = pango_ot_info_get( res->theFace ); - - PangoOTTag* scripts = pango_ot_info_list_scripts( info, PANGO_OT_TABLE_GSUB ); - // std::cout << " scripts: " << std::endl; - for( unsigned i = 0; scripts[i] != 0; ++i ) { - // dump_tag( &scripts[i], " " ); - - guint script_index = -1; - if( pango_ot_info_find_script( info, PANGO_OT_TABLE_GSUB, scripts[i], &script_index )) { - - PangoOTTag* languages = - pango_ot_info_list_languages( info, PANGO_OT_TABLE_GSUB, script_index, NULL); - // if( languages[0] != 0 ) - // std::cout << " languages: " << std::endl; - - for( unsigned j = 0; languages[j] != 0; ++j ) { - // dump_tag( &languages[j], " lang: "); - - guint language_index = -1; - if( pango_ot_info_find_language(info, PANGO_OT_TABLE_GSUB, script_index, languages[j], &language_index, NULL)) { - - PangoOTTag* features = - pango_ot_info_list_features( info, PANGO_OT_TABLE_GSUB, 0, i, j ); - // if( features[0] != 0 ) - // std::cout << " features: " << std::endl; - - for( unsigned k = 0; features[k] != 0; ++k ) { - // dump_tag( &features[k], " feature: "); - ++(res->openTypeTables[ extract_tag(&features[k])]); - } - g_free( features ); - } else { - // std::cout << " No languages defined" << std::endl; - PangoOTTag* features = - pango_ot_info_list_features( info, PANGO_OT_TABLE_GSUB, 0, i, PANGO_OT_DEFAULT_LANGUAGE ); - // if( features[0] != 0 ) - // std::cout << " default features: " << std::endl; - - for( unsigned k = 0; features[k] != 0; ++k ) { - // dump_tag( &features[k], " feature: " ); - ++(res->openTypeTables[ extract_tag(&features[k])]); - } - g_free( features ); + // regardless of which script and langauge they are in. This Harfbuzz code replaces + // an earlier Pango version as the Pango functions are deprecated. + + // Empty map... bitmap fonts seem to be loaded multiple times. + res->openTypeTables.clear(); + + auto const hb_face = hb_ft_face_create(res->theFace, NULL); + + // First time to get size of array + auto script_count = hb_ot_layout_table_get_script_tags(hb_face, HB_OT_TAG_GSUB, 0, NULL, NULL); + auto const scripts_hb = g_new(hb_tag_t, script_count + 1); + + // Second time to fill array (this two step process was not necessary with Pango). + hb_ot_layout_table_get_script_tags(hb_face, HB_OT_TAG_GSUB, 0, &script_count, scripts_hb); + + for(unsigned int i = 0; i < script_count; ++i) { + auto language_count = hb_ot_layout_script_get_language_tags(hb_face, HB_OT_TAG_GSUB, i, 0, NULL, NULL); + + if(language_count > 0) { + auto const languages_hb = g_new(hb_tag_t, language_count + 1); + hb_ot_layout_script_get_language_tags(hb_face, HB_OT_TAG_GSUB, i, 0, &language_count, languages_hb); + + for(unsigned int j = 0; j < language_count; ++j) { + auto feature_count = hb_ot_layout_language_get_feature_tags(hb_face, HB_OT_TAG_GSUB, i, j, 0, NULL, NULL); + auto const features_hb = g_new(hb_tag_t, feature_count + 1); + hb_ot_layout_language_get_feature_tags(hb_face, HB_OT_TAG_GSUB, i, j, 0, &feature_count, features_hb); + + for(unsigned int k = 0; k < feature_count; ++k) { + ++(res->openTypeTables[ extract_tag(&features_hb[k])]); } + + g_free(features_hb); } - g_free( languages ); - } else { - // std::cout << " No scripts defined! " << std::endl; + + g_free(languages_hb); + } + else { + // Even if no languages are present there is still the default. + auto feature_count = hb_ot_layout_language_get_feature_tags(hb_face, HB_OT_TAG_GSUB, i, + HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX, + 0, NULL, NULL); + auto const features_hb = g_new(hb_tag_t, feature_count + 1); + hb_ot_layout_language_get_feature_tags(hb_face, HB_OT_TAG_GSUB, i, + HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX, + 0, &feature_count, features_hb); + + for(unsigned int k = 0; k < feature_count; ++k) { + ++(res->openTypeTables[ extract_tag(&features_hb[k])]); + } + + g_free(features_hb); } } - g_free( scripts ); - - PangoOTTag* features = - pango_ot_info_list_features( info, PANGO_OT_TABLE_GSUB, 0, 0, PANGO_OT_DEFAULT_LANGUAGE ); - // if( features[0] != 0 ) - // std::cout << " DFTL DFTL features: " << std::endl; - for( unsigned i = 0; features[i] != 0; ++i ) { - // dump_tag( &features[i], " feature: " ); - ++(res->openTypeTables[ extract_tag(&features[i])]); - } - // std::map::iterator it; - // for( it = res->openTypeTables.begin(); it != res->openTypeTables.end(); ++it) { - // std::cout << "Table: " << it->first << " Occurances: " << it->second << std::endl; - // } - g_free( features ); + g_free(scripts_hb); } else { // already here res = loadedFaces[descr]; -- cgit v1.2.3 From 0fb25eebd29911c6b0c3515f0cdc86a8dde373a6 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Thu, 1 Sep 2016 14:02:12 +0200 Subject: Fix font style handling for non-system fonts. Gets rid of some Pango-CRITICAL and Gtk_CRITICAL warnings. (bzr r15097) --- src/libnrtype/FontFactory.cpp | 6 ++++++ src/libnrtype/font-lister.cpp | 14 ++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) (limited to 'src/libnrtype') diff --git a/src/libnrtype/FontFactory.cpp b/src/libnrtype/FontFactory.cpp index 1fbdce036..6865e923e 100644 --- a/src/libnrtype/FontFactory.cpp +++ b/src/libnrtype/FontFactory.cpp @@ -295,6 +295,7 @@ void font_factory::GetUIFamilies(std::vector& out) const char* displayName = pango_font_family_get_name(families[currentFamily]); if (displayName == 0 || *displayName == '\0') { + std::cerr << "font_factory::GetUIFamilies: Missing displayName! " << std::endl; continue; } sorted.push_back(std::make_pair(families[currentFamily], displayName)); @@ -313,6 +314,10 @@ GList* font_factory::GetUIStyles(PangoFontFamily * in) // Gather the styles for this family PangoFontFace** faces = NULL; int numFaces = 0; + if (in == NULL) { + std::cerr << "font_factory::GetUIStyles(): PangoFontFamily is NULL" << std::endl; + return ret; + } pango_font_family_list_faces(in, &faces, &numFaces); for (int currentFace = 0; currentFace < numFaces; currentFace++) { @@ -322,6 +327,7 @@ GList* font_factory::GetUIStyles(PangoFontFamily * in) const gchar* displayName = pango_font_face_get_face_name(faces[currentFace]); // std::cout << "Display Name: " << displayName << std::endl; if (displayName == NULL || *displayName == '\0') { + std::cerr << "font_factory::GetUIStyles: Missing displayName! " << std::endl; continue; } diff --git a/src/libnrtype/font-lister.cpp b/src/libnrtype/font-lister.cpp index 4deae821a..48fcf2a22 100644 --- a/src/libnrtype/font-lister.cpp +++ b/src/libnrtype/font-lister.cpp @@ -135,6 +135,8 @@ void FontLister::ensureRowStyles(GtkTreeModel* model, GtkTreeIter const* iterato if (!row[FontList.styles]) { if (row[FontList.pango_family]) { row[FontList.styles] = font_factory::Default()->GetUIStyles(row[FontList.pango_family]); + } else { + row[FontList.styles] = default_styles; } } } @@ -177,6 +179,7 @@ void FontLister::insert_font_family(Glib::ustring new_family) (*treeModelIter)[FontList.family] = new_family; (*treeModelIter)[FontList.styles] = styles; (*treeModelIter)[FontList.onSystem] = false; + (*treeModelIter)[FontList.pango_family] = NULL; } void FontLister::update_font_list(SPDocument *document) @@ -256,7 +259,8 @@ void FontLister::update_font_list(SPDocument *document) Gtk::TreeModel::iterator treeModelIter = font_list_store->prepend(); (*treeModelIter)[FontList.family] = reinterpret_cast(g_strdup((*i).c_str())); (*treeModelIter)[FontList.styles] = styles; - (*treeModelIter)[FontList.onSystem] = false; + (*treeModelIter)[FontList.onSystem] = false; // false if document font + (*treeModelIter)[FontList.pango_family] = NULL; // CHECK ME (set to pango_family if on system?) } @@ -993,7 +997,7 @@ Glib::ustring FontLister::get_best_style_match(Glib::ustring family, Glib::ustri } catch (...) { - //std::cout << " ERROR: can't find family: " << family << std::endl; + std::cerr << "FontLister::get_best_style_match(): can't find family: " << family << std::endl; return (target_style); } @@ -1002,10 +1006,12 @@ Glib::ustring FontLister::get_best_style_match(Glib::ustring family, Glib::ustri //font_description_dump( target ); - if (!row[FontList.styles]) { + GList *styles = default_styles; + if (row[FontList.onSystem] && !row[FontList.styles]) { row[FontList.styles] = font_factory::Default()->GetUIStyles(row[FontList.pango_family]); + styles = row[FontList.styles]; } - GList *styles = row[FontList.styles]; + for (GList *l = styles; l; l = l->next) { Glib::ustring fontspec = family + ", " + ((StyleNames *)l->data)->CssName; PangoFontDescription *candidate = pango_font_description_from_string(fontspec.c_str()); -- cgit v1.2.3 From e458092523bd1e5d77aa8a6675f17b6b0cfe1114 Mon Sep 17 00:00:00 2001 From: Martin Owens Date: Thu, 29 Sep 2016 23:08:37 -0400 Subject: Remove the reset on the glyph tangent, it breaks text on path (bug lp:1627523) Fixed bugs: - https://launchpad.net/bugs/1627523 (bzr r15139) --- src/libnrtype/Layout-TNG-Output.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/libnrtype') diff --git a/src/libnrtype/Layout-TNG-Output.cpp b/src/libnrtype/Layout-TNG-Output.cpp index 526319f35..df7adf5b4 100644 --- a/src/libnrtype/Layout-TNG-Output.cpp +++ b/src/libnrtype/Layout-TNG-Output.cpp @@ -742,8 +742,6 @@ void Layout::fitToPathAlign(SVGLength const &startOffset, Path const &path) if (endpoint != startpoint) { tangent = endpoint - startpoint; tangent.normalize(); - } else { - tangent = Geom::Point (0,0); } } g_free(end_otp); -- cgit v1.2.3 From d19b21f387be9c5516d020679e97d077d8df8242 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Sat, 24 Dec 2016 16:41:34 +0100 Subject: Line space properly blank lines that have their own styling (i.e. empty tspan). (bzr r15352) --- src/libnrtype/Layout-TNG-Compute.cpp | 30 +++++++++++++++++++++++++++--- src/libnrtype/Layout-TNG-Output.cpp | 17 +++++++++++++++++ src/libnrtype/Layout-TNG.h | 8 ++++++-- 3 files changed, 50 insertions(+), 5 deletions(-) (limited to 'src/libnrtype') diff --git a/src/libnrtype/Layout-TNG-Compute.cpp b/src/libnrtype/Layout-TNG-Compute.cpp index 6b1aba53f..e6da9ba63 100644 --- a/src/libnrtype/Layout-TNG-Compute.cpp +++ b/src/libnrtype/Layout-TNG-Compute.cpp @@ -1182,10 +1182,34 @@ unsigned Layout::Calculator::_buildSpansForPara(ParagraphInfo *para) const for(input_index = para->first_input_index ; input_index < _flow._input_stream.size() ; input_index++) { if (_flow._input_stream[input_index]->Type() == CONTROL_CODE) { Layout::InputStreamControlCode const *control_code = static_cast(_flow._input_stream[input_index]); + if ( control_code->code == SHAPE_BREAK - || control_code->code == PARAGRAPH_BREAK) + || control_code->code == PARAGRAPH_BREAK) { + + // Add span to be used to calculate line spacing of blank lines. + UnbrokenSpan new_span; + new_span.pango_item_index = -1; + new_span.input_index = input_index; + + // No pango object, so find font and line height ourselves. + SPObject * object = static_cast(control_code->source_cookie); + if (object) { + SPStyle * style = object->style; + if (style) { + new_span.font_size = style->font_size.computed * _flow.getTextLengthMultiplierDue(); + font_factory * factory = font_factory::Default(); + font_instance * font = factory->FaceFromStyle( style ); + new_span.line_height_multiplier = _computeFontLineHeight( object->style ); + new_span.line_height.set( font ); + new_span.line_height *= new_span.font_size; + } + } + new_span.text_bytes = 0; + new_span.char_index_in_para = char_index_in_para; + para->unbroken_spans.push_back(new_span); + TRACE(("add empty span for break %lu\n", para->unbroken_spans.size() - 1)); break; // stop at the end of the paragraph - else if (control_code->code == ARBITRARY_GAP) { + } else if (control_code->code == ARBITRARY_GAP) { UnbrokenSpan new_span; new_span.pango_item_index = -1; new_span.input_index = input_index; @@ -1619,8 +1643,8 @@ bool Layout::Calculator::_buildChunksInScanRun(ParagraphInfo const ¶, *line_height = *strut_height; for (std::vector::const_iterator it_chunk = chunk_info->begin() ; it_chunk != chunk_info->end() ; it_chunk++) { for (std::vector::const_iterator it_span = it_chunk->broken_spans.begin() ; it_span != it_chunk->broken_spans.end() ; it_span++) { - TRACE((" brokenspan line_height: %f\n", it_span->start.iter_span->line_height.emSize() )); FontMetrics span_height = it_span->start.iter_span->line_height; + TRACE((" brokenspan line_height: %f\n", span_height.emSize() )); span_height.computeEffective( it_span->start.iter_span->line_height_multiplier ); line_height->max( span_height ); } diff --git a/src/libnrtype/Layout-TNG-Output.cpp b/src/libnrtype/Layout-TNG-Output.cpp index df7adf5b4..a1a19f2b3 100644 --- a/src/libnrtype/Layout-TNG-Output.cpp +++ b/src/libnrtype/Layout-TNG-Output.cpp @@ -867,6 +867,23 @@ double Layout::getActualLength() const }//namespace Text }//namespace Inkscape +std::ostream &operator<<(std::ostream &out, const Inkscape::Text::Layout::FontMetrics &f) { + out << " emSize: " << f.emSize() + << " ascent: " << f.ascent + << " descent: " << f.descent + << " xheight: " << f.xheight; + return out; +} + +std::ostream &operator<<(std::ostream &out, const Inkscape::Text::Layout::FontMetrics *f) { + out << " emSize: " << f->emSize() + << " ascent: " << f->ascent + << " descent: " << f->descent + << " xheight: " << f->xheight; + return out; +} + + /* Local Variables: diff --git a/src/libnrtype/Layout-TNG.h b/src/libnrtype/Layout-TNG.h index 8b46758f0..e06b8392f 100644 --- a/src/libnrtype/Layout-TNG.h +++ b/src/libnrtype/Layout-TNG.h @@ -629,7 +629,7 @@ public: void reset() { ascent = 0.8; - descent = -0.2; + descent = 0.2; xheight = 0.5; ascent_max = 0.8; descent_max = 0.2; @@ -664,7 +664,7 @@ public: // private: double ascent; // Typographic ascent. - double descent; // Typographic descent. + double descent; // Typographic descent. (Normally positive). double xheight; // Height of 'x' measured from alphabetic baseline. double ascent_max; // Maximum ascent of all glyphs in font. double descent_max; // Maximum descent of all glyphs in font. @@ -1189,6 +1189,10 @@ inline bool Layout::iterator::prevCharacter() }//namespace Text }//namespace Inkscape +std::ostream &operator<<(std::ostream &out, const Inkscape::Text::Layout::FontMetrics &f); +std::ostream &operator<<(std::ostream &out, const Inkscape::Text::Layout::FontMetrics *f); + + #endif -- cgit v1.2.3 From 2bf5058630b43a23e2a735a6b69487214c7d3f95 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Wed, 25 Jan 2017 19:50:23 +0100 Subject: Fix disappearing text when outer line-height is zero. (bzr r15452) --- src/libnrtype/Layout-TNG-Scanline-Makers.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libnrtype') diff --git a/src/libnrtype/Layout-TNG-Scanline-Makers.cpp b/src/libnrtype/Layout-TNG-Scanline-Makers.cpp index 0d6112d19..a57aaa3e4 100644 --- a/src/libnrtype/Layout-TNG-Scanline-Makers.cpp +++ b/src/libnrtype/Layout-TNG-Scanline-Makers.cpp @@ -124,7 +124,7 @@ std::vector Layout::ShapeScanlineMaker::makeScan FloatLigne line_rasterization; FloatLigne line_decent_length_runs; float line_text_height = (float)(line_height.emSize()); - if (line_text_height == 0.0) + if (line_text_height < 0.001) line_text_height = 0.001; // Scan() doesn't work for zero height so this will have to do _current_line_height = (float)line_height.emSize(); -- cgit v1.2.3 From 9bd36f8f6615ea7daa54fbd9b7b7f378f17787df Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Thu, 26 Jan 2017 09:53:02 +0100 Subject: Add font name to debugging output. (bzr r15454) --- src/libnrtype/Layout-TNG-Compute.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/libnrtype') diff --git a/src/libnrtype/Layout-TNG-Compute.cpp b/src/libnrtype/Layout-TNG-Compute.cpp index e6da9ba63..80541c228 100644 --- a/src/libnrtype/Layout-TNG-Compute.cpp +++ b/src/libnrtype/Layout-TNG-Compute.cpp @@ -210,6 +210,7 @@ class Layout::Calculator */ static void dumpPangoItemsOut(ParagraphInfo *para){ std::cout << "Pango items: " << para->pango_items.size() << std::endl; + font_factory * factory = font_factory::Default(); for(unsigned pidx = 0 ; pidx < para->pango_items.size(); pidx++){ std::cout << "idx: " << pidx @@ -217,6 +218,8 @@ static void dumpPangoItemsOut(ParagraphInfo *para){ << para->pango_items[pidx].item->offset << " length: " << para->pango_items[pidx].item->length + << " font: " + << factory->ConstructFontSpecification( para->pango_items[pidx].font ) << std::endl; } } -- cgit v1.2.3 From f5682fa438f1cc4ab7f8d6d76e72b3c7f8d07cbc Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Tue, 31 Jan 2017 13:40:20 +0100 Subject: Prevent infinite loop when line-height is zero and text does not fit on line. (bzr r15460) --- src/libnrtype/Layout-TNG-Compute.cpp | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) (limited to 'src/libnrtype') diff --git a/src/libnrtype/Layout-TNG-Compute.cpp b/src/libnrtype/Layout-TNG-Compute.cpp index 80541c228..8e173a7c7 100644 --- a/src/libnrtype/Layout-TNG-Compute.cpp +++ b/src/libnrtype/Layout-TNG-Compute.cpp @@ -1486,11 +1486,18 @@ bool Layout::Calculator::_findChunksForLine(ParagraphInfo const ¶, UnbrokenSpanPosition span_pos; for( ; ; ) { + + // Get regions where one can place one line of text (can be more than one, if filling a + // donut for example). std::vector scan_runs; scan_runs = _scanline_maker->makeScanline(*line_box_height); // Only one line with "InfiniteScanlineMaker + + // If scan_runs is empty, we must have reached the bottom of a shape. Go to next shape. while (scan_runs.empty()) { // Only used by ShapeScanlineMaker if (!_goToNextWrapShape()) return false; // no more shapes to wrap in to + + *line_box_height = *strut_height; scan_runs = _scanline_maker->makeScanline(*line_box_height); } @@ -1501,13 +1508,21 @@ bool Layout::Calculator::_findChunksForLine(ParagraphInfo const ¶, unsigned scan_run_index; span_pos = *start_span_pos; for (scan_run_index = 0 ; scan_run_index < scan_runs.size() ; scan_run_index++) { - if (!_buildChunksInScanRun(para, span_pos, scan_runs[scan_run_index], chunk_info, line_box_height, strut_height)) + + // Returns false if some text in line requires a taller line_box_height. + // (We try again with a larger line_box_height.) + if (!_buildChunksInScanRun(para, span_pos, scan_runs[scan_run_index], chunk_info, line_box_height, strut_height)) { break; + } + if (!chunk_info->empty() && !chunk_info->back().broken_spans.empty()) span_pos = chunk_info->back().broken_spans.back().end; } + if (scan_run_index == scan_runs.size()) break; // ie when buildChunksInScanRun() succeeded - } + + } // End for loop + *start_span_pos = span_pos; TRACE((" final line_box_height: %f\n", line_box_height->emSize() )); TRACE((" end _findChunksForLine: chunks: %lu\n", chunk_info->size())); @@ -1581,6 +1596,8 @@ bool Layout::Calculator::_buildChunksInScanRun(ParagraphInfo const ¶, new_span_height.descent > line_height->descent + std::numeric_limits::epsilon() ) { // Take larger of each of the two ascents and two descents per CSS line_height->max(new_span_height); + + // Currently always true for flowed text and false for Inkscape multiline text. if (!_scanline_maker->canExtendCurrentScanline(*line_height)) { return false; } @@ -1755,12 +1772,20 @@ bool Layout::Calculator::calculate() span_pos.char_byte = 0; span_pos.char_index = 0; + bool keep_going = true; do { // for each line in the paragraph TRACE(("begin line\n")); + std::vector line_chunk_info; - if (!_findChunksForLine(para, &span_pos, &line_chunk_info, &line_box_height, &strut_height )) + if (!_findChunksForLine(para, &span_pos, &line_chunk_info, &line_box_height, &strut_height )) { + keep_going = false; break; // out of shapes to wrap in to + } + if (line_box_height.emSize() < 0.001 && line_chunk_info.empty()) { + keep_going = false; + break; // No room for text and not useful to try again at same place. + } _outputLine(para, line_box_height, line_chunk_info); _scanline_maker->setLineHeight( line_box_height ); _scanline_maker->completeLine(); // Increments y by line height @@ -1768,7 +1793,7 @@ bool Layout::Calculator::calculate() } while (span_pos.iter_span != para.unbroken_spans.end()); TRACE(("para %lu end\n\n", _flow._paragraphs.size() - 1)); - if (_scanline_maker != NULL) { + if (keep_going) { bool is_empty_para = _flow._characters.empty() || _flow._characters.back().line(&_flow).in_paragraph != _flow._paragraphs.size() - 1; if ((is_empty_para && para_end_input_index + 1 >= _flow._input_stream.size()) || para_end_input_index + 1 < _flow._input_stream.size()) { -- cgit v1.2.3 From 7a73a9ce1d5f8cc1a6d970ea8f093773f4ddd9db Mon Sep 17 00:00:00 2001 From: sian-ht Date: Fri, 24 Feb 2017 10:17:48 +0100 Subject: [Bug #1464987] --export-latex crashes with a svg file. Fixed bugs: - https://launchpad.net/bugs/1464987 (bzr r15544) --- src/libnrtype/Layout-TNG.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/libnrtype') diff --git a/src/libnrtype/Layout-TNG.h b/src/libnrtype/Layout-TNG.h index e06b8392f..c39315106 100644 --- a/src/libnrtype/Layout-TNG.h +++ b/src/libnrtype/Layout-TNG.h @@ -194,7 +194,7 @@ public: /** For expressing paragraph alignment. These values are rotated in the case of vertical text, but are not dependent on whether the paragraph is rtl or ltr, thus LEFT is always either left or top. */ - enum Alignment {LEFT, CENTER, RIGHT, FULL}; + enum Alignment {LEFT, CENTER, RIGHT, FULL, NONE}; /** The CSS spec allows line-height:normal to be whatever the user agent thinks will look good. This is our value, as a multiple of font-size. */ @@ -1144,7 +1144,7 @@ inline unsigned Layout::paragraphIndex(iterator const &it) const {return it._char_index == _characters.size() ? _paragraphs.size() - 1 : _characters[it._char_index].line(this).in_paragraph;} inline Layout::Alignment Layout::paragraphAlignment(iterator const &it) const - {return _paragraphs[paragraphIndex(it)].alignment;} + {return (_paragraphs.size() == 0) ? NONE : _paragraphs[paragraphIndex(it)].alignment;} inline bool Layout::iterator::nextGlyph() { -- cgit v1.2.3 From fedd7b75fa6002dbd170d54a3d26042e086c9264 Mon Sep 17 00:00:00 2001 From: Eduard Braun Date: Thu, 11 May 2017 00:22:53 +0200 Subject: Fix crash with fonts containing illegal characters in family name. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the problem at hand [1] the crash is caused by a font with the name "Æ Systematic -BRK-". However the font family name returned by pango is "\xc6 Systematic - BRK-". "(\xc6" is the character code of "Æ" in Latin-1 encoding, but is not a valid UTF-8 character, so obviously at some point there went something wrong with character encoding conversion) At this time it is unclear to me where in the chain the issue originates, as it's possible that a) the font name is already stored incorrectly in the font file b) fontconfig incorrectly parses the font file when creating the font cache c) pango messes up somehow For now we ignore fonts with illegal characters in file name as they cause a whole lot of issues (even before triggering a crash), but figuring out the above and (if applicable) work around it in Inkscape might make the font available after all. [1] https://answers.launchpad.net/inkscape/+question/630886 (bzr r15687) --- src/libnrtype/FontFactory.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/libnrtype') diff --git a/src/libnrtype/FontFactory.cpp b/src/libnrtype/FontFactory.cpp index 6865e923e..770616ae7 100644 --- a/src/libnrtype/FontFactory.cpp +++ b/src/libnrtype/FontFactory.cpp @@ -298,6 +298,12 @@ void font_factory::GetUIFamilies(std::vector& out) std::cerr << "font_factory::GetUIFamilies: Missing displayName! " << std::endl; continue; } + if (!g_utf8_validate(displayName, -1, 0)) { + // TODO: can can do anything about this or does it always indicate broken fonts that should not be used? + std::cerr << "font_factory::GetUIFamilies: Illegal characters in displayName. "; + std::cerr << "Ignoring font '" << displayName << "'" << std::endl; + continue; + } sorted.push_back(std::make_pair(families[currentFamily], displayName)); } -- cgit v1.2.3