mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-27 03:36:39 +00:00
Transfer ParagraphMetrics::rowChangeStatus() to Row::changed(). Prepare for fine grained row redrawing.
^ Row: - changed_: new boolean to inform change status at draw time. - crc_: new crc_ signature - inline pos() and endpos() - replace width(), ascent() and descent() direct access with dimension(). * ParagraphMetrics - do not maintain row_signature_ anymore - rename calculateRowSignature() to computeRowSignature() and make it public * TextMetrics - redoParagraph(): don't clear the ParagraphMetrics row list, reuse and update it. - rowHeight(), rowWidth(), rowBreakPoint(): take first/end positions instead of Row. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@19895 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
parent
8a947f63da
commit
8175971041
@ -94,7 +94,7 @@ void ParagraphMetrics::reset(Paragraph const & par)
|
||||
}
|
||||
|
||||
|
||||
size_type ParagraphMetrics::calculateRowSignature(Row const & row,
|
||||
void ParagraphMetrics::computeRowSignature(Row & row,
|
||||
BufferParams const & bparams)
|
||||
{
|
||||
boost::crc_32_type crc;
|
||||
@ -107,22 +107,7 @@ size_type ParagraphMetrics::calculateRowSignature(Row const & row,
|
||||
crc.process_bytes(b, 1);
|
||||
}
|
||||
}
|
||||
return crc.checksum();
|
||||
}
|
||||
|
||||
|
||||
void ParagraphMetrics::updateRowChangeStatus(BufferParams const & bparams)
|
||||
{
|
||||
size_t const size = rows_.size();
|
||||
row_change_status_.resize(size);
|
||||
row_signature_.resize(size);
|
||||
|
||||
for (size_t i = 0; i != size; ++i) {
|
||||
// Row signature; has row changed since last update?
|
||||
size_type const row_sig = calculateRowSignature(rows_[i], bparams);
|
||||
row_change_status_[i] = row_signature_[i] != row_sig;
|
||||
row_signature_[i] = row_sig;
|
||||
}
|
||||
row.setCrc(crc.checksum());
|
||||
}
|
||||
|
||||
|
||||
|
@ -40,9 +40,6 @@ public:
|
||||
ParagraphMetrics(Paragraph const & par);
|
||||
|
||||
/// Copy operator.
|
||||
/// Important note: We don't copy \c row_change_status_ and
|
||||
/// \c row_signature_ because those are updated externally with
|
||||
/// \c updateRowChangeStatus() in TextMetrics::redoParagraph().
|
||||
ParagraphMetrics & operator=(ParagraphMetrics const &);
|
||||
|
||||
void reset(Paragraph const & par);
|
||||
@ -69,11 +66,6 @@ public:
|
||||
RowList & rows() { return rows_; }
|
||||
/// The painter and others use this
|
||||
RowList const & rows() const { return rows_; }
|
||||
/// The painter and others use this
|
||||
std::vector<bool> const & rowChangeStatus() const
|
||||
{ return row_change_status_; }
|
||||
///
|
||||
void updateRowChangeStatus(BufferParams const & bparams);
|
||||
///
|
||||
int rightMargin(Buffer const & buffer) const;
|
||||
///
|
||||
@ -81,18 +73,12 @@ public:
|
||||
|
||||
/// dump some information to lyxerr
|
||||
void dump() const;
|
||||
///
|
||||
void computeRowSignature(Row &, BufferParams const & bparams);
|
||||
|
||||
private:
|
||||
///
|
||||
typedef std::vector<size_type> RowSignature;
|
||||
///
|
||||
size_type calculateRowSignature(Row const &, BufferParams const & bparams);
|
||||
///
|
||||
mutable RowList rows_;
|
||||
///
|
||||
RowSignature row_signature_;
|
||||
///
|
||||
std::vector<bool> row_change_status_;
|
||||
/// cached dimensions of paragraph
|
||||
Dimension dim_;
|
||||
///
|
||||
|
34
src/Row.cpp
34
src/Row.cpp
@ -24,39 +24,45 @@ namespace lyx {
|
||||
|
||||
|
||||
Row::Row()
|
||||
: pos_(0), end_(0), separator(0), hfill(0), label_hfill(0), x(0)
|
||||
: changed_(false), crc_(0), pos_(0), end_(0), separator(0), hfill(0),
|
||||
label_hfill(0), x(0)
|
||||
{}
|
||||
|
||||
|
||||
Row::Row(pos_type pos)
|
||||
: pos_(pos), end_(0), separator(0), hfill(0), label_hfill(0), x(0)
|
||||
: changed_(false), crc_(0), pos_(pos), end_(0), separator(0), hfill(0),
|
||||
label_hfill(0), x(0)
|
||||
{}
|
||||
|
||||
|
||||
void Row::setCrc(size_type crc)
|
||||
{
|
||||
changed_ |= crc != crc_;
|
||||
crc_ = crc;
|
||||
}
|
||||
|
||||
|
||||
void Row::setDimension(Dimension const & dim)
|
||||
{
|
||||
changed_ |= dim != dim_;
|
||||
dim_ = dim;
|
||||
}
|
||||
|
||||
|
||||
void Row::pos(pos_type p)
|
||||
{
|
||||
changed_ |= p != pos_;
|
||||
pos_ = p;
|
||||
}
|
||||
|
||||
|
||||
pos_type Row::pos() const
|
||||
{
|
||||
return pos_;
|
||||
}
|
||||
|
||||
|
||||
void Row::endpos(pos_type p)
|
||||
{
|
||||
changed_ |= p != end_;
|
||||
end_ = p;
|
||||
}
|
||||
|
||||
|
||||
pos_type Row::endpos() const
|
||||
{
|
||||
return end_;
|
||||
}
|
||||
|
||||
|
||||
void Row::dump(const char * s) const
|
||||
{
|
||||
lyxerr << s << " pos: " << pos_ << " end: " << end_
|
||||
|
21
src/Row.h
21
src/Row.h
@ -34,29 +34,30 @@ public:
|
||||
///
|
||||
Row(pos_type pos);
|
||||
///
|
||||
bool changed() const { return changed_; }
|
||||
///
|
||||
void setCrc(size_type crc);
|
||||
///
|
||||
void pos(pos_type p);
|
||||
///
|
||||
pos_type pos() const;
|
||||
pos_type pos() const { return pos_; }
|
||||
///
|
||||
void endpos(pos_type p);
|
||||
///
|
||||
pos_type endpos() const;
|
||||
pos_type endpos() const { return end_; }
|
||||
///
|
||||
void setDimension(Dimension const & dim);
|
||||
///
|
||||
Dimension const & dimension() const { return dim_; }
|
||||
///
|
||||
int height() const { return dim_.height(); }
|
||||
///
|
||||
void width(int w) { dim_.wid = w; }
|
||||
///
|
||||
int width() const { return dim_.wid; }
|
||||
///
|
||||
void ascent(int a) { dim_.asc = a; }
|
||||
///
|
||||
int ascent() const { return dim_.asc; }
|
||||
///
|
||||
void descent(int d) { dim_.des = d; }
|
||||
///
|
||||
int descent() const { return dim_.des; }
|
||||
|
||||
/// current debugging only
|
||||
void dump(const char * = "") const;
|
||||
|
||||
@ -70,6 +71,10 @@ public:
|
||||
double x;
|
||||
|
||||
private:
|
||||
/// has the Row appearance changed since last drawing?
|
||||
bool changed_;
|
||||
/// CRC of row contents.
|
||||
size_type crc_;
|
||||
/// first pos covered by this row
|
||||
pos_type pos_;
|
||||
/// one behind last pos covered by this row
|
||||
|
@ -193,6 +193,7 @@ bool TextMetrics::redoParagraph(pit_type const pit)
|
||||
pm.reset(par);
|
||||
|
||||
Buffer & buffer = bv_->buffer();
|
||||
BufferParams const & bparams = buffer.params();
|
||||
main_text_ = (text_ == &buffer.text());
|
||||
bool changed = false;
|
||||
|
||||
@ -234,31 +235,45 @@ bool TextMetrics::redoParagraph(pit_type const pit)
|
||||
}
|
||||
|
||||
par.setBeginOfBody();
|
||||
pos_type z = 0;
|
||||
pos_type first = 0;
|
||||
size_t row_index = 0;
|
||||
// maximum pixel width of a row
|
||||
int width = max_width_ - right_margin; // - leftMargin(buffer, max_width_, pit, row);
|
||||
do {
|
||||
Row row(z);
|
||||
rowBreakPoint(width, pit, row);
|
||||
setRowWidth(right_margin, pit, row);
|
||||
setHeightOfRow(pit, row);
|
||||
Dimension dim;
|
||||
pos_type end = rowBreakPoint(width, pit, first);
|
||||
dim.wid = rowWidth(right_margin, pit, first, end);
|
||||
boost::tie(dim.asc, dim.des) = rowHeight(pit, first, end);
|
||||
if (row_index == pm.rows().size())
|
||||
pm.rows().push_back(Row());
|
||||
Row & row = pm.rows()[row_index];
|
||||
row.pos(first);
|
||||
row.endpos(end);
|
||||
row.setDimension(dim);
|
||||
computeRowMetrics(pit, row);
|
||||
pm.rows().push_back(row);
|
||||
pm.dim().wid = std::max(pm.dim().wid, row.width());
|
||||
pm.dim().des += row.height();
|
||||
z = row.endpos();
|
||||
} while (z < par.size());
|
||||
pm.computeRowSignature(row, bparams);
|
||||
first = end;
|
||||
++row_index;
|
||||
|
||||
pm.dim().wid = std::max(pm.dim().wid, dim.wid);
|
||||
pm.dim().des += dim.height();
|
||||
} while (first < par.size());
|
||||
|
||||
// Make sure that if a par ends in newline, there is one more row
|
||||
// under it
|
||||
if (z > 0 && par.isNewline(z - 1)) {
|
||||
Row row(z);
|
||||
row.endpos(z);
|
||||
setRowWidth(right_margin, pit, row);
|
||||
setHeightOfRow(pit, row);
|
||||
if (first > 0 && par.isNewline(first - 1)) {
|
||||
Dimension dim;
|
||||
dim.wid = rowWidth(right_margin, pit, first, first);
|
||||
boost::tie(dim.asc, dim.des) = rowHeight(pit, first, first);
|
||||
if (row_index == pm.rows().size())
|
||||
pm.rows().push_back(Row());
|
||||
Row & row = pm.rows()[row_index];
|
||||
row.pos(first);
|
||||
row.endpos(first);
|
||||
row.setDimension(dim);
|
||||
computeRowMetrics(pit, row);
|
||||
pm.rows().push_back(row);
|
||||
pm.dim().des += row.height();
|
||||
pm.computeRowSignature(row, bparams);
|
||||
pm.dim().des += dim.height();
|
||||
}
|
||||
|
||||
pm.dim().asc += pm.rows()[0].ascent();
|
||||
@ -266,10 +281,6 @@ bool TextMetrics::redoParagraph(pit_type const pit)
|
||||
|
||||
changed |= old_dim.height() != pm.dim().height();
|
||||
|
||||
// Update the row change statuses. The painter will need that info
|
||||
// in order to know which row has to be repainted.
|
||||
pm.updateRowChangeStatus(bv_->buffer().params());
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
@ -451,30 +462,20 @@ int TextMetrics::labelEnd(pit_type const pit) const
|
||||
}
|
||||
|
||||
|
||||
void TextMetrics::rowBreakPoint(int width, pit_type const pit,
|
||||
Row & row) const
|
||||
pit_type TextMetrics::rowBreakPoint(int width, pit_type const pit,
|
||||
pit_type pos) const
|
||||
{
|
||||
Buffer & buffer = bv_->buffer();
|
||||
ParagraphMetrics const & pm = par_metrics_[pit];
|
||||
Paragraph const & par = text_->getPar(pit);
|
||||
pos_type const end = par.size();
|
||||
pos_type const pos = row.pos();
|
||||
if (pos == end) {
|
||||
row.endpos(end);
|
||||
return;
|
||||
}
|
||||
|
||||
if (width < 0) {
|
||||
row.endpos(end);
|
||||
return;
|
||||
}
|
||||
if (pos == end || width < 0)
|
||||
return end;
|
||||
|
||||
LayoutPtr const & layout = par.layout();
|
||||
|
||||
if (layout->margintype == MARGIN_RIGHT_ADDRESS_BOX) {
|
||||
row.endpos(addressBreakPoint(pos, par));
|
||||
return;
|
||||
}
|
||||
if (layout->margintype == MARGIN_RIGHT_ADDRESS_BOX)
|
||||
return addressBreakPoint(pos, par);
|
||||
|
||||
pos_type const body_pos = par.beginOfBody();
|
||||
|
||||
@ -563,23 +564,22 @@ void TextMetrics::rowBreakPoint(int width, pit_type const pit,
|
||||
if (body_pos && point < body_pos)
|
||||
point = body_pos;
|
||||
|
||||
row.endpos(point);
|
||||
return point;
|
||||
}
|
||||
|
||||
|
||||
void TextMetrics::setRowWidth(int right_margin,
|
||||
pit_type const pit, Row & row) const
|
||||
int TextMetrics::rowWidth(int right_margin, pit_type const pit,
|
||||
pos_type const first, pos_type const end) const
|
||||
{
|
||||
Buffer & buffer = bv_->buffer();
|
||||
// get the pure distance
|
||||
pos_type const end = row.endpos();
|
||||
ParagraphMetrics const & pm = par_metrics_[pit];
|
||||
Paragraph const & par = text_->getPar(pit);
|
||||
int w = text_->leftMargin(buffer, max_width_, pit, row.pos());
|
||||
int w = text_->leftMargin(buffer, max_width_, pit, first);
|
||||
int label_end = labelEnd(pit);
|
||||
|
||||
pos_type const body_pos = par.beginOfBody();
|
||||
pos_type i = row.pos();
|
||||
pos_type i = first;
|
||||
|
||||
if (i < end) {
|
||||
FontIterator fi = FontIterator(buffer, *text_, par, i);
|
||||
@ -605,12 +605,12 @@ void TextMetrics::setRowWidth(int right_margin,
|
||||
w = max(w, label_end);
|
||||
}
|
||||
|
||||
row.width(w + right_margin);
|
||||
return w + right_margin;
|
||||
}
|
||||
|
||||
|
||||
void TextMetrics::setHeightOfRow(pit_type const pit,
|
||||
Row & row)
|
||||
boost::tuple<int, int> TextMetrics::rowHeight(pit_type const pit, pos_type const first,
|
||||
pos_type const end) const
|
||||
{
|
||||
Paragraph const & par = text_->getPar(pit);
|
||||
// get the maximum ascent and the maximum descent
|
||||
@ -628,7 +628,7 @@ void TextMetrics::setHeightOfRow(pit_type const pit,
|
||||
// start with so we don't have to do the assignment below too
|
||||
// often.
|
||||
Buffer const & buffer = bv_->buffer();
|
||||
Font font = text_->getFont(buffer, par, row.pos());
|
||||
Font font = text_->getFont(buffer, par, first);
|
||||
Font::FONT_SIZE const tmpsize = font.size();
|
||||
font = text_->getLayoutFont(buffer, pit);
|
||||
Font::FONT_SIZE const size = font.size();
|
||||
@ -650,7 +650,7 @@ void TextMetrics::setHeightOfRow(pit_type const pit,
|
||||
InsetList::const_iterator ii = par.insetlist.begin();
|
||||
InsetList::const_iterator iend = par.insetlist.end();
|
||||
for ( ; ii != iend; ++ii) {
|
||||
if (ii->pos >= row.pos() && ii->pos < row.endpos()) {
|
||||
if (ii->pos >= first && ii->pos < end) {
|
||||
maxasc = max(maxasc, ii->inset->ascent());
|
||||
maxdesc = max(maxdesc, ii->inset->descent());
|
||||
}
|
||||
@ -660,10 +660,9 @@ void TextMetrics::setHeightOfRow(pit_type const pit,
|
||||
// This is not completely correct, but we can live with the small,
|
||||
// cosmetic error for now.
|
||||
int labeladdon = 0;
|
||||
pos_type const pos_end = row.endpos();
|
||||
|
||||
Font::FONT_SIZE maxsize =
|
||||
par.highestFontInRange(row.pos(), pos_end, size);
|
||||
par.highestFontInRange(first, end, size);
|
||||
if (maxsize > font.size()) {
|
||||
// use standard paragraph font with the maximal size
|
||||
Font maxfont = font;
|
||||
@ -677,11 +676,10 @@ void TextMetrics::setHeightOfRow(pit_type const pit,
|
||||
++maxasc;
|
||||
++maxdesc;
|
||||
|
||||
row.ascent(maxasc);
|
||||
ParagraphList const & pars = text_->paragraphs();
|
||||
|
||||
// is it a top line?
|
||||
if (row.pos() == 0) {
|
||||
if (first == 0) {
|
||||
BufferParams const & bufparams = buffer.params();
|
||||
// some parskips VERY EASY IMPLEMENTATION
|
||||
if (bufparams.paragraph_separation
|
||||
@ -734,7 +732,7 @@ void TextMetrics::setHeightOfRow(pit_type const pit,
|
||||
&& prevpar.getLabelWidthString()
|
||||
== par.getLabelWidthString()) {
|
||||
layoutasc = layout->itemsep * dh;
|
||||
} else if (pit != 0 || row.pos() != 0) {
|
||||
} else if (pit != 0 || first != 0) {
|
||||
if (layout->topsep > 0)
|
||||
layoutasc = layout->topsep * dh;
|
||||
}
|
||||
@ -752,7 +750,7 @@ void TextMetrics::setHeightOfRow(pit_type const pit,
|
||||
}
|
||||
|
||||
// is it a bottom line?
|
||||
if (row.endpos() >= par.size()) {
|
||||
if (end >= par.size()) {
|
||||
// add the layout spaces, for example before and after
|
||||
// a section, or between the items of a itemize or enumerate
|
||||
// environment
|
||||
@ -788,16 +786,15 @@ void TextMetrics::setHeightOfRow(pit_type const pit,
|
||||
// main Text. The following test is thus bogus.
|
||||
// Top and bottom margin of the document (only at top-level)
|
||||
if (main_text_) {
|
||||
if (pit == 0 && row.pos() == 0)
|
||||
if (pit == 0 && first == 0)
|
||||
maxasc += 20;
|
||||
if (pit + 1 == pit_type(pars.size()) &&
|
||||
row.endpos() == par.size() &&
|
||||
!(row.endpos() > 0 && par.isNewline(row.endpos() - 1)))
|
||||
end == par.size() &&
|
||||
!(end > 0 && par.isNewline(end - 1)))
|
||||
maxdesc += 20;
|
||||
}
|
||||
|
||||
row.ascent(maxasc + labeladdon);
|
||||
row.descent(maxdesc);
|
||||
return boost::make_tuple(maxasc + labeladdon, maxdesc);
|
||||
}
|
||||
|
||||
|
||||
@ -997,11 +994,10 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type pit, int x, int y,
|
||||
Bidi bidi;
|
||||
|
||||
y -= rb->ascent();
|
||||
size_type rowno = 0;
|
||||
for (RowList::const_iterator rit = rb; rit != re; ++rit, ++rowno) {
|
||||
for (RowList::const_iterator rit = rb; rit != re; ++rit) {
|
||||
y += rit->ascent();
|
||||
// Row signature; has row changed since last paint?
|
||||
bool row_has_changed = pm.rowChangeStatus()[rowno];
|
||||
bool row_has_changed = rit->changed();
|
||||
|
||||
// Paint the row if a full repaint has been requested or it has
|
||||
// changed.
|
||||
|
@ -18,6 +18,9 @@
|
||||
|
||||
#include "support/types.h"
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
|
||||
#include <map>
|
||||
|
||||
|
||||
@ -91,13 +94,26 @@ private:
|
||||
|
||||
/// sets row.end to the pos value *after* which a row should break.
|
||||
/// for example, the pos after which isNewLine(pos) == true
|
||||
void rowBreakPoint(int width, pit_type const pit, Row & row) const;
|
||||
pit_type rowBreakPoint(
|
||||
int width,
|
||||
pit_type const pit,
|
||||
pit_type first
|
||||
) const;
|
||||
|
||||
/// sets row.width to the minimum space a row needs on the screen in pixel
|
||||
void setRowWidth(int right_margin, pit_type const pit, Row & row) const;
|
||||
int rowWidth(
|
||||
int right_margin,
|
||||
pit_type const pit,
|
||||
pos_type const first,
|
||||
pos_type const end
|
||||
) const;
|
||||
|
||||
/// Calculate and set the height of the row
|
||||
void setHeightOfRow(pit_type, Row & row);
|
||||
boost::tuple<int, int> rowHeight(
|
||||
pit_type const pit,
|
||||
pos_type const first,
|
||||
pos_type const end
|
||||
) const;
|
||||
|
||||
// Temporary public:
|
||||
public:
|
||||
|
Loading…
Reference in New Issue
Block a user