Cleanup Painter text() API

* remove optional arguments to the helpers that use a FontInfo
* add a textwidth argument to the text() methods that are used by rowpainter.

Now textwidth is only computed if a null value was passed to the
text() method. This means that in the use case of rowpainter, no
textwidth needs to be computed.
This commit is contained in:
Jean-Marc Lasgouttes 2016-03-20 20:02:05 +01:00
parent 333f6fcf07
commit 598f7e4a45
5 changed files with 67 additions and 40 deletions

View File

@ -60,6 +60,7 @@ cursor.
* Proposals * Proposals
* Clean-up of drawing code * Clean-up of drawing code
The goal is to make painting with drawing disable fast enough that it The goal is to make painting with drawing disable fast enough that it
@ -81,7 +82,7 @@ paintInset needs to be called.
The only thing we want to do here is to set inset positions (for The only thing we want to do here is to set inset positions (for
text). The other insets still use the painter with drawing disabled. text). The other insets still use the painter with drawing disabled.
** Painter::text ** DONE Painter::text
We cannot remove (or make private) the version that uses a We cannot remove (or make private) the version that uses a
FontInfo because it is used by PainterInfo::draw. Document this and FontInfo because it is used by PainterInfo::draw. Document this and
@ -99,6 +100,26 @@ version.
==> more versions, no optional parameters. ==> more versions, no optional parameters.
** make Inset::display() more useful
Extending the DisplayType enum would allow to remove special cases
from the code.
The enumeration could be like
: Inline = 0
: BreakBefore = 1 // break row before this inset
: BreakAfter = 2 // break row after this inset
: CanBreakAfter = 4 // optionally break row after this inset
: AlignLeft = 8
: AlignRight = 16
: NoBoundary = 32 // do not allow cursor to go at the end of the row
: //before display inset
: Display = BreakBefore|BreakAfter
A display equation would be Display, other could be Display|AlignLeft
BreakAfter can be used by Newline or separator insets
CanBreakAfter can be used by the optional hyphen InsetSpecialChar.
** Set inset position during metrics phase ** Set inset position during metrics phase
In order to do that, a no-paint drawing will be initiated after every In order to do that, a no-paint drawing will be initiated after every

View File

@ -246,13 +246,14 @@ void RowPainter::paintStringAndSel(Row::Element const & e)
Color const col = e.change.changed() ? e.change.color() Color const col = e.change.changed() ? e.change.color()
: Color_selectiontext; : Color_selectiontext;
copy.fontInfo().setPaintColor(col); copy.fontInfo().setPaintColor(col);
pi_.pain.text(int(x_), yo_, e.str, copy, e.extra); pi_.pain.text(int(x_), yo_, e.str, copy, e.extra, e.full_width());
} else if (!some_sel) { } else if (!some_sel) {
pi_.pain.text(int(x_), yo_, e.str, e.font, e.extra); pi_.pain.text(int(x_), yo_, e.str, e.font, e.extra, e.full_width());
} else { } else {
pi_.pain.text(int(x_), yo_, e.str, e.font, Color_selectiontext, pi_.pain.text(int(x_), yo_, e.str, e.font, Color_selectiontext,
max(row_.sel_beg, e.pos) - e.pos, max(row_.sel_beg, e.pos) - e.pos,
min(row_.sel_end, e.endpos) - e.pos, e.extra); min(row_.sel_end, e.endpos) - e.pos,
e.extra, e.full_width());
} }
x_ += e.full_width(); x_ += e.full_width();
} }

View File

@ -133,21 +133,17 @@ public:
virtual void image(int x, int y, int w, int h, virtual void image(int x, int y, int w, int h,
graphics::Image const & image) = 0; graphics::Image const & image) = 0;
/** draw a character at position x, y (y is the baseline) /// draw a string at position x, y (y is the baseline).
*/ virtual void text(int x, int y, docstring const & str, FontInfo const & f) = 0;
virtual void text(int x, int y, char_type c, FontInfo const & f) = 0;
/** draw a string at position x, y (y is the baseline). The /// draw a char at position x, y (y is the baseline)
* text direction is given by \c rtl. virtual void text(int x, int y, char_type c, FontInfo const & f) = 0;
*/
virtual void text(int x, int y, docstring const & str, FontInfo const & f,
bool rtl = false, double wordspacing = 0.0) = 0;
/** draw a string at position x, y (y is the baseline). The /** draw a string at position x, y (y is the baseline). The
* text direction is enforced by the \c Font. * text direction is enforced by the \c Font.
*/ */
virtual void text(int x, int y, docstring const & str, Font const & f, virtual void text(int x, int y, docstring const & str, Font const & f,
double wordspacing = 0.0) = 0; double wordspacing, double textwidth) = 0;
/** draw a string at position x, y (y is the baseline), but /** draw a string at position x, y (y is the baseline), but
* make sure that the part between \c from and \c to is in * make sure that the part between \c from and \c to is in
@ -155,7 +151,7 @@ public:
*/ */
virtual void text(int x, int y, docstring const & str, Font const & f, virtual void text(int x, int y, docstring const & str, Font const & f,
Color other, size_type from, size_type to, Color other, size_type from, size_type to,
double const wordspacing) = 0; double wordspacing, double textwidth) = 0;
void setDrawingEnabled(bool drawing_enabled) void setDrawingEnabled(bool drawing_enabled)
{ drawing_enabled_ = drawing_enabled; } { drawing_enabled_ = drawing_enabled; }

View File

@ -333,6 +333,12 @@ void GuiPainter::text(int x, int y, char_type c, FontInfo const & f)
} }
void GuiPainter::text(int x, int y, docstring const & s, FontInfo const & f)
{
text(x, y, s, f, false, 0.0, 0.0);
}
void GuiPainter::do_drawText(int x, int y, QString str, bool rtl, FontInfo const & f, QFont ff) void GuiPainter::do_drawText(int x, int y, QString str, bool rtl, FontInfo const & f, QFont ff)
{ {
setQPainterPen(computeColor(f.realColor())); setQPainterPen(computeColor(f.realColor()));
@ -370,7 +376,7 @@ void GuiPainter::do_drawText(int x, int y, QString str, bool rtl, FontInfo const
void GuiPainter::text(int x, int y, docstring const & s, void GuiPainter::text(int x, int y, docstring const & s,
FontInfo const & f, bool const rtl, FontInfo const & f, bool const rtl,
double const wordspacing) double const wordspacing, double const tw)
{ {
//LYXERR0("text: x=" << x << ", s=" << s); //LYXERR0("text: x=" << x << ", s=" << s);
if (s.empty() || !isDrawingEnabled()) if (s.empty() || !isDrawingEnabled())
@ -382,8 +388,8 @@ void GuiPainter::text(int x, int y, docstring const & s,
of the symbol in the font (as given in lib/symbols) as a char_type to the of the symbol in the font (as given in lib/symbols) as a char_type to the
frontend. This is just wrong, because the symbol is no UCS4 character at frontend. This is just wrong, because the symbol is no UCS4 character at
all. You can think of this number as the code point of the symbol in a all. You can think of this number as the code point of the symbol in a
custom symbol encoding. It works because this char_type is lateron again custom symbol encoding. It works because this char_type is later on again
interpreted as a position in the font again. interpreted as a position in the font.
The correct solution would be to have extra functions for symbols, but that The correct solution would be to have extra functions for symbols, but that
would require to duplicate a lot of frontend and mathed support code. would require to duplicate a lot of frontend and mathed support code.
*/ */
@ -400,11 +406,12 @@ void GuiPainter::text(int x, int y, docstring const & s,
ff.setWordSpacing(wordspacing); ff.setWordSpacing(wordspacing);
GuiFontMetrics const & fm = getFontMetrics(f); GuiFontMetrics const & fm = getFontMetrics(f);
// Here we use the font width cache instead of int textwidth = 0;
// textwidth = fontMetrics().width(str); if (tw == 0.0)
// because the above is awfully expensive on MacOSX // Note that we have to take in account space stretching (word spacing)
// Note that we have to take in account space stretching (word spacing) textwidth = fm.width(s) + count(s.begin(), s.end(), ' ') * wordspacing;
int const textwidth = fm.width(s) + count(s.begin(), s.end(), ' ') * wordspacing; else
textwidth = static_cast<int>(tw);
textDecoration(f, x, y, textwidth); textDecoration(f, x, y, textwidth);
@ -464,15 +471,15 @@ void GuiPainter::text(int x, int y, docstring const & s,
void GuiPainter::text(int x, int y, docstring const & str, Font const & f, void GuiPainter::text(int x, int y, docstring const & str, Font const & f,
double const wordspacing) double const wordspacing, double const tw)
{ {
text(x, y, str, f.fontInfo(), f.isVisibleRightToLeft(), wordspacing); text(x, y, str, f.fontInfo(), f.isVisibleRightToLeft(), wordspacing, tw);
} }
void GuiPainter::text(int x, int y, docstring const & str, Font const & f, void GuiPainter::text(int x, int y, docstring const & str, Font const & f,
Color other, size_type const from, size_type const to, Color other, size_type const from, size_type const to,
double const wordspacing) double const wordspacing, double const tw)
{ {
GuiFontMetrics const & fm = getFontMetrics(f.fontInfo()); GuiFontMetrics const & fm = getFontMetrics(f.fontInfo());
FontInfo fi = f.fontInfo(); FontInfo fi = f.fontInfo();
@ -491,7 +498,7 @@ void GuiPainter::text(int x, int y, docstring const & str, Font const & f,
fi.setPaintColor(other); fi.setPaintColor(other);
QRegion const clip(x + xmin, y - ascent, xmax - xmin, height); QRegion const clip(x + xmin, y - ascent, xmax - xmin, height);
setClipRegion(clip); setClipRegion(clip);
text(x, y, str, fi, rtl, wordspacing); text(x, y, str, fi, rtl, wordspacing, tw);
// Then the part in normal color // Then the part in normal color
// Note that in Qt5, it is not possible to use Qt::UniteClip, // Note that in Qt5, it is not possible to use Qt::UniteClip,
@ -499,7 +506,7 @@ void GuiPainter::text(int x, int y, docstring const & str, Font const & f,
fi.setPaintColor(orig); fi.setPaintColor(orig);
QRegion region(viewport()); QRegion region(viewport());
setClipRegion(region - clip); setClipRegion(region - clip);
text(x, y, str, fi, rtl, wordspacing); text(x, y, str, fi, rtl, wordspacing, tw);
setClipping(false); setClipping(false);
} }

View File

@ -105,17 +105,17 @@ public:
virtual void image(int x, int y, int w, int h, virtual void image(int x, int y, int w, int h,
lyx::graphics::Image const & image); lyx::graphics::Image const & image);
/** draw a string at position x, y (y is the baseline). The /// draw a string at position x, y (y is the baseline).
* text direction is given by \c rtl. virtual void text(int x, int y, docstring const & str, FontInfo const & f);
*/
virtual void text(int x, int y, docstring const & str, FontInfo const & f, /// draw a char at position x, y (y is the baseline)
bool rtl = false, double wordspacing = 0.0); virtual void text(int x, int y, char_type c, FontInfo const & f);
/** draw a string at position x, y (y is the baseline). The /** draw a string at position x, y (y is the baseline). The
* text direction is enforced by the \c Font. * text direction is enforced by the \c Font.
*/ */
virtual void text(int x, int y, docstring const & str, Font const & f, virtual void text(int x, int y, docstring const & str, Font const & f,
double wordspacing = 0.0); double wordspacing, double textwidth);
/** draw a string at position x, y (y is the baseline), but /** draw a string at position x, y (y is the baseline), but
* make sure that the part between \c from and \c to is in * make sure that the part between \c from and \c to is in
@ -123,10 +123,7 @@ public:
*/ */
virtual void text(int x, int y, docstring const & str, Font const & f, virtual void text(int x, int y, docstring const & str, Font const & f,
Color other, size_type from, size_type to, Color other, size_type from, size_type to,
double const wordspacing); double wordspacing, double textwidth);
/// draw a char at position x, y (y is the baseline)
virtual void text(int x, int y, char_type c, FontInfo const & f);
/// ///
virtual void textDecoration(FontInfo const & f, int x, int y, int width); virtual void textDecoration(FontInfo const & f, int x, int y, int width);
@ -136,11 +133,11 @@ public:
FontInfo const & font, bool mouseHover); FontInfo const & font, bool mouseHover);
/// start monochrome painting mode, i.e. map every color into [min,max] /// start monochrome painting mode, i.e. map every color into [min,max]
virtual void enterMonochromeMode(Color const & min, virtual void enterMonochromeMode(Color const & min,
Color const & max); Color const & max);
/// leave monochrome painting mode /// leave monochrome painting mode
virtual void leaveMonochromeMode(); virtual void leaveMonochromeMode();
/** /**
* Draw a string and enclose it inside a rectangle. If * Draw a string and enclose it inside a rectangle. If
* back color is specified, the background is cleared with * back color is specified, the background is cleared with
@ -186,6 +183,11 @@ private:
// Helper for text() method // Helper for text() method
void do_drawText(int x, int y, QString str, bool rtl, FontInfo const & f, QFont ff); void do_drawText(int x, int y, QString str, bool rtl, FontInfo const & f, QFont ff);
// Real text() method
void text(int x, int y, docstring const & s,
FontInfo const & f, bool const rtl,
double const wordspacing, double tw);
QColor current_color_; QColor current_color_;
Painter::line_style current_ls_; Painter::line_style current_ls_;
int current_lw_; int current_lw_;