Code

NR::Maybe => boost::optional
[inkscape.git] / src / libnrtype / Layout-TNG-OutIter.cpp
old mode 100755 (executable)
new mode 100644 (file)
index 3dd043a..84307c9
@@ -201,7 +201,7 @@ Layout::iterator Layout::sourceToIterator(void *source_cookie) const
     return sourceToIterator(source_cookie, Glib::ustring::const_iterator(std::string::const_iterator(NULL)));
 }
 
-NR::Rect Layout::glyphBoundingBox(iterator const &it, double *rotation) const
+boost::optional<NR::Rect> Layout::glyphBoundingBox(iterator const &it, double *rotation) const
 {
    if (rotation) *rotation = _glyphs[it._glyph_index].rotation;
    return _glyphs[it._glyph_index].span(this).font->BBox(_glyphs[it._glyph_index].glyph);
@@ -264,14 +264,15 @@ NR::Rect Layout::characterBoundingBox(iterator const &it, double *rotation) cons
             NR::Point midpoint;
             NR::Point tangent;
             Span const &span = _characters[char_index].span(this);
-            double top = span.baseline_shift - span.line_height.ascent;
-            double bottom = span.baseline_shift + span.line_height.descent;
 
             const_cast<Path*>(_path_fitted)->PointAndTangentAt(midpoint_otp[0].piece, midpoint_otp[0].t, midpoint, tangent);
             top_left[NR::X] = midpoint[NR::X] - cluster_half_width;
-            top_left[NR::Y] = midpoint[NR::Y] + top;
+            top_left[NR::Y] = midpoint[NR::Y] - span.line_height.ascent;
             bottom_right[NR::X] = midpoint[NR::X] + cluster_half_width;
-            bottom_right[NR::Y] = midpoint[NR::Y] + bottom;
+            bottom_right[NR::Y] = midpoint[NR::Y] + span.line_height.descent;
+            NR::Point normal = tangent.cw();
+            top_left += span.baseline_shift * normal;
+            bottom_right += span.baseline_shift * normal;
             if (rotation)
                 *rotation = atan2(tangent[1], tangent[0]);
         }
@@ -692,25 +693,28 @@ void Layout::iterator::beginCursorUpDown()
     _cursor_moving_vertically = true;
 }
 
-bool Layout::iterator::nextLineCursor()
+bool Layout::iterator::nextLineCursor(int n)
 {
     if (!_cursor_moving_vertically)
         beginCursorUpDown();
     if (_char_index == _parent_layout->_characters.size())
         return false;
     unsigned line_index = _parent_layout->_characters[_char_index].chunk(_parent_layout).in_line;
-    if (line_index == _parent_layout->_lines.size() - 1) return false;
-    if (_parent_layout->_lines[line_index + 1].in_shape != _parent_layout->_lines[line_index].in_shape) {
+    if (line_index == _parent_layout->_lines.size() - 1) 
+        return false; // nowhere to go
+               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
-        _x_coordinate +=   _parent_layout->_chunks[_parent_layout->_spans[_parent_layout->_lineToSpan(line_index + 1)].in_chunk].left_x
+        _x_coordinate +=   _parent_layout->_chunks[_parent_layout->_spans[_parent_layout->_lineToSpan(line_index + n)].in_chunk].left_x
                          - _parent_layout->_chunks[_parent_layout->_spans[_parent_layout->_lineToSpan(line_index)].in_chunk].left_x;
     }
-    _char_index = _parent_layout->_cursorXOnLineToIterator(line_index + 1, _x_coordinate)._char_index;
+    _char_index = _parent_layout->_cursorXOnLineToIterator(line_index + n, _x_coordinate)._char_index;
     _glyph_index = _parent_layout->_characters[_char_index].in_glyph;
     return true;
 }
 
-bool Layout::iterator::prevLineCursor()
+bool Layout::iterator::prevLineCursor(int n)
 {
     if (!_cursor_moving_vertically)
         beginCursorUpDown();
@@ -719,13 +723,16 @@ bool Layout::iterator::prevLineCursor()
         line_index = _parent_layout->_lines.size() - 1;
     else
         line_index = _parent_layout->_characters[_char_index].chunk(_parent_layout).in_line;
-    if (line_index == 0) return false;
-    if (_parent_layout->_lines[line_index - 1].in_shape != _parent_layout->_lines[line_index].in_shape) {
+    if (line_index == 0) 
+        return false; // nowhere to go
+               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
-        _x_coordinate +=   _parent_layout->_chunks[_parent_layout->_spans[_parent_layout->_lineToSpan(line_index - 1)].in_chunk].left_x
+        _x_coordinate +=   _parent_layout->_chunks[_parent_layout->_spans[_parent_layout->_lineToSpan(line_index - n)].in_chunk].left_x
                          - _parent_layout->_chunks[_parent_layout->_spans[_parent_layout->_lineToSpan(line_index)].in_chunk].left_x;
     }
-    _char_index = _parent_layout->_cursorXOnLineToIterator(line_index - 1, _x_coordinate)._char_index;
+    _char_index = _parent_layout->_cursorXOnLineToIterator(line_index - n, _x_coordinate)._char_index;
     _glyph_index = _parent_layout->_characters[_char_index].in_glyph;
     return true;
 }
@@ -753,7 +760,7 @@ bool Layout::iterator::prevLineCursor()
         for ( ; ; ) {                                                                            \
             if (_char_index == 0) {                                                              \
                 _glyph_index = 0;                                                                \
-                return true;                                                                     \
+                return false;                                                                    \
             }                                                                                    \
             _char_index--;                                                                       \
             if (_parent_layout->_characters[_char_index].char_attributes.attr) break;            \
@@ -902,24 +909,24 @@ bool Layout::iterator::_cursorLeftOrRightLocalXByWord(Direction direction)
     return r;
 }
 
-bool Layout::iterator::cursorUp()
+bool Layout::iterator::cursorUp(int n)
 {
     Direction block_progression = _parent_layout->_blockProgression();
     if(block_progression == TOP_TO_BOTTOM)
-        return prevLineCursor();
+        return prevLineCursor(n);
     else if(block_progression == BOTTOM_TO_TOP)
-        return nextLineCursor();
+        return nextLineCursor(n);
     else
         return _cursorLeftOrRightLocalX(RIGHT_TO_LEFT);
 }
 
-bool Layout::iterator::cursorDown()
+bool Layout::iterator::cursorDown(int n)
 {
     Direction block_progression = _parent_layout->_blockProgression();
     if(block_progression == TOP_TO_BOTTOM)
-        return nextLineCursor();
+        return nextLineCursor(n);
     else if(block_progression == BOTTOM_TO_TOP)
-        return prevLineCursor();
+        return prevLineCursor(n);
     else
         return _cursorLeftOrRightLocalX(LEFT_TO_RIGHT);
 }