X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Frowpainter.C;h=fdb3450e6407679b09c51d90fc9ce9b2853d8b10;hb=35204f8f33d7400a5fefeffea533fb4cb4097211;hp=f4fb24d1e2b806737aafc5052c10521829f7b278;hpb=128a8ef3e86fedf60b2a123da089898994f4211e;p=lyx.git diff --git a/src/rowpainter.C b/src/rowpainter.C index f4fb24d1e2..fdb3450e64 100644 --- a/src/rowpainter.C +++ b/src/rowpainter.C @@ -129,7 +129,7 @@ RowPainter::RowPainter(PainterInfo & pi, erased_(pi.erased_), xo_(x), yo_(y), width_(text_.width()) { - RowMetrics m = text_.computeRowMetrics(pit, row_); + RowMetrics m = text_.computeRowMetrics(*bv_.buffer(), pit, row_); x_ = m.x + xo_; //lyxerr << "RowPainter: x: " << x_ << " xo: " << xo_ << " yo: " << yo_ << endl; @@ -146,16 +146,21 @@ RowPainter::RowPainter(PainterInfo & pi, LyXFont const RowPainter::getLabelFont() const { - return text_.getLabelFont(par_); + return text_.getLabelFont(*bv_.buffer(), par_); } int RowPainter::leftMargin() const { - return text_.leftMargin(pit_, row_.pos()); + return text_.leftMargin(*bv_.buffer(), pit_, row_.pos()); } +// If you want to debug inset metrics uncomment the following line: +// #define DEBUG_METRICS +// This draws green lines around each inset. + + void RowPainter::paintInset(pos_type const pos, LyXFont const & font) { InsetBase const * inset = par_.getInset(pos); @@ -168,19 +173,53 @@ void RowPainter::paintInset(pos_type const pos, LyXFont const & font) font; pi.ltr_pos = (text_.bidi.level(pos) % 2 == 0); pi.erased_ = erased_ || par_.isDeleted(pos); +#ifdef DEBUG_METRICS + int const x1 = int(x_); +#endif bv_.coordCache().insets().add(inset, int(x_), yo_); InsetText const * const in = inset->asTextInset(); // non-wide insets are painted completely. Recursive bool tmp = refreshInside; - if (!in || !in->Wide()) { + if (!in || !in->wide()) { refreshInside = true; - lyxerr[Debug::PAINTING] << endl << "Paint inset fully" << endl; + if (lyxerr.debugging(Debug::PAINTING)) { + lyxerr << endl << "Paint inset fully" << endl; + } } if (refreshInside) inset->drawSelection(pi, int(x_), yo_); inset->draw(pi, int(x_), yo_); refreshInside = tmp; x_ += inset->width(); +#ifdef DEBUG_METRICS + Dimension dim; + BOOST_ASSERT(text_.maxwidth_ > 0); + int const w = text_.maxwidth_ - leftMargin() - text_.rightMargin(*bv_.buffer(), par_); + MetricsInfo mi(&bv_, font, w); + inset->metrics(mi, dim); + if (inset->width() > dim.wid) + lyxerr << "Error: inset " << to_ascii(inset->getInsetName()) + << " draw width " << inset->width() + << "> metrics width " << dim.wid << "." << std::endl; + if (inset->ascent() > dim.asc) + lyxerr << "Error: inset " << to_ascii(inset->getInsetName()) + << " draw ascent " << inset->ascent() + << "> metrics ascent " << dim.asc << "." << std::endl; + if (inset->descent() > dim.des) + lyxerr << "Error: inset " << to_ascii(inset->getInsetName()) + << " draw ascent " << inset->descent() + << "> metrics descent " << dim.des << "." << std::endl; + BOOST_ASSERT(inset->width() <= dim.wid); + BOOST_ASSERT(inset->ascent() <= dim.asc); + BOOST_ASSERT(inset->descent() <= dim.des); + int const x2 = x1 + dim.wid; + int const y1 = yo_ + dim.des; + int const y2 = yo_ - dim.asc; + pi.pain.line(x1, y1, x1, y2, LColor::green); + pi.pain.line(x1, y1, x2, y1, LColor::green); + pi.pain.line(x2, y1, x2, y2, LColor::green); + pi.pain.line(x1, y2, x2, y2, LColor::green); +#endif } @@ -202,8 +241,8 @@ void RowPainter::paintHebrewComposeChar(pos_type & vpos, LyXFont const & font) c = par_.getChar(i); if (!Encodings::isComposeChar_hebrew(c)) { if (isPrintableNonspace(c)) { - int const width2 = - text_.singleWidth(par_, i, c, text_.getFont(par_, i)); + int const width2 = text_.singleWidth(par_, i, c, + text_.getFont(*bv_.buffer(), par_, i)); // FIXME UNICODE // This does not work anymore, and non-ascii // characters in source files are forbidden @@ -241,8 +280,8 @@ void RowPainter::paintArabicComposeChar(pos_type & vpos, LyXFont const & font) c = par_.getChar(i); if (!Encodings::isComposeChar_arabic(c)) { if (isPrintableNonspace(c)) { - int const width2 = - text_.singleWidth(par_, i, c, text_.getFont(par_, i)); + int const width2 = text_.singleWidth(par_, i, c, + text_.getFont(*bv_.buffer(), par_, i)); dx = (width2 - width) / 2; } break; @@ -328,7 +367,7 @@ void RowPainter::paintForeignMark(double orig_x, LyXFont const & font, int desc) void RowPainter::paintFromPos(pos_type & vpos) { pos_type const pos = text_.bidi.vis2log(vpos); - LyXFont orig_font = text_.getFont(par_, pos); + LyXFont orig_font = text_.getFont(*bv_.buffer(), par_, pos); double const orig_x = x_; @@ -368,7 +407,13 @@ void RowPainter::paintFromPos(pos_type & vpos) void RowPainter::paintChangeBar() { pos_type const start = row_.pos(); - pos_type const end = row_.endpos(); + pos_type end = row_.endpos(); + + if (par_.size() == end) { + // this is the last row of the paragraph; + // thus, we must also consider the imaginary end-of-par character + end++; + } if (start == end || !par_.isChanged(start, end)) return; @@ -423,7 +468,7 @@ void RowPainter::paintDepthBar() int const w = nestMargin() / 5; int x = int(xo_) + w * i; // only consider the changebar space if we're drawing outermost text - if (text_.isMainText()) + if (text_.isMainText(*bv_.buffer())) x += changebarMargin(); int const starty = yo_ - row_.ascent(); @@ -494,7 +539,7 @@ void RowPainter::paintFirst() } } - bool const is_rtl = text_.isRTL(par_); + bool const is_rtl = text_.isRTL(buffer, par_); bool const is_seq = isFirstInSequence(pit_, text_.paragraphs()); //lyxerr << "paintFirst: " << par_.id() << " is_seq: " << is_seq << std::endl; @@ -576,7 +621,7 @@ void RowPainter::paintFirst() if (layout->labeltype == LABEL_CENTERED_TOP_ENVIRONMENT) { if (is_rtl) x = leftMargin(); - x += (width_ - text_.rightMargin(par_) - leftMargin()) / 2; + x += (width_ - text_.rightMargin(buffer, par_) - leftMargin()) / 2; x -= fm.width(str) / 2; } else if (is_rtl) { x = width_ - leftMargin() - fm.width(str); @@ -589,7 +634,7 @@ void RowPainter::paintFirst() void RowPainter::paintLast() { - bool const is_rtl = text_.isRTL(par_); + bool const is_rtl = text_.isRTL(*bv_.buffer(), par_); int const endlabel = getEndLabel(pit_, text_.paragraphs()); // draw an endlabel @@ -618,7 +663,7 @@ void RowPainter::paintLast() docstring const & str = par_.layout()->endlabelstring(); double const x = is_rtl ? x_ - fm.width(str) - : - text_.rightMargin(par_) - row_.width(); + : - text_.rightMargin(*bv_.buffer(), par_) - row_.width(); pain_.text(int(x), yo_, str, font); break; } @@ -647,6 +692,7 @@ void RowPainter::paintText() // Use font span to speed things up, see below FontSpan font_span; LyXFont font; + Buffer const & buffer = *bv_.buffer(); for (pos_type vpos = row_.pos(); vpos < end; ) { if (x_ > bv_.workWidth()) @@ -662,7 +708,7 @@ void RowPainter::paintText() // Use font span to speed things up, see above if (vpos < font_span.first || vpos > font_span.last) { font_span = par_.fontSpan(vpos); - font = text_.getFont(par_, vpos); + font = text_.getFont(buffer, par_, vpos); } const int width_pos = @@ -836,12 +882,17 @@ void paintPar text); // If this is the only object on the row, we can make it wide + // + // FIXME: there is a const_cast here because paintPar() is not supposed + // to touch the paragraph contents. So either we move this "wide" + // property out of InsetText or we localize the feature to the painting + // done here. for (pos_type i = rit->pos() ; i != rit->endpos(); ++i) { InsetBase const * const in = par.getInset(i); if (in) { - InsetText const * const t = in->asTextInset(); + InsetText * t = const_cast(in->asTextInset()); if (t) - t->Wide() = in_inset_alone_on_row; + t->setWide(in_inset_alone_on_row); } } @@ -851,9 +902,11 @@ void paintPar if (repaintAll || row_has_changed || cursor_on_row) { // Add to row signature cache par.rowSignature()[rowno] = row_sig; - + bool const inside = (y + rit->descent() >= 0 - && y - rit->ascent() < ww); + && y - rit->ascent() < ww); + // it is not needed to draw on screen if we are not inside. + pi.pain.setDrawingEnabled(inside); RowPainter rp(pi, text, pit, *rit, x, y); // Clear background of this row // (if paragraph background was not cleared) @@ -870,12 +923,14 @@ void paintPar // Instrumentation for testing row cache (see also // 12 lines lower): - if (text.isMainText()) - lyxerr[Debug::PAINTING] << "#"; - else - lyxerr[Debug::PAINTING] << "[" << - repaintAll << row_has_changed << - cursor_on_row << "]"; + if (lyxerr.debugging(Debug::PAINTING)) { + if (text.isMainText(*pi.base.bv->buffer())) + lyxerr[Debug::PAINTING] << "#"; + else + lyxerr[Debug::PAINTING] << "[" << + repaintAll << row_has_changed << + cursor_on_row << "]"; + } rp.paintAppendix(); rp.paintDepthBar(); rp.paintChangeBar(); @@ -889,21 +944,26 @@ void paintPar // Restore, see above refreshInside = tmp; } - lyxerr[Debug::PAINTING] << "." << endl; + // Re-enable screen drawing for future use of the painter. + pi.pain.setDrawingEnabled(true); + + if (lyxerr.debugging(Debug::PAINTING)) { + lyxerr[Debug::PAINTING] << "." << endl; + } } } // namespace anon -void paintText(BufferView & bv, ViewMetricsInfo const & vi, +void paintText(BufferView & bv, Painter & pain) { - if (!bv.buffer()) - return; - - LyXText & text = bv.buffer()->text(); + BOOST_ASSERT(bv.buffer()); + Buffer const & buffer = *bv.buffer(); + LyXText & text = buffer.text(); bool const select = bv.cursor().selection(); - + ViewMetricsInfo const & vi = bv.viewMetricsInfo(); + PainterInfo pi(const_cast(&bv), pain); // Should the whole screen, including insets, be refreshed? bool repaintAll = select || !vi.singlepar; @@ -932,13 +992,13 @@ void paintText(BufferView & bv, ViewMetricsInfo const & vi, // Try viewing the User Guide Mobius figure if (vi.p1 > 0) { - text.redoParagraph(vi.p1 - 1); + text.redoParagraph(bv, vi.p1 - 1); bv.coordCache().parPos()[&text][vi.p1 - 1] = Point(0, vi.y1 - text.getPar(vi.p1 - 1).descent()); } if (vi.p2 < pit_type(text.paragraphs().size()) - 1) { - text.redoParagraph(vi.p2 + 1); + text.redoParagraph(bv, vi.p2 + 1); bv.coordCache().parPos()[&text][vi.p2 + 1] = Point(0, vi.y2 + text.getPar(vi.p2 + 1).ascent()); }