Code

Removed duplication of menu items.
[inkscape.git] / src / libnrtype / Layout-TNG-Compute.cpp
old mode 100755 (executable)
new mode 100644 (file)
index ca16291..2e65c2b
@@ -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<Layout::InputStreamTextSource *>(_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,
                                 &para->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<PangoGlyphInfo> infos(nglyphs);
+                        std::vector<gint> 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<ScanlineMaker::ScanRun> 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);
         }
     }
 }