X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Flibnrtype%2FLayout-TNG-Compute.cpp;h=2e65c2b24dd08f8cec2bd32466c58f85d8e3a6d6;hb=1e25a603bad48b0bb68458f31c1c6e551a466bd2;hp=ca16291d04bcbfd57bc08658f327fea2b231c341;hpb=47959af86ae7dff5618818339925b97f3bb7e1be;p=inkscape.git diff --git a/src/libnrtype/Layout-TNG-Compute.cpp b/src/libnrtype/Layout-TNG-Compute.cpp old mode 100755 new mode 100644 index ca16291d0..2e65c2b24 --- a/src/libnrtype/Layout-TNG-Compute.cpp +++ b/src/libnrtype/Layout-TNG-Compute.cpp @@ -19,9 +19,9 @@ namespace Inkscape { namespace Text { //#define IFTRACE(_code) _code -//#define TRACE(_args) g_print _args #define IFTRACE(_code) -#define TRACE(_args) + +#define TRACE(_args) IFTRACE(g_print _args) // ******* enum conversion tables static Layout::EnumConversionItem const enum_convert_spstyle_direction_to_pango_direction[] = { @@ -291,7 +291,7 @@ class Layout::Calculator do { PangoLogAttr const &char_attributes = _charAttributes(para, span->end); - if (char_attributes.is_mandatory_break) { + if (char_attributes.is_mandatory_break && span->end != span->start) { *last_emergency_break_span = *last_break_span = *span; TRACE(("span %d end of para; width = %f chars = %d\n", span->start.iter_span - para.unbroken_spans.begin(), span->width, char_count)); return false; @@ -475,9 +475,9 @@ class Layout::Calculator new_span.in_input_stream_item = unbroken_span.input_index; new_span.baseline_shift = _y_offset; new_span.block_progression = _block_progression; - if (_flow._input_stream[unbroken_span.input_index]->Type() == TEXT_SOURCE) { - new_span.font = para.pango_items[unbroken_span.pango_item_index].font; - new_span.font->Ref(); + if ((_flow._input_stream[unbroken_span.input_index]->Type() == TEXT_SOURCE) && (new_span.font = para.pango_items[unbroken_span.pango_item_index].font)) + { + new_span.font->Ref(); new_span.font_size = unbroken_span.font_size; new_span.direction = para.pango_items[unbroken_span.pango_item_index].item->analysis.level & 1 ? RIGHT_TO_LEFT : LEFT_TO_RIGHT; new_span.input_stream_first_character = Glib::ustring::const_iterator(unbroken_span.input_stream_first_character.base() + it_span->start.char_byte); @@ -562,7 +562,7 @@ class Layout::Calculator new_glyph.x = x + unbroken_span.glyph_string->glyphs[glyph_index].geometry.x_offset * font_size_multiplier; new_glyph.y = _y_offset + unbroken_span.glyph_string->glyphs[glyph_index].geometry.y_offset * font_size_multiplier; new_glyph.width = unbroken_span.glyph_string->glyphs[glyph_index].geometry.width * font_size_multiplier; - if (new_glyph.width == 0) + if ((new_glyph.width == 0) && (para.pango_items[unbroken_span.pango_item_index].font)) new_glyph.width = new_span.font_size * para.pango_items[unbroken_span.pango_item_index].font->Advance(unbroken_span.glyph_string->glyphs[glyph_index].glyph, false); // for some reason pango returns zero width for invalid glyph characters (those empty boxes), so go to freetype for the info } @@ -615,7 +615,6 @@ class Layout::Calculator iter_source_text++; char_index_in_unbroken_span++; char_byte = iter_source_text.base() - unbroken_span.input_stream_first_character.base(); - glyph_rotate = 0.0; } advance_width *= direction_sign; @@ -832,10 +831,10 @@ void Layout::Calculator::_buildPangoItemizationForPara(ParagraphInfo *para) cons } else if (_flow._input_stream[input_index]->Type() == TEXT_SOURCE) { Layout::InputStreamTextSource *text_source = static_cast(_flow._input_stream[input_index]); - // create the font_instance - font_instance *font = text_source->styleGetFontInstance(); - if (font == NULL) - continue; // bad news: we'll have to ignore all this text because we know of no font to render it + // create the font_instance + font_instance *font = text_source->styleGetFontInstance(); + if (font == NULL) + continue; // bad news: we'll have to ignore all this text because we know of no font to render it PangoAttribute *attribute_font_description = pango_attr_font_desc_new(font->descr); attribute_font_description->start_index = para_text.bytes(); @@ -903,7 +902,8 @@ void Layout::Calculator::_computeFontLineHeight(font_instance *font, double font line_height->setZero(); *line_height_multiplier = 1.0; } - font->FontMetrics(line_height->ascent, line_height->descent, line_height->leading); + else + font->FontMetrics(line_height->ascent, line_height->descent, line_height->leading); *line_height *= font_size; // yet another borked SPStyle member that we're going to have to fix ourselves @@ -929,7 +929,7 @@ void Layout::Calculator::_computeFontLineHeight(font_instance *font, double font } break; } - if (style->object->parent == NULL) break; + if (style->object == NULL || style->object->parent == NULL) break; style = style->object->parent->style; if (style == NULL) break; } @@ -1013,6 +1013,7 @@ unsigned Layout::Calculator::_buildSpansForPara(ParagraphInfo *para) const if (text_source->dy.size() > char_index_in_source) new_span.dx = text_source->dy[char_index_in_source]; } if (text_source->rotate.size() > char_index_in_source) new_span.rotate = text_source->rotate[char_index_in_source]; + else if (char_index_in_source == 0) new_span.rotate = 0.f; if (input_index == 0 && para->unbroken_spans.empty() && !new_span.y._set && _flow._input_wrap_shapes.empty()) { // if we don't set an explicit y some of the automatic wrapping code takes over and moves the text vertically // so that the top of the letters is at zero, not the baseline @@ -1040,10 +1041,6 @@ unsigned Layout::Calculator::_buildSpansForPara(ParagraphInfo *para) const // now we know the length, do some final calculations and add the UnbrokenSpan to the list new_span.font_size = text_source->styleComputeFontSize(); if (new_span.text_bytes) { - int const original_bidi_level = para->pango_items[pango_item_index].item->analysis.level; - para->pango_items[pango_item_index].item->analysis.level = 0; - // pango_shape() will reorder glyphs in rtl sections which messes us up because - // the svg spec requires us to draw glyphs in character order new_span.glyph_string = pango_glyph_string_new(); /* Some assertions intended to help diagnose bug #1277746. */ g_assert( 0 < new_span.text_bytes ); @@ -1055,7 +1052,32 @@ unsigned Layout::Calculator::_buildSpansForPara(ParagraphInfo *para) const new_span.text_bytes, ¶->pango_items[pango_item_index].item->analysis, new_span.glyph_string); - para->pango_items[pango_item_index].item->analysis.level = original_bidi_level; + + if (para->pango_items[pango_item_index].item->analysis.level & 1) { + // pango_shape() will reorder glyphs in rtl sections into visual order which messes + // us up because the svg spec requires us to draw glyphs in logical order + // let's reverse the glyphstring on a cluster-by-cluster basis + const unsigned nglyphs = new_span.glyph_string->num_glyphs; + std::vector infos(nglyphs); + std::vector clusters(nglyphs); + unsigned i, cluster_start = 0; + + for (i = 0 ; i < nglyphs ; ++i) { + if (new_span.glyph_string->glyphs[i].attr.is_cluster_start) { + if (i != cluster_start) { + std::copy(&new_span.glyph_string->glyphs[cluster_start], &new_span.glyph_string->glyphs[i], infos.end() - i); + std::copy(&new_span.glyph_string->log_clusters[cluster_start], &new_span.glyph_string->log_clusters[i], clusters.end() - i); + } + cluster_start = i; + } + } + if (i != cluster_start) { + std::copy(&new_span.glyph_string->glyphs[cluster_start], &new_span.glyph_string->glyphs[i], infos.end() - i); + std::copy(&new_span.glyph_string->log_clusters[cluster_start], &new_span.glyph_string->log_clusters[i], clusters.end() - i); + } + std::copy(infos.begin(), infos.end(), new_span.glyph_string->glyphs); + std::copy(clusters.begin(), clusters.end(), new_span.glyph_string->log_clusters); + } new_span.pango_item_index = pango_item_index; _computeFontLineHeight(para->pango_items[pango_item_index].font, new_span.font_size, text_source->style, &new_span.line_height, &new_span.line_height_multiplier); // TODO: metrics for vertical text @@ -1447,7 +1469,7 @@ bool Layout::Calculator::calculate() void Layout::_calculateCursorShapeForEmpty() { - _empty_cursor_shape.position = NR::Point(0, 0); + _empty_cursor_shape.position = Geom::Point(0, 0); _empty_cursor_shape.height = 0.0; _empty_cursor_shape.rotation = 0.0; if (_input_stream.empty() || _input_stream.front()->Type() != TEXT_SOURCE) @@ -1474,7 +1496,7 @@ void Layout::_calculateCursorShapeForEmpty() _empty_cursor_shape.rotation = caret_slope; if (_input_wrap_shapes.empty()) { - _empty_cursor_shape.position = NR::Point(text_source->x.empty() || !text_source->x.front()._set ? 0.0 : text_source->x.front().computed, + _empty_cursor_shape.position = Geom::Point(text_source->x.empty() || !text_source->x.front()._set ? 0.0 : text_source->x.front().computed, text_source->y.empty() || !text_source->y.front()._set ? 0.0 : text_source->y.front().computed); } else { Direction block_progression = text_source->styleGetBlockProgression(); @@ -1482,9 +1504,9 @@ void Layout::_calculateCursorShapeForEmpty() std::vector scan_runs = scanline_maker.makeScanline(line_height); if (!scan_runs.empty()) { if (block_progression == LEFT_TO_RIGHT || block_progression == RIGHT_TO_LEFT) - _empty_cursor_shape.position = NR::Point(scan_runs.front().y + font_size, scan_runs.front().x_start); + _empty_cursor_shape.position = Geom::Point(scan_runs.front().y + font_size, scan_runs.front().x_start); else - _empty_cursor_shape.position = NR::Point(scan_runs.front().x_start, scan_runs.front().y + font_size); + _empty_cursor_shape.position = Geom::Point(scan_runs.front().x_start, scan_runs.front().y + font_size); } } }