- Element & front = elements_.front();
- if (!(front.type == STRING
- && (elements_.size() == 1
- || (elements_.size() == 2
- && back().type == VIRTUAL))))
- return;
-
- // If this is a string element, we can try to split it.
- if (front.type != STRING)
- return;
- double xstr = w - x;
- // If there is a paragraph marker, it should be taken in account
- if (elements_.size() == 2)
- xstr -= back().width();
- pos_type new_pos = front.x2pos(xstr, true);
- front.str = front.str.substr(0, new_pos - pos_);
- front.dim.wid = xstr;
- front.endpos = new_pos;
- end_ = new_pos;
- dim_.wid = x + xstr;
- // If there is a paragraph marker, it should be removed.
- if (elements_.size() == 2)
- elements_.pop_back();
- return;
+ if (wid_brk <= w && brk.row_flags & CanBreakAfter) {
+ end_ = brk.endpos;
+ dim_.wid = wid_brk;
+ moveElements(elements_, cit_brk + 1, tail);
+ return tail;
+ }
+ // assume now that the current element is not there
+ wid_brk -= brk.dim.wid;
+ /* If the current element is an inset that allows breaking row
+ * before itself, and if the row is already short enough before
+ * this element, then cut right before it.
+ */
+ if (wid_brk <= w && brk.row_flags & CanBreakBefore && cit_brk != beg) {
+ end_ = (cit_brk -1)->endpos;
+ dim_.wid = wid_brk;
+ moveElements(elements_, cit_brk, tail);
+ return tail;
+ }
+ /* We have found a suitable separable element. This is the common case.
+ * Try to break it cleanly at a length that is both
+ * - less than the available space on the row
+ * - shorter than the natural width of the element, in order to enforce
+ * break-up.
+ */
+ if (brk.splitAt(min(w - wid_brk, brk.dim.wid - 2), next_width, false, tail)) {
+ /* if this element originally did not cause a row overflow
+ * in itself, and the remainder of the row would still be
+ * too large after breaking, then we will have issues in
+ * next row. Thus breaking does not help.
+ */
+ if (wid_brk + cit_brk->dim.wid < w
+ && dim_.wid - (wid_brk + brk.dim.wid) >= next_width) {
+ tail.clear();
+ break;
+ }
+ end_ = brk.endpos;
+ *cit_brk = brk;
+ dim_.wid = wid_brk + brk.dim.wid;
+ // If there are other elements, they should be removed.
+ moveElements(elements_, cit_brk + 1, tail);
+ return tail;
+ }
+ LATTEST(tail.empty());
+ }
+
+ if (cit != beg && cit->row_flags & NoBreakBefore) {
+ // It is not possible to separate this element from the
+ // previous one. (e.g. VIRTUAL)
+ --cit;
+ wid -= cit->dim.wid;
+ }
+
+ if (cit != beg) {
+ // There is no usable separator, but several elements have
+ // been added. We can cut right here.
+ end_ = cit->pos;
+ dim_.wid = wid;
+ moveElements(elements_, cit, tail);
+ return tail;