3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
9 * Full author contact details are available in file CREDITS
16 #include "frontends/Painter.h"
17 #include "frontends/screen.h"
18 #include "frontends/font_metrics.h"
19 #include "support/LAssert.h"
20 #include "paragraph.h"
21 #include "support/textutils.h"
23 #include "insets/insettext.h"
24 #include "ParagraphParameters.h"
25 #include "BufferView.h"
32 #include "rowpainter.h"
34 #include "lyxrow_funcs.h"
39 extern int PAPER_MARGIN;
40 extern int CHANGEBAR_MARGIN;
41 extern int LEFT_MARGIN;
45 // "temporary". We'll never get to use more
46 // references until we start adding hacks like
47 // these until other places catch up.
48 BufferView * perv(BufferView const & bv)
50 return const_cast<BufferView *>(&bv);
56 RowPainter::RowPainter(BufferView const & bv,
57 LyXText const & text, RowList::iterator rit)
58 : bv_(bv), pain_(bv_.painter()), text_(text), row_(rit), pit_(rit->par())
63 LyXFont const RowPainter::getFont(pos_type pos) const
65 return text_.getFont(bv_.buffer(), pit_, pos);
69 int RowPainter::singleWidth(lyx::pos_type pos) const
71 return text_.singleWidth(pit_, pos);
75 int RowPainter::singleWidth(lyx::pos_type pos, char c) const
77 return text_.singleWidth(pit_, pos, c);
81 LyXFont const RowPainter::getLabelFont() const
83 return text_.getLabelFont(bv_.buffer(), &*pit_);
87 char const RowPainter::transformChar(char c, lyx::pos_type pos) const
89 return text_.transformChar(c, *pit_, pos);
93 int RowPainter::leftMargin() const
95 return text_.leftMargin(*row_);
99 void RowPainter::paintInset(pos_type const pos)
101 Inset * inset = const_cast<Inset*>(pit_->getInset(pos));
105 LyXFont const & font = getFont(pos);
107 #warning inset->update FIXME
108 inset->update(perv(bv_), false);
110 inset->draw(perv(bv_), font, yo_ + row_->baseline(), x_);
114 void RowPainter::paintHebrewComposeChar(pos_type & vpos)
116 pos_type pos = text_.vis2log(vpos);
121 char c = pit_->getChar(pos);
125 LyXFont const & font = getFont(pos);
126 int const width = font_metrics::width(c, font);
129 for (pos_type i = pos - 1; i >= 0; --i) {
130 c = pit_->getChar(i);
131 if (!Encodings::IsComposeChar_hebrew(c)) {
132 if (IsPrintableNonspace(c)) {
136 dx = (c == 'ø' || c == 'ã')
138 : (width2 - width) / 2;
145 pain_.text(int(x_) + dx, yo_ + row_->baseline(), str, font);
149 void RowPainter::paintArabicComposeChar(pos_type & vpos)
151 pos_type pos = text_.vis2log(vpos);
155 char c = pit_->getChar(pos);
156 c = transformChar(c, pos);
160 LyXFont const & font = getFont(pos);
161 int const width = font_metrics::width(c, font);
164 for (pos_type i = pos - 1; i >= 0; --i) {
165 c = pit_->getChar(i);
166 if (!Encodings::IsComposeChar_arabic(c)) {
167 if (IsPrintableNonspace(c)) {
170 dx = (width2 - width) / 2;
176 pain_.text(int(x_) + dx, yo_ + row_->baseline(), str, font);
180 void RowPainter::paintChars(pos_type & vpos, bool hebrew, bool arabic)
182 pos_type pos = text_.vis2log(vpos);
183 pos_type const last = lastPrintablePos(text_, row_);
184 LyXFont orig_font(getFont(pos));
188 str += pit_->getChar(pos);
190 unsigned char c = str[0];
191 str[0] = transformChar(c, pos);
194 bool prev_struckout(isDeletedText(*pit_, pos));
195 bool prev_newtext(isInsertedText(*pit_, pos));
199 // collect as much similar chars as we can
200 while (vpos <= last && (pos = text_.vis2log(vpos)) >= 0) {
201 char c = pit_->getChar(pos);
203 if (!IsPrintableNonspace(c))
206 if (prev_struckout != isDeletedText(*pit_, pos))
209 if (prev_newtext != isInsertedText(*pit_, pos))
212 if (arabic && Encodings::IsComposeChar_arabic(c))
214 if (hebrew && Encodings::IsComposeChar_hebrew(c))
217 if (orig_font != getFont(pos))
221 c = transformChar(c, pos);
226 if (prev_struckout) {
227 orig_font.setColor(LColor::strikeout);
228 } else if (prev_newtext) {
229 orig_font.setColor(LColor::newtext);
232 // Draw text and set the new x position
233 pain_.text(int(x_), yo_ + row_->baseline(), str, orig_font);
234 x_ += font_metrics::width(str, orig_font);
238 void RowPainter::paintForeignMark(float const orig_x, LyXFont const & orig_font)
240 if (!lyxrc.mark_foreign_language)
242 if (orig_font.language() == latex_language)
244 if (orig_font.language() == bv_.buffer()->params.language)
247 int const y = yo_ + row_->baseline() + 1;
248 pain_.line(int(orig_x), y, int(x_), y, LColor::language);
252 void RowPainter::paintFromPos(pos_type & vpos)
254 pos_type const pos = text_.vis2log(vpos);
256 LyXFont const & orig_font = getFont(pos);
258 float const orig_x = x_;
260 char const c = pit_->getChar(pos);
262 if (IsInsetChar(c)) {
265 paintForeignMark(orig_x, orig_font);
269 // usual characters, no insets
271 // special case languages
272 bool const hebrew = (orig_font.language()->lang() == "hebrew");
274 orig_font.language()->lang() == "arabic" &&
275 (lyxrc.font_norm_type == LyXRC::ISO_8859_6_8 ||
276 lyxrc.font_norm_type == LyXRC::ISO_10646_1);
278 // draw as many chars as we can
279 if ((!hebrew && !arabic)
280 || (hebrew && !Encodings::IsComposeChar_hebrew(c))
281 || (arabic && !Encodings::IsComposeChar_arabic(c))) {
282 paintChars(vpos, hebrew, arabic);
284 paintHebrewComposeChar(vpos);
286 paintArabicComposeChar(vpos);
289 paintForeignMark(orig_x, orig_font);
295 void RowPainter::paintBackground()
298 int const y = yo_ < 0 ? 0 : yo_;
299 int const h = yo_ < 0 ? row_->height() + yo_ : row_->height();
300 pain_.fillRectangle(x, y, width_, h, text_.backgroundColor());
304 void RowPainter::paintSelection()
306 bool const is_rtl = pit_->isRightToLeftPar(bv_.buffer()->params);
308 // the current selection
309 int const startx = text_.selection.start.x();
310 int const endx = text_.selection.end.x();
311 int const starty = text_.selection.start.y();
312 int const endy = text_.selection.end.y();
313 RowList::iterator startrow = text_.selection.start.row();
314 RowList::iterator endrow = text_.selection.end.row();
316 if (text_.bidi_same_direction) {
320 int h = row_->height();
322 if (startrow == row_ && endrow == row_) {
326 pain_.fillRectangle(x, y, w, h, LColor::selection);
330 pain_.fillRectangle(x, y, w, h, LColor::selection);
332 } else if (startrow == row_) {
333 int const x = (is_rtl) ? xo_ : (xo_ + startx);
334 int const w = (is_rtl) ? startx : (width_ - startx);
335 pain_.fillRectangle(x, y, w, h, LColor::selection);
336 } else if (endrow == row_) {
337 int const x = (is_rtl) ? (xo_ + endx) : xo_;
338 int const w = (is_rtl) ? (width_ - endx) : endx;
339 pain_.fillRectangle(x, y, w, h, LColor::selection);
340 } else if (y_ > starty && y_ < endy) {
341 pain_.fillRectangle(xo_, y, width_, h, LColor::selection);
344 } else if (startrow != row_ && endrow != row_) {
345 if (y_ > starty && y_ < endy) {
347 int h = row_->height();
348 pain_.fillRectangle(xo_, yo_, w, h, LColor::selection);
353 if ((startrow != row_ && !is_rtl) || (endrow != row_ && is_rtl))
354 pain_.fillRectangle(xo_, yo_, int(x_), row_->height(), LColor::selection);
356 pos_type const body_pos = pit_->beginningOfBody();
357 pos_type const last = lastPrintablePos(text_, row_);
360 for (pos_type vpos = row_->pos(); vpos <= last; ++vpos) {
361 pos_type pos = text_.vis2log(vpos);
362 float const old_tmpx = tmpx;
363 if (body_pos > 0 && pos == body_pos - 1) {
364 LyXLayout_ptr const & layout = pit_->layout();
365 LyXFont const lfont = getLabelFont();
367 tmpx += label_hfill_ + font_metrics::width(layout->labelsep, lfont);
369 if (pit_->isLineSeparator(body_pos - 1))
370 tmpx -= singleWidth(body_pos - 1);
373 if (hfillExpansion(text_, row_, pos)) {
374 tmpx += singleWidth(pos);
378 tmpx += label_hfill_;
381 else if (pit_->isSeparator(pos)) {
382 tmpx += singleWidth(pos);
386 tmpx += singleWidth(pos);
389 if ((startrow != row_ || text_.selection.start.pos() <= pos) &&
390 (endrow != row_ || pos < text_.selection.end.pos())) {
391 // Here we do not use x_ as xo_ was added to x_.
392 pain_.fillRectangle(int(old_tmpx), yo_,
393 int(tmpx - old_tmpx + 1),
394 row_->height(), LColor::selection);
398 if ((startrow != row_ && is_rtl) || (endrow != row_ && !is_rtl)) {
399 pain_.fillRectangle(xo_ + int(tmpx),
400 yo_, int(bv_.workWidth() - tmpx),
401 row_->height(), LColor::selection);
406 void RowPainter::paintChangeBar()
408 pos_type const start = row_->pos();
409 pos_type const end = lastPrintablePos(text_, row_);
411 if (!pit_->isChanged(start, end))
414 int const height = (boost::next(row_) != text_.rows().end()
415 ? row_->height() + boost::next(row_)->top_of_text()
418 pain_.fillRectangle(4, yo_, 5, height, LColor::changebar);
422 void RowPainter::paintAppendix()
424 if (!pit_->params().appendix())
427 // FIXME: can be just width_ ?
428 int const ww = bv_.workWidth();
432 if (pit_->params().startOfAppendix())
433 y += 2 * defaultRowHeight();
435 pain_.line(1, y, 1, yo_ + row_->height(), LColor::appendix);
436 pain_.line(ww - 2, y, ww - 2, yo_ + row_->height(), LColor::appendix);
440 void RowPainter::paintDepthBar()
442 Paragraph::depth_type const depth = pit_->getDepth();
447 Paragraph::depth_type prev_depth = 0;
448 if (row_ != text_.rows().begin())
449 prev_depth = boost::prior(row_)->par()->getDepth();
450 Paragraph::depth_type next_depth = 0;
451 if (boost::next(row_) != text_.rows().end())
452 next_depth = boost::next(row_)->par()->getDepth();
454 for (Paragraph::depth_type i = 1; i <= depth; ++i) {
455 int x = (PAPER_MARGIN / 5) * i + xo_;
456 // only consider the changebar space if we're drawing outer left
458 x += CHANGEBAR_MARGIN;
459 int const h = yo_ + row_->height() - 1 - (i - next_depth - 1) * 3;
461 pain_.line(x, yo_, x, h, LColor::depthbar);
463 int const w = PAPER_MARGIN / 5;
465 if (i > prev_depth) {
466 pain_.fillRectangle(x, yo_, w, 2, LColor::depthbar);
468 if (i > next_depth) {
469 pain_.fillRectangle(x, h, w, 2, LColor::depthbar);
475 int getLengthMarkerHeight(BufferView const & bv, VSpace const & vsp)
477 if (vsp.kind() == VSpace::NONE)
480 int const arrow_size = 4;
481 int const space_size = int(vsp.inPixels(bv));
485 int const min_size = max(3 * arrow_size,
486 font_metrics::maxAscent(font)
487 + font_metrics::maxDescent(font));
489 if (vsp.length().len().value() < 0.0)
492 return max(min_size, space_size);
496 int RowPainter::paintLengthMarker(string const & prefix, VSpace const & vsp, int start)
498 if (vsp.kind() == VSpace::NONE)
501 int const arrow_size = 4;
502 int const size = getLengthMarkerHeight(bv_, vsp);
503 int const end = start + size;
505 // the label to display (if any)
507 // y-values for top arrow
509 // y-values for bottom arrow
512 str = prefix + " (" + vsp.asLyXCommand() + ")";
514 if (vsp.kind() == VSpace::VFILL) {
518 // adding or removing space
519 bool const added = vsp.kind() != VSpace::LENGTH ||
520 vsp.length().len().value() > 0.0;
521 ty1 = added ? (start + arrow_size) : start;
522 ty2 = added ? start : (start + arrow_size);
523 by1 = added ? (end - arrow_size) : end;
524 by2 = added ? end : (end - arrow_size);
527 int const leftx = xo_ + leftMargin();
528 int const midx = leftx + arrow_size;
529 int const rightx = midx + arrow_size;
537 font.setColor(LColor::added_space).decSize().decSize();
538 font_metrics::rectText(str, font, w, a, d);
540 pain_.rectText(leftx + 2 * arrow_size + 5,
541 start + ((end - start) / 2) + d,
545 pain_.line(leftx, ty1, midx, ty2, LColor::added_space);
546 pain_.line(midx, ty2, rightx, ty1, LColor::added_space);
549 pain_.line(leftx, by1, midx, by2, LColor::added_space);
550 pain_.line(midx, by2, rightx, by1, LColor::added_space);
553 pain_.line(midx, ty2, midx, by2, LColor::added_space);
559 int RowPainter::paintPageBreak(string const & label, int y)
562 pb_font.setColor(LColor::pagebreak).decSize();
567 font_metrics::rectText(label, pb_font, w, a, d);
569 int const text_start = xo_ + ((width_ - w) / 2);
570 int const text_end = text_start + w;
572 pain_.rectText(text_start, y + d, label, pb_font);
574 pain_.line(xo_, y, text_start, y,
575 LColor::pagebreak, Painter::line_onoffdash);
576 pain_.line(text_end, y, xo_ + width_, y,
577 LColor::pagebreak, Painter::line_onoffdash);
579 return 3 * defaultRowHeight();
583 int RowPainter::paintAppendixStart(int y)
586 pb_font.setColor(LColor::appendix).decSize();
588 string const label = _("Appendix");
592 font_metrics::rectText(label, pb_font, w, a, d);
594 int const text_start = xo_ + ((width_ - w) / 2);
595 int const text_end = text_start + w;
597 pain_.rectText(text_start, y + d, label, pb_font);
599 pain_.line(xo_ + 1, y, text_start, y, LColor::appendix);
600 pain_.line(text_end, y, xo_ + width_ - 2, y, LColor::appendix);
602 return 3 * defaultRowHeight();
606 void RowPainter::paintFirst()
608 ParagraphParameters const & parparams = pit_->params();
612 // start of appendix?
613 if (parparams.startOfAppendix()) {
614 y_top += paintAppendixStart(yo_ + y_top + 2 * defaultRowHeight());
618 if (row_ == text_.rows().begin() && !text_.isInInset())
619 y_top += PAPER_MARGIN;
621 // draw a top pagebreak
622 if (parparams.pagebreakTop()) {
623 y_top += paintPageBreak(_("Page Break (top)"),
624 yo_ + y_top + 2 * defaultRowHeight());
627 // draw the additional space if needed:
628 y_top += paintLengthMarker(_("Space above"), parparams.spaceTop(),
631 Buffer const * buffer = bv_.buffer();
633 LyXLayout_ptr const & layout = pit_->layout();
635 if (buffer->params.paragraph_separation == BufferParams::PARSEP_SKIP) {
636 if (pit_->previous()) {
637 if (layout->latextype == LATEX_PARAGRAPH
638 && !pit_->getDepth()) {
639 y_top += buffer->params.getDefSkip().inPixels(bv_);
641 LyXLayout_ptr const & playout =
642 boost::prior(pit_)->layout();
643 if (playout->latextype == LATEX_PARAGRAPH
644 && !boost::prior(pit_)->getDepth()) {
645 // is it right to use defskip here, too? (AS)
646 y_top += buffer->params.getDefSkip().inPixels(bv_);
652 int const ww = bv_.workWidth();
655 if (parparams.lineTop()) {
656 LyXFont font(LyXFont::ALL_SANE);
657 int const asc = font_metrics::ascent('x', getFont(0));
661 int const w = (text_.isInInset() ? text_.inset_owner->width(perv(bv_), font) : ww);
662 int const xp = static_cast<int>(text_.isInInset() ? xo_ : 0);
663 pain_.line(xp, yo_ + y_top, xp + w, yo_ + y_top,
664 LColor::topline, Painter::line_solid,
665 Painter::line_thick);
670 bool const is_rtl = pit_->isRightToLeftPar(bv_.buffer()->params);
672 // should we print a label?
673 if (layout->labeltype >= LABEL_STATIC
674 && (layout->labeltype != LABEL_STATIC
675 || layout->latextype != LATEX_ENVIRONMENT
676 || pit_->isFirstInSequence())) {
678 LyXFont font = getLabelFont();
679 if (!pit_->getLabelstring().empty()) {
681 string const str = pit_->getLabelstring();
683 // this is special code for the chapter layout. This is
684 // printed in an extra row and has a pagebreak at
686 if (layout->labeltype == LABEL_COUNTER_CHAPTER) {
687 if (buffer->params.secnumdepth >= 0) {
688 float spacing_val = 1.0;
689 if (!parparams.spacing().isDefault()) {
690 spacing_val = parparams.spacing().getValue();
692 spacing_val = buffer->params.spacing.getValue();
696 int(font_metrics::maxDescent(font) * layout->spacing.getValue() * spacing_val)
697 + int(layout->parsep) * defaultRowHeight();
700 x = ww - leftMargin() -
701 font_metrics::width(str, font);
705 yo_ + row_->baseline() -
706 row_->ascent_of_text() - maxdesc,
711 x = ww - leftMargin()
712 + font_metrics::width(layout->labelsep, font);
714 x = x_ - font_metrics::width(layout->labelsep, font)
715 - font_metrics::width(str, font);
718 pain_.text(int(x), yo_ + row_->baseline(), str, font);
722 // the labels at the top of an environment.
723 // More or less for bibliography
724 } else if (pit_->isFirstInSequence() &&
725 (layout->labeltype == LABEL_TOP_ENVIRONMENT ||
726 layout->labeltype == LABEL_BIBLIO ||
727 layout->labeltype == LABEL_CENTERED_TOP_ENVIRONMENT)) {
728 LyXFont font = getLabelFont();
729 if (!pit_->getLabelstring().empty()) {
730 string const str = pit_->getLabelstring();
731 float spacing_val = 1.0;
732 if (!parparams.spacing().isDefault()) {
733 spacing_val = parparams.spacing().getValue();
735 spacing_val = buffer->params.spacing.getValue();
739 int(font_metrics::maxDescent(font) * layout->spacing.getValue() * spacing_val
740 + (layout->labelbottomsep * defaultRowHeight()));
743 if (layout->labeltype == LABEL_CENTERED_TOP_ENVIRONMENT) {
744 x = ((is_rtl ? leftMargin() : x_)
745 + ww - text_.rightMargin(*bv_.buffer(), *row_)) / 2;
746 x -= font_metrics::width(str, font) / 2;
748 x = ww - leftMargin() -
749 font_metrics::width(str, font);
751 pain_.text(int(x), yo_ + row_->baseline()
752 - row_->ascent_of_text() - maxdesc,
759 void RowPainter::paintLast()
761 ParagraphParameters const & parparams = pit_->params();
762 int y_bottom = row_->height() - 1;
765 if (boost::next(row_) == text_.rows().end() && !text_.isInInset())
766 y_bottom -= PAPER_MARGIN;
768 int const ww = bv_.workWidth();
770 // draw a bottom pagebreak
771 if (parparams.pagebreakBottom()) {
772 y_bottom -= paintPageBreak(_("Page Break (bottom)"),
773 yo_ + y_bottom - 2 * defaultRowHeight());
776 // draw the additional space if needed:
777 int const height = getLengthMarkerHeight(bv_, parparams.spaceBottom());
778 y_bottom -= paintLengthMarker(_("Space below"), parparams.spaceBottom(),
779 yo_ + y_bottom - height);
781 // draw a bottom line
782 if (parparams.lineBottom()) {
783 LyXFont font(LyXFont::ALL_SANE);
784 int const asc = font_metrics::ascent('x',
785 getFont(max(pos_type(0), pit_->size() - 1)));
789 int const w = (text_.isInInset() ? text_.inset_owner->width(perv(bv_), font) : ww);
790 int const xp = static_cast<int>(text_.isInInset() ? xo_ : 0);
791 int const y = yo_ + y_bottom;
792 pain_.line(xp, y, xp + w, y, LColor::topline, Painter::line_solid,
793 Painter::line_thick);
798 bool const is_rtl = pit_->isRightToLeftPar(bv_.buffer()->params);
799 int const endlabel = pit_->getEndLabel();
804 case END_LABEL_FILLED_BOX:
806 LyXFont const font = getLabelFont();
807 int const size = int(0.75 * font_metrics::maxAscent(font));
808 int const y = (yo_ + row_->baseline()) - size;
809 int x = is_rtl ? LEFT_MARGIN : ww - PAPER_MARGIN - size;
811 if (row_->fill() <= size)
812 x += (size - row_->fill() + 1) * (is_rtl ? -1 : 1);
814 if (endlabel == END_LABEL_BOX) {
815 pain_.rectangle(x, y, size, size, LColor::eolmarker);
817 pain_.fillRectangle(x, y, size, size, LColor::eolmarker);
821 case END_LABEL_STATIC:
824 LyXFont font(LyXFont::ALL_SANE);
825 font = getLabelFont();
827 LyXFont font = getLabelFont();
829 string const & str = pit_->layout()->endlabelstring();
830 int const x = is_rtl ?
831 int(x_) - font_metrics::width(str, font)
832 : ww - text_.rightMargin(*bv_.buffer(), *row_) - row_->fill();
833 pain_.text(x, yo_ + row_->baseline(), str, font);
836 case END_LABEL_NO_LABEL:
842 void RowPainter::paintText()
844 pos_type const last = lastPrintablePos(text_, row_);
845 pos_type body_pos = pit_->beginningOfBody();
847 (body_pos - 1 > last ||
848 !pit_->isLineSeparator(body_pos - 1))) {
852 LyXLayout_ptr const & layout = pit_->layout();
854 bool running_strikeout = false;
855 bool is_struckout = false;
856 float last_strikeout_x = 0.0;
858 pos_type vpos = row_->pos();
859 while (vpos <= last) {
860 if (x_ > bv_.workWidth())
862 pos_type pos = text_.vis2log(vpos);
864 if (pos >= pit_->size()) {
869 if (x_ + singleWidth(pos) < 0) {
870 x_ += singleWidth(pos);
875 is_struckout = isDeletedText(*pit_, pos);
877 if (is_struckout && !running_strikeout) {
878 running_strikeout = true;
879 last_strikeout_x = x_;
882 bool const highly_editable_inset = pit_->isInset(pos)
883 && isHighlyEditableInset(pit_->getInset(pos));
885 // if we reach the end of a struck out range, paint it
886 // we also don't paint across things like tables
887 if (running_strikeout && (highly_editable_inset || !is_struckout)) {
888 int const middle = yo_ + row_->top_of_text()
889 + ((row_->baseline() - row_->top_of_text()) / 2);
890 pain_.line(int(last_strikeout_x), middle, int(x_), middle,
891 LColor::strikeout, Painter::line_solid, Painter::line_thin);
892 running_strikeout = false;
895 if (body_pos > 0 && pos == body_pos - 1) {
896 int const lwidth = font_metrics::width(layout->labelsep,
899 x_ += label_hfill_ + lwidth
900 - singleWidth(body_pos - 1);
903 if (pit_->isHfill(pos)) {
906 int const y0 = yo_ + row_->baseline();
907 int const y1 = y0 - defaultRowHeight() / 2;
909 pain_.line(int(x_), y1, int(x_), y0,
910 LColor::added_space);
912 if (hfillExpansion(text_, row_, pos)) {
913 int const y2 = (y0 + y1) / 2;
915 if (pos >= body_pos) {
916 pain_.line(int(x_), y2,
917 int(x_ + hfill_), y2,
919 Painter::line_onoffdash);
922 pain_.line(int(x_), y2,
923 int(x_ + label_hfill_), y2,
925 Painter::line_onoffdash);
928 pain_.line(int(x_), y1,
930 LColor::added_space);
934 } else if (pit_->isSeparator(pos)) {
935 x_ += singleWidth(pos);
944 // if we reach the end of a struck out range, paint it
945 if (running_strikeout) {
946 int const middle = yo_ + row_->top_of_text()
947 + ((row_->baseline() - row_->top_of_text()) / 2);
948 pain_.line(int(last_strikeout_x), middle, int(x_), middle,
949 LColor::strikeout, Painter::line_solid, Painter::line_thin);
950 running_strikeout = false;
956 void RowPainter::paint(int y_offset, int x_offset, int y)
961 width_ = text_.isInInset()
962 ? text_.inset_owner->textWidth(perv(bv_), true) : bv_.workWidth();
964 // FIXME: must be a cleaner way here. Aren't these calculations
965 // belonging to row metrics ?
966 text_.prepareToPrint(row_, x_, separator_, hfill_, label_hfill_);
968 // FIXME: what is this fixing ?
969 if (text_.isInInset() && (x_ < 0))
973 // If we're *not* at the top-level of rows, then the
974 // background has already been cleared.
975 if (&text_ == bv_.text)
978 // paint the selection background
979 if (text_.selection.set()) {
983 // vertical lines for appendix
986 // environment depth brackets
992 if (row_->isParStart()) {
996 if (isParEnd(text_, row_)) {