]> git.lyx.org Git - lyx.git/blobdiff - src/TextMetrics.cpp
Merge the Row and RowMetrics class. Those classes were separated in the 1.4 code...
[lyx.git] / src / TextMetrics.cpp
index 925c8039775fcace0183b279901e88066ee88b5f..b0f09deef5affa5cd042646c2b0d508b8a6683f5 100644 (file)
 #include "Buffer.h"
 #include "BufferParams.h"
 #include "BufferView.h"
-#include "paragraph_funcs.h"
-#include "ParIterator.h"
+#include "Color.h"
 #include "CoordCache.h"
 #include "debug.h"
-#include "FuncRequest.h"
 #include "FontIterator.h"
-#include "Color.h"
+#include "FuncRequest.h"
 #include "Length.h"
 #include "LyXRC.h"
-#include "Text.h"
 #include "MetricsInfo.h"
+#include "paragraph_funcs.h"
 #include "ParagraphParameters.h"
+#include "ParIterator.h"
+#include "rowpainter.h"
+#include "Text.h"
 #include "VSpace.h"
 
 #include "frontends/FontMetrics.h"
@@ -184,13 +185,13 @@ int TextMetrics::rightMargin(pit_type const pit) const
 
 bool TextMetrics::redoParagraph(pit_type const pit)
 {
+       Paragraph & par = text_->getPar(pit);
        // IMPORTANT NOTE: We pass 'false' explicitely in order to not call
        // redoParagraph() recursively inside parMetrics.
        Dimension old_dim = parMetrics(pit, false).dim();
        ParagraphMetrics & pm = par_metrics_[pit];
-       // reinitialize paragraph dimension.
-       pm.dim() = Dimension();
-       Paragraph & par = text_->getPar(pit);
+       pm.reset(par);
+
        Buffer & buffer = bv_->buffer();
        main_text_ = (text_ == &buffer.text());
        bool changed = false;
@@ -221,18 +222,17 @@ bool TextMetrics::redoParagraph(pit_type const pit)
        InsetList::const_iterator ii = par.insetlist.begin();
        InsetList::const_iterator iend = par.insetlist.end();
        for (; ii != iend; ++ii) {
+               Dimension old_dim = ii->inset->dimension();
                Dimension dim;
                int const w = max_width_ - text_->leftMargin(buffer, max_width_, pit, ii->pos)
                        - right_margin;
                Font const & font = ii->inset->noFontChange() ?
                        bufferfont : text_->getFont(buffer, par, ii->pos);
                MetricsInfo mi(bv_, font, w);
-               changed |= ii->inset->metrics(mi, dim);
+               ii->inset->metrics(mi, dim);
+               changed |= (old_dim != dim);
        }
 
-       // rebreak the paragraph
-       pm.rows().clear();
-
        par.setBeginOfBody();
        pos_type z = 0;
        // maximum pixel width of a row
@@ -242,6 +242,7 @@ bool TextMetrics::redoParagraph(pit_type const pit)
                rowBreakPoint(width, pit, row);
                setRowWidth(right_margin, pit, row);
                setHeightOfRow(pit, row);
+               computeRowMetrics(pit, row);
                pm.rows().push_back(row);
                pm.dim().wid = std::max(pm.dim().wid, row.width());
                pm.dim().des += row.height();
@@ -255,6 +256,7 @@ bool TextMetrics::redoParagraph(pit_type const pit)
                row.endpos(z);
                setRowWidth(right_margin, pit, row);
                setHeightOfRow(pit, row);
+               computeRowMetrics(pit, row);
                pm.rows().push_back(row);
                pm.dim().des += row.height();
        }
@@ -271,10 +273,9 @@ bool TextMetrics::redoParagraph(pit_type const pit)
        return changed;
 }
 
-RowMetrics TextMetrics::computeRowMetrics(pit_type const pit,
-               Row const & row) const
+void TextMetrics::computeRowMetrics(pit_type const pit,
+               Row & row) const
 {
-       RowMetrics result;
        Buffer & buffer = bv_->buffer();
        Paragraph const & par = text_->getPar(pit);
 
@@ -282,9 +283,9 @@ RowMetrics TextMetrics::computeRowMetrics(pit_type const pit,
 
        bool const is_rtl = text_->isRTL(buffer, par);
        if (is_rtl)
-               result.x = rightMargin(pit);
+               row.x = rightMargin(pit);
        else
-               result.x = text_->leftMargin(buffer, max_width_, pit, row.pos());
+               row.x = text_->leftMargin(buffer, max_width_, pit, row.pos());
 
        // is there a manual margin with a manual label
        LayoutPtr const & layout = par.layout();
@@ -303,7 +304,7 @@ RowMetrics TextMetrics::computeRowMetrics(pit_type const pit,
                        ++nlh;
 
                if (nlh && !par.getLabelWidthString().empty())
-                       result.label_hfill = labelFill(pit, row) / double(nlh);
+                       row.label_hfill = labelFill(pit, row) / double(nlh);
        }
 
        // are there any hfills in the row?
@@ -311,7 +312,7 @@ RowMetrics TextMetrics::computeRowMetrics(pit_type const pit,
 
        if (nh) {
                if (w > 0)
-                       result.hfill = w / nh;
+                       row.hfill = w / nh;
        // we don't have to look at the alignment if it is ALIGN_LEFT and
        // if the row is already larger then the permitted width as then
        // we force the LEFT_ALIGN'edness!
@@ -362,17 +363,17 @@ RowMetrics TextMetrics::computeRowMetrics(pit_type const pit,
                            && !par.isNewline(row.endpos() - 1)
                            && !disp_inset
                                ) {
-                               result.separator = w / ns;
+                               row.separator = w / ns;
                        } else if (is_rtl) {
-                               result.x += w;
+                               row.x += w;
                        }
                        break;
                }
                case LYX_ALIGN_RIGHT:
-                       result.x += w;
+                       row.x += w;
                        break;
                case LYX_ALIGN_CENTER:
-                       result.x += w / 2;
+                       row.x += w / 2;
                        break;
                }
        }
@@ -384,14 +385,12 @@ RowMetrics TextMetrics::computeRowMetrics(pit_type const pit,
                if (body_pos > 0
                    && (body_pos > end || !par.isLineSeparator(body_pos - 1)))
                {
-                       result.x += theFontMetrics(text_->getLabelFont(buffer, par)).
+                       row.x += theFontMetrics(text_->getLabelFont(buffer, par)).
                                width(layout->labelsep);
                        if (body_pos <= end)
-                               result.x += result.label_hfill;
+                               row.x += row.label_hfill;
                }
        }
-
-       return result;
 }
 
 
@@ -815,7 +814,6 @@ pos_type TextMetrics::getColumnNearX(pit_type const pit,
        /// x Paragraph coordinate is always 0 for main text anyway.
        int const xo = main_text_? 0 : bv_->coordCache().get(text_, pit).x_;
        x -= xo;
-       RowMetrics const r = computeRowMetrics(pit, row);
        Paragraph const & par = text_->getPar(pit);
        Bidi bidi;
        bidi.computeTables(par, buffer, row);
@@ -829,7 +827,7 @@ pos_type TextMetrics::getColumnNearX(pit_type const pit,
 
        pos_type body_pos = par.beginOfBody();
 
-       double tmpx = r.x;
+       double tmpx = row.x;
        double last_tmpx = tmpx;
 
        if (body_pos > 0 &&
@@ -848,7 +846,7 @@ pos_type TextMetrics::getColumnNearX(pit_type const pit,
                if (body_pos > 0 && c == body_pos - 1) {
                        FontMetrics const & fm = theFontMetrics(
                                text_->getLabelFont(buffer, par));
-                       tmpx += r.label_hfill + fm.width(layout->labelsep);
+                       tmpx += row.label_hfill + fm.width(layout->labelsep);
                        if (par.isLineSeparator(body_pos - 1))
                                tmpx -= singleWidth(pit, body_pos - 1);
                }
@@ -856,13 +854,13 @@ pos_type TextMetrics::getColumnNearX(pit_type const pit,
                if (par.hfillExpansion(row, c)) {
                        tmpx += singleWidth(pit, c);
                        if (c >= body_pos)
-                               tmpx += r.hfill;
+                               tmpx += row.hfill;
                        else
-                               tmpx += r.label_hfill;
+                               tmpx += row.label_hfill;
                } else if (par.isSeparator(c)) {
                        tmpx += singleWidth(pit, c);
                        if (c >= body_pos)
-                               tmpx += r.separator;
+                               tmpx += row.separator;
                } else {
                        tmpx += singleWidth(pit, c);
                }
@@ -964,6 +962,110 @@ int TextMetrics::singleWidth(pit_type pit, pos_type pos) const
 }
 
 
+// only used for inset right now. should also be used for main text
+void TextMetrics::draw(PainterInfo & pi, int x, int y) const
+{
+       ParMetricsCache::const_iterator it = par_metrics_.begin();
+       ParMetricsCache::const_iterator const end = par_metrics_.end();
+       y -= it->second.ascent();
+       for (; it != end; ++it) {
+               ParagraphMetrics const & pmi = it->second;
+               y += pmi.ascent();
+               drawParagraph(pi, it->first, x, y, true);
+               y += pmi.descent();
+       }
+}
+
+namespace {
+
+bool CursorOnRow(PainterInfo & pi, pit_type const pit,
+       RowList::const_iterator rit, Text const & text)
+{
+       // Is there a cursor on this row (or inside inset on row)
+       Cursor & cur = pi.base.bv->cursor();
+       for (size_type d = 0; d < cur.depth(); ++d) {
+               CursorSlice const & sl = cur[d];
+               if (sl.text() == &text
+                   && sl.pit() == pit
+                   && sl.pos() >= rit->pos()
+                   && sl.pos() <= rit->endpos())
+                       return true;
+       }
+       return false;
+}
+
+} // namespace anon
+
+
+void TextMetrics::drawParagraph(PainterInfo & pi, pit_type pit, int x, int y,
+        bool repaintAll) const
+{
+//     lyxerr << "  paintPar: pit: " << pit << " at y: " << y << endl;
+       int const ww = bv_->workHeight();
+
+       bv_->coordCache().parPos()[text_][pit] = Point(x, y);
+
+       ParagraphMetrics const & pm = par_metrics_[pit];
+       if (pm.rows().empty())
+               return;
+
+       RowList::const_iterator const rb = pm.rows().begin();
+       RowList::const_iterator const re = pm.rows().end();
+
+       Bidi bidi;
+
+       y -= rb->ascent();
+       size_type rowno = 0;
+       for (RowList::const_iterator rit = rb; rit != re; ++rit, ++rowno) {
+               y += rit->ascent();
+               // Row signature; has row changed since last paint?
+               bool row_has_changed = pm.rowChangeStatus()[rowno];
+
+               bool cursor_on_row = CursorOnRow(pi, pit, rit, *text_);
+
+               // If selection is on, the current row signature differs
+               // from cache, or cursor is inside an inset _on this row_,
+               // then paint the row
+               if (repaintAll || row_has_changed || cursor_on_row) {
+                       bool const inside = (y + rit->descent() >= 0
+                               && 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, bidi, x, y);
+                       // Clear background of this row
+                       // (if paragraph background was not cleared)
+                       if (!repaintAll && row_has_changed)
+                               pi.pain.fillRectangle(x, y - rit->ascent(),
+                                       width(), rit->height(),
+                                       text_->backgroundColor());
+
+                       // Instrumentation for testing row cache (see also
+                       // 12 lines lower):
+                       if (lyxerr.debugging(Debug::PAINTING)) {
+                               if (text_->isMainText(bv_->buffer()))
+                                       LYXERR(Debug::PAINTING) << "#";
+                               else
+                                       LYXERR(Debug::PAINTING) << "[" <<
+                                               repaintAll << row_has_changed <<
+                                               cursor_on_row << "]";
+                       }
+                       rp.paintAppendix();
+                       rp.paintDepthBar();
+                       rp.paintChangeBar();
+                       if (rit == rb)
+                               rp.paintFirst();
+                       rp.paintText();
+                       if (rit + 1 == re)
+                               rp.paintLast();
+               }
+               y += rit->descent();
+       }
+       // Re-enable screen drawing for future use of the painter.
+       pi.pain.setDrawingEnabled(true);
+
+       LYXERR(Debug::PAINTING) << "." << endl;
+}
+
 //int Text::pos2x(pit_type pit, pos_type pos) const
 //{
 //     ParagraphMetrics const & pm = par_metrics_[pit];