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 "paragraph_funcs.h"
22 #include "support/textutils.h"
24 #include "insets/insettext.h"
25 #include "ParagraphParameters.h"
26 #include "BufferView.h"
33 #include "rowpainter.h"
35 #include "lyxrow_funcs.h"
40 extern int PAPER_MARGIN;
41 extern int CHANGEBAR_MARGIN;
42 extern int LEFT_MARGIN;
46 // "temporary". We'll never get to use more
47 // references until we start adding hacks like
48 // these until other places catch up.
49 BufferView * perv(BufferView const & bv)
51 return const_cast<BufferView *>(&bv);
57 RowPainter::RowPainter(BufferView const & bv,
58 LyXText const & text, RowList::iterator rit)
59 : bv_(bv), pain_(bv_.painter()), text_(text), row_(rit), pit_(rit->par())
64 LyXFont const RowPainter::getFont(pos_type pos) const
66 return text_.getFont(bv_.buffer(), pit_, pos);
70 int RowPainter::singleWidth(lyx::pos_type pos) const
72 return text_.singleWidth(pit_, pos);
76 int RowPainter::singleWidth(lyx::pos_type pos, char c) const
78 return text_.singleWidth(pit_, pos, c);
82 LyXFont const RowPainter::getLabelFont() const
84 return text_.getLabelFont(bv_.buffer(), pit_);
88 char const RowPainter::transformChar(char c, lyx::pos_type pos) const
90 return text_.transformChar(c, *pit_, pos);
94 int RowPainter::leftMargin() const
96 return text_.leftMargin(*row_);
100 void RowPainter::paintInset(pos_type const pos)
102 Inset * inset = const_cast<Inset*>(pit_->getInset(pos));
106 LyXFont const & font = getFont(pos);
108 #warning inset->update FIXME
109 inset->update(perv(bv_), false);
111 inset->draw(perv(bv_), font, yo_ + row_->baseline(), x_);
115 void RowPainter::paintHebrewComposeChar(pos_type & vpos)
117 pos_type pos = text_.vis2log(vpos);
122 char c = pit_->getChar(pos);
126 LyXFont const & font = getFont(pos);
127 int const width = font_metrics::width(c, font);
130 for (pos_type i = pos - 1; i >= 0; --i) {
131 c = pit_->getChar(i);
132 if (!Encodings::IsComposeChar_hebrew(c)) {
133 if (IsPrintableNonspace(c)) {
137 dx = (c == 'ø' || c == 'ã')
139 : (width2 - width) / 2;
146 pain_.text(int(x_) + dx, yo_ + row_->baseline(), str, font);
150 void RowPainter::paintArabicComposeChar(pos_type & vpos)
152 pos_type pos = text_.vis2log(vpos);
156 char c = pit_->getChar(pos);
157 c = transformChar(c, pos);
161 LyXFont const & font = getFont(pos);
162 int const width = font_metrics::width(c, font);
165 for (pos_type i = pos - 1; i >= 0; --i) {
166 c = pit_->getChar(i);
167 if (!Encodings::IsComposeChar_arabic(c)) {
168 if (IsPrintableNonspace(c)) {
171 dx = (width2 - width) / 2;
177 pain_.text(int(x_) + dx, yo_ + row_->baseline(), str, font);
181 void RowPainter::paintChars(pos_type & vpos, bool hebrew, bool arabic)
183 pos_type pos = text_.vis2log(vpos);
184 pos_type const last = lastPrintablePos(text_, row_);
185 LyXFont orig_font(getFont(pos));
189 str += pit_->getChar(pos);
191 unsigned char c = str[0];
192 str[0] = transformChar(c, pos);
195 bool prev_struckout(isDeletedText(*pit_, pos));
196 bool prev_newtext(isInsertedText(*pit_, pos));
200 // collect as much similar chars as we can
201 while (vpos <= last && (pos = text_.vis2log(vpos)) >= 0) {
202 char c = pit_->getChar(pos);
204 if (!IsPrintableNonspace(c))
207 if (prev_struckout != isDeletedText(*pit_, pos))
210 if (prev_newtext != isInsertedText(*pit_, pos))
213 if (arabic && Encodings::IsComposeChar_arabic(c))
215 if (hebrew && Encodings::IsComposeChar_hebrew(c))
218 if (orig_font != getFont(pos))
222 c = transformChar(c, pos);
227 if (prev_struckout) {
228 orig_font.setColor(LColor::strikeout);
229 } else if (prev_newtext) {
230 orig_font.setColor(LColor::newtext);
233 // Draw text and set the new x position
234 pain_.text(int(x_), yo_ + row_->baseline(), str, orig_font);
235 x_ += font_metrics::width(str, orig_font);
239 void RowPainter::paintForeignMark(float const orig_x, LyXFont const & orig_font)
241 if (!lyxrc.mark_foreign_language)
243 if (orig_font.language() == latex_language)
245 if (orig_font.language() == bv_.buffer()->params.language)
248 int const y = yo_ + row_->baseline() + 1;
249 pain_.line(int(orig_x), y, int(x_), y, LColor::language);
253 void RowPainter::paintFromPos(pos_type & vpos)
255 pos_type const pos = text_.vis2log(vpos);
257 LyXFont const & orig_font = getFont(pos);
259 float const orig_x = x_;
261 char const c = pit_->getChar(pos);
263 if (IsInsetChar(c)) {
266 paintForeignMark(orig_x, orig_font);
270 // usual characters, no insets
272 // special case languages
273 bool const hebrew = (orig_font.language()->lang() == "hebrew");
275 orig_font.language()->lang() == "arabic" &&
276 (lyxrc.font_norm_type == LyXRC::ISO_8859_6_8 ||
277 lyxrc.font_norm_type == LyXRC::ISO_10646_1);
279 // draw as many chars as we can
280 if ((!hebrew && !arabic)
281 || (hebrew && !Encodings::IsComposeChar_hebrew(c))
282 || (arabic && !Encodings::IsComposeChar_arabic(c))) {
283 paintChars(vpos, hebrew, arabic);
285 paintHebrewComposeChar(vpos);
287 paintArabicComposeChar(vpos);
290 paintForeignMark(orig_x, orig_font);
296 void RowPainter::paintBackground()
299 int const y = yo_ < 0 ? 0 : yo_;
300 int const h = yo_ < 0 ? row_->height() + yo_ : row_->height();
301 pain_.fillRectangle(x, y, width_, h, text_.backgroundColor());
305 void RowPainter::paintSelection()
307 bool const is_rtl = pit_->isRightToLeftPar(bv_.buffer()->params);
309 // the current selection
310 int const startx = text_.selection.start.x();
311 int const endx = text_.selection.end.x();
312 int const starty = text_.selection.start.y();
313 int const endy = text_.selection.end.y();
314 RowList::iterator startrow = text_.selection.start.row();
315 RowList::iterator endrow = text_.selection.end.row();
317 if (text_.bidi_same_direction) {
321 int h = row_->height();
323 if (startrow == row_ && endrow == row_) {
327 pain_.fillRectangle(x, y, w, h, LColor::selection);
331 pain_.fillRectangle(x, y, w, h, LColor::selection);
333 } else if (startrow == row_) {
334 int const x = (is_rtl) ? xo_ : (xo_ + startx);
335 int const w = (is_rtl) ? startx : (width_ - startx);
336 pain_.fillRectangle(x, y, w, h, LColor::selection);
337 } else if (endrow == row_) {
338 int const x = (is_rtl) ? (xo_ + endx) : xo_;
339 int const w = (is_rtl) ? (width_ - endx) : endx;
340 pain_.fillRectangle(x, y, w, h, LColor::selection);
341 } else if (y_ > starty && y_ < endy) {
342 pain_.fillRectangle(xo_, y, width_, h, LColor::selection);
345 } else if (startrow != row_ && endrow != row_) {
346 if (y_ > starty && y_ < endy) {
348 int h = row_->height();
349 pain_.fillRectangle(xo_, yo_, w, h, LColor::selection);
354 if ((startrow != row_ && !is_rtl) || (endrow != row_ && is_rtl))
355 pain_.fillRectangle(xo_, yo_, int(x_), row_->height(), LColor::selection);
357 pos_type const body_pos = pit_->beginningOfBody();
358 pos_type const last = lastPrintablePos(text_, row_);
361 for (pos_type vpos = row_->pos(); vpos <= last; ++vpos) {
362 pos_type pos = text_.vis2log(vpos);
363 float const old_tmpx = tmpx;
364 if (body_pos > 0 && pos == body_pos - 1) {
365 LyXLayout_ptr const & layout = pit_->layout();
366 LyXFont const lfont = getLabelFont();
368 tmpx += label_hfill_ + font_metrics::width(layout->labelsep, lfont);
370 if (pit_->isLineSeparator(body_pos - 1))
371 tmpx -= singleWidth(body_pos - 1);
374 if (hfillExpansion(text_, row_, pos)) {
375 tmpx += singleWidth(pos);
379 tmpx += label_hfill_;
382 else if (pit_->isSeparator(pos)) {
383 tmpx += singleWidth(pos);
387 tmpx += singleWidth(pos);
390 if ((startrow != row_ || text_.selection.start.pos() <= pos) &&
391 (endrow != row_ || pos < text_.selection.end.pos())) {
392 // Here we do not use x_ as xo_ was added to x_.
393 pain_.fillRectangle(int(old_tmpx), yo_,
394 int(tmpx - old_tmpx + 1),
395 row_->height(), LColor::selection);
399 if ((startrow != row_ && is_rtl) || (endrow != row_ && !is_rtl)) {
400 pain_.fillRectangle(xo_ + int(tmpx),
401 yo_, int(bv_.workWidth() - tmpx),
402 row_->height(), LColor::selection);
407 void RowPainter::paintChangeBar()
409 pos_type const start = row_->pos();
410 pos_type const end = lastPrintablePos(text_, row_);
412 if (!pit_->isChanged(start, end))
415 int const height = (boost::next(row_) != text_.rows().end()
416 ? row_->height() + boost::next(row_)->top_of_text()
419 pain_.fillRectangle(4, yo_, 5, height, LColor::changebar);
423 void RowPainter::paintAppendix()
425 if (!pit_->params().appendix())
428 // FIXME: can be just width_ ?
429 int const ww = bv_.workWidth();
433 if (pit_->params().startOfAppendix())
434 y += 2 * defaultRowHeight();
436 pain_.line(1, y, 1, yo_ + row_->height(), LColor::appendix);
437 pain_.line(ww - 2, y, ww - 2, yo_ + row_->height(), LColor::appendix);
441 void RowPainter::paintDepthBar()
443 Paragraph::depth_type const depth = pit_->getDepth();
448 Paragraph::depth_type prev_depth = 0;
449 if (row_ != text_.rows().begin())
450 prev_depth = boost::prior(row_)->par()->getDepth();
451 Paragraph::depth_type next_depth = 0;
452 if (boost::next(row_) != text_.rows().end())
453 next_depth = boost::next(row_)->par()->getDepth();
455 for (Paragraph::depth_type i = 1; i <= depth; ++i) {
456 int x = (PAPER_MARGIN / 5) * i + xo_;
457 // only consider the changebar space if we're drawing outer left
459 x += CHANGEBAR_MARGIN;
460 int const h = yo_ + row_->height() - 1 - (i - next_depth - 1) * 3;
462 pain_.line(x, yo_, x, h, LColor::depthbar);
464 int const w = PAPER_MARGIN / 5;
466 if (i > prev_depth) {
467 pain_.fillRectangle(x, yo_, w, 2, LColor::depthbar);
469 if (i > next_depth) {
470 pain_.fillRectangle(x, h, w, 2, LColor::depthbar);
476 int getLengthMarkerHeight(BufferView const & bv, VSpace const & vsp)
478 if (vsp.kind() == VSpace::NONE)
481 int const arrow_size = 4;
482 int const space_size = int(vsp.inPixels(bv));
486 int const min_size = max(3 * arrow_size,
487 font_metrics::maxAscent(font)
488 + font_metrics::maxDescent(font));
490 if (vsp.length().len().value() < 0.0)
493 return max(min_size, space_size);
497 int RowPainter::paintLengthMarker(string const & prefix, VSpace const & vsp, int start)
499 if (vsp.kind() == VSpace::NONE)
502 int const arrow_size = 4;
503 int const size = getLengthMarkerHeight(bv_, vsp);
504 int const end = start + size;
506 // the label to display (if any)
508 // y-values for top arrow
510 // y-values for bottom arrow
513 str = prefix + " (" + vsp.asLyXCommand() + ")";
515 if (vsp.kind() == VSpace::VFILL) {
519 // adding or removing space
520 bool const added = vsp.kind() != VSpace::LENGTH ||
521 vsp.length().len().value() > 0.0;
522 ty1 = added ? (start + arrow_size) : start;
523 ty2 = added ? start : (start + arrow_size);
524 by1 = added ? (end - arrow_size) : end;
525 by2 = added ? end : (end - arrow_size);
528 int const leftx = xo_ + leftMargin();
529 int const midx = leftx + arrow_size;
530 int const rightx = midx + arrow_size;
538 font.setColor(LColor::added_space).decSize().decSize();
539 font_metrics::rectText(str, font, w, a, d);
541 pain_.rectText(leftx + 2 * arrow_size + 5,
542 start + ((end - start) / 2) + d,
546 pain_.line(leftx, ty1, midx, ty2, LColor::added_space);
547 pain_.line(midx, ty2, rightx, ty1, LColor::added_space);
550 pain_.line(leftx, by1, midx, by2, LColor::added_space);
551 pain_.line(midx, by2, rightx, by1, LColor::added_space);
554 pain_.line(midx, ty2, midx, by2, LColor::added_space);
560 int RowPainter::paintPageBreak(string const & label, int y)
563 pb_font.setColor(LColor::pagebreak).decSize();
568 font_metrics::rectText(label, pb_font, w, a, d);
570 int const text_start = xo_ + ((width_ - w) / 2);
571 int const text_end = text_start + w;
573 pain_.rectText(text_start, y + d, label, pb_font);
575 pain_.line(xo_, y, text_start, y,
576 LColor::pagebreak, Painter::line_onoffdash);
577 pain_.line(text_end, y, xo_ + width_, y,
578 LColor::pagebreak, Painter::line_onoffdash);
580 return 3 * defaultRowHeight();
584 int RowPainter::paintAppendixStart(int y)
587 pb_font.setColor(LColor::appendix).decSize();
589 string const label = _("Appendix");
593 font_metrics::rectText(label, pb_font, w, a, d);
595 int const text_start = xo_ + ((width_ - w) / 2);
596 int const text_end = text_start + w;
598 pain_.rectText(text_start, y + d, label, pb_font);
600 pain_.line(xo_ + 1, y, text_start, y, LColor::appendix);
601 pain_.line(text_end, y, xo_ + width_ - 2, y, LColor::appendix);
603 return 3 * defaultRowHeight();
607 void RowPainter::paintFirst()
609 ParagraphParameters const & parparams = pit_->params();
613 // start of appendix?
614 if (parparams.startOfAppendix()) {
615 y_top += paintAppendixStart(yo_ + y_top + 2 * defaultRowHeight());
619 if (row_ == text_.rows().begin() && !text_.isInInset())
620 y_top += PAPER_MARGIN;
622 // draw a top pagebreak
623 if (parparams.pagebreakTop()) {
624 y_top += paintPageBreak(_("Page Break (top)"),
625 yo_ + y_top + 2 * defaultRowHeight());
628 // draw the additional space if needed:
629 y_top += paintLengthMarker(_("Space above"), parparams.spaceTop(),
632 Buffer const * buffer = bv_.buffer();
634 LyXLayout_ptr const & layout = pit_->layout();
636 if (buffer->params.paragraph_separation == BufferParams::PARSEP_SKIP) {
637 if (pit_->previous()) {
638 if (layout->latextype == LATEX_PARAGRAPH
639 && !pit_->getDepth()) {
640 y_top += buffer->params.getDefSkip().inPixels(bv_);
642 LyXLayout_ptr const & playout =
643 boost::prior(pit_)->layout();
644 if (playout->latextype == LATEX_PARAGRAPH
645 && !boost::prior(pit_)->getDepth()) {
646 // is it right to use defskip here, too? (AS)
647 y_top += buffer->params.getDefSkip().inPixels(bv_);
653 int const ww = bv_.workWidth();
656 if (parparams.lineTop()) {
657 LyXFont font(LyXFont::ALL_SANE);
658 int const asc = font_metrics::ascent('x', getFont(0));
662 int const w = (text_.isInInset() ? text_.inset_owner->width(perv(bv_), font) : ww);
663 int const xp = static_cast<int>(text_.isInInset() ? xo_ : 0);
664 pain_.line(xp, yo_ + y_top, xp + w, yo_ + y_top,
665 LColor::topline, Painter::line_solid,
666 Painter::line_thick);
671 bool const is_rtl = pit_->isRightToLeftPar(bv_.buffer()->params);
673 // should we print a label?
674 if (layout->labeltype >= LABEL_STATIC
675 && (layout->labeltype != LABEL_STATIC
676 || layout->latextype != LATEX_ENVIRONMENT
677 || isFirstInSequence(pit_, text_.ownerParagraphs()))) {
679 LyXFont font = getLabelFont();
680 if (!pit_->getLabelstring().empty()) {
682 string const str = pit_->getLabelstring();
684 // this is special code for the chapter layout. This is
685 // printed in an extra row and has a pagebreak at
687 if (layout->labeltype == LABEL_COUNTER_CHAPTER) {
688 if (buffer->params.secnumdepth >= 0) {
689 float spacing_val = 1.0;
690 if (!parparams.spacing().isDefault()) {
691 spacing_val = parparams.spacing().getValue();
693 spacing_val = buffer->params.spacing.getValue();
697 int(font_metrics::maxDescent(font) * layout->spacing.getValue() * spacing_val)
698 + int(layout->parsep) * defaultRowHeight();
701 x = ww - leftMargin() -
702 font_metrics::width(str, font);
706 yo_ + row_->baseline() -
707 row_->ascent_of_text() - maxdesc,
712 x = ww - leftMargin()
713 + font_metrics::width(layout->labelsep, font);
715 x = x_ - font_metrics::width(layout->labelsep, font)
716 - font_metrics::width(str, font);
719 pain_.text(int(x), yo_ + row_->baseline(), str, font);
723 // the labels at the top of an environment.
724 // More or less for bibliography
725 } else if (isFirstInSequence(pit_, text_.ownerParagraphs()) &&
726 (layout->labeltype == LABEL_TOP_ENVIRONMENT ||
727 layout->labeltype == LABEL_BIBLIO ||
728 layout->labeltype == LABEL_CENTERED_TOP_ENVIRONMENT)) {
729 LyXFont font = getLabelFont();
730 if (!pit_->getLabelstring().empty()) {
731 string const str = pit_->getLabelstring();
732 float spacing_val = 1.0;
733 if (!parparams.spacing().isDefault()) {
734 spacing_val = parparams.spacing().getValue();
736 spacing_val = buffer->params.spacing.getValue();
740 int(font_metrics::maxDescent(font) * layout->spacing.getValue() * spacing_val
741 + (layout->labelbottomsep * defaultRowHeight()));
744 if (layout->labeltype == LABEL_CENTERED_TOP_ENVIRONMENT) {
745 x = ((is_rtl ? leftMargin() : x_)
746 + ww - text_.rightMargin(*bv_.buffer(), *row_)) / 2;
747 x -= font_metrics::width(str, font) / 2;
749 x = ww - leftMargin() -
750 font_metrics::width(str, font);
752 pain_.text(int(x), yo_ + row_->baseline()
753 - row_->ascent_of_text() - maxdesc,
760 void RowPainter::paintLast()
762 ParagraphParameters const & parparams = pit_->params();
763 int y_bottom = row_->height() - 1;
766 if (boost::next(row_) == text_.rows().end() && !text_.isInInset())
767 y_bottom -= PAPER_MARGIN;
769 int const ww = bv_.workWidth();
771 // draw a bottom pagebreak
772 if (parparams.pagebreakBottom()) {
773 y_bottom -= paintPageBreak(_("Page Break (bottom)"),
774 yo_ + y_bottom - 2 * defaultRowHeight());
777 // draw the additional space if needed:
778 int const height = getLengthMarkerHeight(bv_, parparams.spaceBottom());
779 y_bottom -= paintLengthMarker(_("Space below"), parparams.spaceBottom(),
780 yo_ + y_bottom - height);
782 // draw a bottom line
783 if (parparams.lineBottom()) {
784 LyXFont font(LyXFont::ALL_SANE);
785 int const asc = font_metrics::ascent('x',
786 getFont(max(pos_type(0), pit_->size() - 1)));
790 int const w = (text_.isInInset() ? text_.inset_owner->width(perv(bv_), font) : ww);
791 int const xp = static_cast<int>(text_.isInInset() ? xo_ : 0);
792 int const y = yo_ + y_bottom;
793 pain_.line(xp, y, xp + w, y, LColor::topline, Painter::line_solid,
794 Painter::line_thick);
799 bool const is_rtl = pit_->isRightToLeftPar(bv_.buffer()->params);
800 int const endlabel = getEndLabel(pit_, text_.ownerParagraphs());
805 case END_LABEL_FILLED_BOX:
807 LyXFont const font = getLabelFont();
808 int const size = int(0.75 * font_metrics::maxAscent(font));
809 int const y = (yo_ + row_->baseline()) - size;
810 int x = is_rtl ? LEFT_MARGIN : ww - PAPER_MARGIN - size;
812 if (row_->fill() <= size)
813 x += (size - row_->fill() + 1) * (is_rtl ? -1 : 1);
815 if (endlabel == END_LABEL_BOX) {
816 pain_.rectangle(x, y, size, size, LColor::eolmarker);
818 pain_.fillRectangle(x, y, size, size, LColor::eolmarker);
822 case END_LABEL_STATIC:
825 LyXFont font(LyXFont::ALL_SANE);
826 font = getLabelFont();
828 LyXFont font = getLabelFont();
830 string const & str = pit_->layout()->endlabelstring();
831 int const x = is_rtl ?
832 int(x_) - font_metrics::width(str, font)
833 : ww - text_.rightMargin(*bv_.buffer(), *row_) - row_->fill();
834 pain_.text(x, yo_ + row_->baseline(), str, font);
837 case END_LABEL_NO_LABEL:
843 void RowPainter::paintText()
845 pos_type const last = lastPrintablePos(text_, row_);
846 pos_type body_pos = pit_->beginningOfBody();
848 (body_pos - 1 > last ||
849 !pit_->isLineSeparator(body_pos - 1))) {
853 LyXLayout_ptr const & layout = pit_->layout();
855 bool running_strikeout = false;
856 bool is_struckout = false;
857 float last_strikeout_x = 0.0;
859 pos_type vpos = row_->pos();
860 while (vpos <= last) {
861 if (x_ > bv_.workWidth())
863 pos_type pos = text_.vis2log(vpos);
865 if (pos >= pit_->size()) {
870 if (x_ + singleWidth(pos) < 0) {
871 x_ += singleWidth(pos);
876 is_struckout = isDeletedText(*pit_, pos);
878 if (is_struckout && !running_strikeout) {
879 running_strikeout = true;
880 last_strikeout_x = x_;
883 bool const highly_editable_inset = pit_->isInset(pos)
884 && isHighlyEditableInset(pit_->getInset(pos));
886 // if we reach the end of a struck out range, paint it
887 // we also don't paint across things like tables
888 if (running_strikeout && (highly_editable_inset || !is_struckout)) {
889 int const middle = yo_ + row_->top_of_text()
890 + ((row_->baseline() - row_->top_of_text()) / 2);
891 pain_.line(int(last_strikeout_x), middle, int(x_), middle,
892 LColor::strikeout, Painter::line_solid, Painter::line_thin);
893 running_strikeout = false;
896 if (body_pos > 0 && pos == body_pos - 1) {
897 int const lwidth = font_metrics::width(layout->labelsep,
900 x_ += label_hfill_ + lwidth
901 - singleWidth(body_pos - 1);
904 if (pit_->isHfill(pos)) {
907 int const y0 = yo_ + row_->baseline();
908 int const y1 = y0 - defaultRowHeight() / 2;
910 pain_.line(int(x_), y1, int(x_), y0,
911 LColor::added_space);
913 if (hfillExpansion(text_, row_, pos)) {
914 int const y2 = (y0 + y1) / 2;
916 if (pos >= body_pos) {
917 pain_.line(int(x_), y2,
918 int(x_ + hfill_), y2,
920 Painter::line_onoffdash);
923 pain_.line(int(x_), y2,
924 int(x_ + label_hfill_), y2,
926 Painter::line_onoffdash);
929 pain_.line(int(x_), y1,
931 LColor::added_space);
935 } else if (pit_->isSeparator(pos)) {
936 x_ += singleWidth(pos);
945 // if we reach the end of a struck out range, paint it
946 if (running_strikeout) {
947 int const middle = yo_ + row_->top_of_text()
948 + ((row_->baseline() - row_->top_of_text()) / 2);
949 pain_.line(int(last_strikeout_x), middle, int(x_), middle,
950 LColor::strikeout, Painter::line_solid, Painter::line_thin);
951 running_strikeout = false;
957 void RowPainter::paint(int y_offset, int x_offset, int y)
962 width_ = text_.isInInset()
963 ? text_.inset_owner->textWidth(perv(bv_), true) : bv_.workWidth();
965 // FIXME: must be a cleaner way here. Aren't these calculations
966 // belonging to row metrics ?
967 text_.prepareToPrint(row_, x_, separator_, hfill_, label_hfill_);
969 // FIXME: what is this fixing ?
970 if (text_.isInInset() && (x_ < 0))
974 // If we're *not* at the top-level of rows, then the
975 // background has already been cleared.
976 if (&text_ == bv_.text)
979 // paint the selection background
980 if (text_.selection.set()) {
984 // vertical lines for appendix
987 // environment depth brackets
993 if (row_->isParStart()) {
997 if (isParEnd(text_, row_)) {