* Text: Move some more stuff from Text to TextMetrics:

- getFont() becomes TextMetrics::getDisplayFont()
- setCharFont() now needs a display font.
- setInsetFont() and setFont() now needs a BufferView, will be transferred to TextMetrics too.
- isRTL(): moved to TextMetrics
- isRTLBoundary(): ditto
- font_: ditto

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@20014 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Abdelrazak Younes 2007-09-02 21:48:49 +00:00
parent 80a05b1eb5
commit d35d25460b
13 changed files with 238 additions and 222 deletions

View File

@ -1459,9 +1459,10 @@ Font Cursor::getFont() const
// on space? Take the font before (only for RTL boundary stay) // on space? Take the font before (only for RTL boundary stay)
if (pos > 0) { if (pos > 0) {
TextMetrics const & tm = bv().textMetrics(&text);
if (pos == sl.lastpos() if (pos == sl.lastpos()
|| (par.isSeparator(pos) && || (par.isSeparator(pos) &&
!text.isRTLBoundary(buffer(), par, pos))) !tm.isRTLBoundary(par, pos)))
--pos; --pos;
} }
@ -1509,6 +1510,7 @@ void Cursor::setCurrentFont()
pos_type cpos = pos(); pos_type cpos = pos();
Paragraph & par = paragraph(); Paragraph & par = paragraph();
Text const & ctext = *text(); Text const & ctext = *text();
TextMetrics const & tm = bv().textMetrics(&ctext);
// are we behind previous char in fact? -> go to that char // are we behind previous char in fact? -> go to that char
if (cpos > 0 && boundary()) if (cpos > 0 && boundary())
@ -1524,7 +1526,7 @@ void Cursor::setCurrentFont()
// abc| def -> font of c // abc| def -> font of c
// abc |[WERBEH], i.e. boundary==true -> font of c // abc |[WERBEH], i.e. boundary==true -> font of c
// abc [WERBEH]| def, font of the space // abc [WERBEH]| def, font of the space
if (!ctext.isRTLBoundary(buffer(), par, cpos)) if (!tm.isRTLBoundary(par, cpos))
--cpos; --cpos;
} }
} }
@ -1532,11 +1534,11 @@ void Cursor::setCurrentFont()
// get font // get font
BufferParams const & bufparams = buffer().params(); BufferParams const & bufparams = buffer().params();
current_font = par.getFontSettings(bufparams, cpos); current_font = par.getFontSettings(bufparams, cpos);
real_current_font = ctext.getFont(buffer(), par, cpos); real_current_font = tm.getDisplayFont(par, cpos);
// special case for paragraph end // special case for paragraph end
if (pos() == lastpos() if (pos() == lastpos()
&& ctext.isRTLBoundary(buffer(), par, pos()) && tm.isRTLBoundary(par, pos())
&& !boundary()) { && !boundary()) {
Language const * lang = par.getParLanguage(bufparams); Language const * lang = par.getParLanguage(bufparams);
current_font.setLanguage(lang); current_font.setLanguage(lang);

View File

@ -14,18 +14,17 @@
#include "FontIterator.h" #include "FontIterator.h"
#include "Buffer.h" #include "TextMetrics.h"
#include "Text.h"
#include "Paragraph.h" #include "Paragraph.h"
namespace lyx { namespace lyx {
FontIterator::FontIterator(Buffer const & buffer, Text const & text, FontIterator::FontIterator(TextMetrics const & tm,
Paragraph const & par, pos_type pos) Paragraph const & par, pos_type pos)
: buffer_(buffer), text_(text), par_(par), pos_(pos), : tm_(tm), par_(par), pos_(pos),
font_(text.getFont(buffer, par, pos)), font_(tm.getDisplayFont(par, pos)),
endspan_(par.fontSpan(pos).last), endspan_(par.fontSpan(pos).last),
bodypos_(par.beginOfBody()) bodypos_(par.beginOfBody())
{} {}
@ -47,7 +46,7 @@ FontIterator & FontIterator::operator++()
{ {
++pos_; ++pos_;
if (pos_ > endspan_ || pos_ == bodypos_) { if (pos_ > endspan_ || pos_ == bodypos_) {
font_ = text_.getFont(buffer_, par_, pos_); font_ = tm_.getDisplayFont(par_, pos_);
endspan_ = par_.fontSpan(pos_).last; endspan_ = par_.fontSpan(pos_).last;
} }
return *this; return *this;

View File

@ -27,16 +27,15 @@
namespace lyx { namespace lyx {
class Buffer;
class Text;
class Paragraph; class Paragraph;
class TextMetrics;
class FontIterator : std::iterator<std::forward_iterator_tag, Font> class FontIterator : std::iterator<std::forward_iterator_tag, Font>
{ {
public: public:
/// ///
FontIterator(Buffer const & buffer, Text const & text, FontIterator(TextMetrics const & tm,
Paragraph const & par, pos_type pos); Paragraph const & par, pos_type pos);
/// ///
Font const & operator*() const; Font const & operator*() const;
@ -47,9 +46,7 @@ public:
private: private:
/// ///
Buffer const & buffer_; TextMetrics const & tm_;
///
Text const & text_;
/// ///
Paragraph const & par_; Paragraph const & par_;
/// ///

View File

@ -440,6 +440,7 @@ void Text::insertChar(Cursor & cur, char_type c)
recordUndo(cur, Undo::INSERT); recordUndo(cur, Undo::INSERT);
TextMetrics const & tm = cur.bv().textMetrics(this);
Buffer const & buffer = cur.buffer(); Buffer const & buffer = cur.buffer();
Paragraph & par = cur.paragraph(); Paragraph & par = cur.paragraph();
// try to remove this // try to remove this
@ -458,8 +459,8 @@ void Text::insertChar(Cursor & cur, char_type c)
!(contains(number_seperators, c) && !(contains(number_seperators, c) &&
cur.pos() != 0 && cur.pos() != 0 &&
cur.pos() != cur.lastpos() && cur.pos() != cur.lastpos() &&
getFont(buffer, par, cur.pos()).number() == Font::ON && tm.getDisplayFont(par, cur.pos()).number() == Font::ON &&
getFont(buffer, par, cur.pos() - 1).number() == Font::ON) tm.getDisplayFont(par, cur.pos() - 1).number() == Font::ON)
) )
number(cur); // Set current_font.number to OFF number(cur); // Set current_font.number to OFF
} else if (isDigit(c) && } else if (isDigit(c) &&
@ -473,11 +474,13 @@ void Text::insertChar(Cursor & cur, char_type c)
|| par.isSeparator(cur.pos() - 2) || par.isSeparator(cur.pos() - 2)
|| par.isNewline(cur.pos() - 2)) || par.isNewline(cur.pos() - 2))
) { ) {
setCharFont(buffer, pit, cur.pos() - 1, cur.current_font); setCharFont(buffer, pit, cur.pos() - 1, cur.current_font,
tm.font_);
} else if (contains(number_seperators, c) } else if (contains(number_seperators, c)
&& cur.pos() >= 2 && cur.pos() >= 2
&& getFont(buffer, par, cur.pos() - 2).number() == Font::ON) { && tm.getDisplayFont(par, cur.pos() - 2).number() == Font::ON) {
setCharFont(buffer, pit, cur.pos() - 1, cur.current_font); setCharFont(buffer, pit, cur.pos() - 1, cur.current_font,
tm.font_);
} }
} }
} }
@ -508,7 +511,7 @@ void Text::insertChar(Cursor & cur, char_type c)
if ((cur.pos() >= 2) && (par.isLineSeparator(cur.pos() - 1))) { if ((cur.pos() >= 2) && (par.isLineSeparator(cur.pos() - 1))) {
// get font in front and behind the space in question. But do NOT // get font in front and behind the space in question. But do NOT
// use getFont(cur.pos()) because the character c is not inserted yet // use getFont(cur.pos()) because the character c is not inserted yet
Font const & pre_space_font = getFont(buffer, par, cur.pos() - 2); Font const & pre_space_font = tm.getDisplayFont(par, cur.pos() - 2);
Font const & post_space_font = cur.real_current_font; Font const & post_space_font = cur.real_current_font;
bool pre_space_rtl = pre_space_font.isVisibleRightToLeft(); bool pre_space_rtl = pre_space_font.isVisibleRightToLeft();
bool post_space_rtl = post_space_font.isVisibleRightToLeft(); bool post_space_rtl = post_space_font.isVisibleRightToLeft();
@ -521,7 +524,7 @@ void Text::insertChar(Cursor & cur, char_type c)
(pre_space_rtl == par.isRightToLeftPar(buffer.params())) ? (pre_space_rtl == par.isRightToLeftPar(buffer.params())) ?
pre_space_font.language() : post_space_font.language(); pre_space_font.language() : post_space_font.language();
Font space_font = getFont(buffer, par, cur.pos() - 1); Font space_font = tm.getDisplayFont(par, cur.pos() - 1);
space_font.setLanguage(lang); space_font.setLanguage(lang);
par.setFont(cur.pos() - 1, space_font); par.setFont(cur.pos() - 1, space_font);
} }

View File

@ -52,11 +52,6 @@ public:
// count as empty. // count as empty.
bool empty() const; bool empty() const;
///
Font getFont(Buffer const & buffer, Paragraph const & par,
pos_type pos) const;
///
void applyOuterFont(Buffer const & buffer, Font &) const;
/// ///
Font getLayoutFont(Buffer const & buffer, pit_type pit) const; Font getLayoutFont(Buffer const & buffer, pit_type pit) const;
/// ///
@ -67,7 +62,7 @@ public:
* and the inset is not allowed inside a font change (see below). * and the inset is not allowed inside a font change (see below).
*/ */
void setCharFont(Buffer const & buffer, pit_type pit, pos_type pos, void setCharFont(Buffer const & buffer, pit_type pit, pos_type pos,
Font const & font); Font const & font, Font const & display_font);
/** Needed to propagate font changes to all text cells of insets /** Needed to propagate font changes to all text cells of insets
* that are not allowed inside a font change (bug 1973). * that are not allowed inside a font change (bug 1973).
@ -76,7 +71,7 @@ public:
* FIXME: This should be removed, see documentation of noFontChange * FIXME: This should be removed, see documentation of noFontChange
* in insetbase.h * in insetbase.h
*/ */
void setInsetFont(Buffer const & buffer, pit_type pit, pos_type pos, void setInsetFont(BufferView const & bv, pit_type pit, pos_type pos,
Font const & font, bool toggleall = false); Font const & font, bool toggleall = false);
/// what you expect when pressing \<enter\> at cursor position /// what you expect when pressing \<enter\> at cursor position
@ -106,7 +101,7 @@ public:
/// FIXME: replace Cursor with DocIterator. /// FIXME: replace Cursor with DocIterator.
void setFont(Cursor & cur, Font const &, bool toggleall = false); void setFont(Cursor & cur, Font const &, bool toggleall = false);
/// Set font from \p begin to \p end and rebreak. /// Set font from \p begin to \p end and rebreak.
void setFont(Buffer const & buffer, CursorSlice const & begin, void setFont(BufferView const & bv, CursorSlice const & begin,
CursorSlice const & end, Font const &, CursorSlice const & end, Font const &,
bool toggleall = false); bool toggleall = false);
@ -257,14 +252,6 @@ public:
docstring getPossibleLabel(Cursor & cur) const; docstring getPossibleLabel(Cursor & cur) const;
/// is this paragraph right-to-left? /// is this paragraph right-to-left?
bool isRTL(Buffer const &, Paragraph const & par) const; bool isRTL(Buffer const &, Paragraph const & par) const;
/// is this position in the paragraph right-to-left?
bool isRTL(Buffer const & buffer, CursorSlice const & sl, bool boundary) const;
/// is between pos-1 and pos an RTL<->LTR boundary?
bool isRTLBoundary(Buffer const & buffer, Paragraph const & par,
pos_type pos) const;
/// would be a RTL<->LTR boundary between pos and the given font?
bool isRTLBoundary(Buffer const & buffer, Paragraph const & par,
pos_type pos, Font const & font) const;
/// ///
bool checkAndActivateInset(Cursor & cur, bool front); bool checkAndActivateInset(Cursor & cur, bool front);
@ -289,14 +276,6 @@ public:
/// ///
ParagraphList pars_; ParagraphList pars_;
/// FIXME: this font_ member has nothing to do here!
/// It is used in applyOuterFont() and setCharFont() for reasons
/// that are not clear... to hand hand the outermost language and
/// also for char style apparently.
/// our 'outermost' font. This is handed down from the surrounding
/// inset through the pi/mi parameter (pi.base.font)
Font font_;
/// ///
bool autoBreakRows_; bool autoBreakRows_;
private: private:

View File

@ -81,92 +81,6 @@ bool Text::isMainText(Buffer const & buffer) const
} }
// Gets the fully instantiated font at a given position in a paragraph
// Basically the same routine as Paragraph::getFont() in Paragraph.cpp.
// The difference is that this one is used for displaying, and thus we
// are allowed to make cosmetic improvements. For instance make footnotes
// smaller. (Asger)
Font Text::getFont(Buffer const & buffer, Paragraph const & par,
pos_type const pos) const
{
BOOST_ASSERT(pos >= 0);
LayoutPtr const & layout = par.layout();
// FIXME: broken?
BufferParams const & params = buffer.params();
pos_type const body_pos = par.beginOfBody();
// We specialize the 95% common case:
if (!par.getDepth()) {
Font f = par.getFontSettings(params, pos);
if (!isMainText(buffer))
applyOuterFont(buffer, f);
Font lf;
Font rlf;
if (layout->labeltype == LABEL_MANUAL && pos < body_pos) {
lf = layout->labelfont;
rlf = layout->reslabelfont;
} else {
lf = layout->font;
rlf = layout->resfont;
}
// In case the default family has been customized
if (lf.family() == Font::INHERIT_FAMILY)
rlf.setFamily(params.getFont().family());
return f.realize(rlf);
}
// The uncommon case need not be optimized as much
Font layoutfont;
if (pos < body_pos)
layoutfont = layout->labelfont;
else
layoutfont = layout->font;
Font font = par.getFontSettings(params, pos);
font.realize(layoutfont);
if (!isMainText(buffer))
applyOuterFont(buffer, font);
// Find the pit value belonging to paragraph. This will not break
// even if pars_ would not be a vector anymore.
// Performance appears acceptable.
pit_type pit = pars_.size();
for (pit_type it = 0; it < pit; ++it)
if (&pars_[it] == &par) {
pit = it;
break;
}
// Realize against environment font information
// NOTE: the cast to pit_type should be removed when pit_type
// changes to a unsigned integer.
if (pit < pit_type(pars_.size()))
font.realize(outerFont(pit, pars_));
// Realize with the fonts of lesser depth.
font.realize(params.getFont());
return font;
}
// There are currently two font mechanisms in LyX:
// 1. The font attributes in a lyxtext, and
// 2. The inset-specific font properties, defined in an inset's
// metrics() and draw() methods and handed down the inset chain through
// the pi/mi parameters, and stored locally in a lyxtext in font_.
// This is where the two are integrated in the final fully realized
// font.
void Text::applyOuterFont(Buffer const & buffer, Font & font) const {
Font lf(font_);
lf.reduce(buffer.params().getFont());
lf.realize(font);
lf.setLanguage(font.language());
font = lf;
}
Font Text::getLayoutFont(Buffer const & buffer, pit_type const pit) const Font Text::getLayoutFont(Buffer const & buffer, pit_type const pit) const
{ {
LayoutPtr const & layout = pars_[pit].layout(); LayoutPtr const & layout = pars_[pit].layout();
@ -209,7 +123,7 @@ Font Text::getLabelFont(Buffer const & buffer, Paragraph const & par) const
void Text::setCharFont(Buffer const & buffer, pit_type pit, void Text::setCharFont(Buffer const & buffer, pit_type pit,
pos_type pos, Font const & fnt) pos_type pos, Font const & fnt, Font const & display_font)
{ {
Font font = fnt; Font font = fnt;
LayoutPtr const & layout = pars_[pit].layout(); LayoutPtr const & layout = pars_[pit].layout();
@ -237,7 +151,7 @@ void Text::setCharFont(Buffer const & buffer, pit_type pit,
// Inside inset, apply the inset's font attributes if any // Inside inset, apply the inset's font attributes if any
// (charstyle!) // (charstyle!)
if (!isMainText(buffer)) if (!isMainText(buffer))
layoutfont.realize(font_); layoutfont.realize(display_font);
layoutfont.realize(buffer.params().getFont()); layoutfont.realize(buffer.params().getFont());
@ -248,7 +162,7 @@ void Text::setCharFont(Buffer const & buffer, pit_type pit,
} }
void Text::setInsetFont(Buffer const & buffer, pit_type pit, void Text::setInsetFont(BufferView const & bv, pit_type pit,
pos_type pos, Font const & font, bool toggleall) pos_type pos, Font const & font, bool toggleall)
{ {
BOOST_ASSERT(pars_[pit].isInset(pos) && BOOST_ASSERT(pars_[pit].isInset(pos) &&
@ -263,7 +177,7 @@ void Text::setInsetFont(Buffer const & buffer, pit_type pit,
CursorSlice cellend = cs; CursorSlice cellend = cs;
cellend.pit() = cellend.lastpit(); cellend.pit() = cellend.lastpit();
cellend.pos() = cellend.lastpos(); cellend.pos() = cellend.lastpos();
text->setFont(buffer, cs, cellend, font, toggleall); text->setFont(bv, cs, cellend, font, toggleall);
} }
} }
} }
@ -425,15 +339,17 @@ void Text::setFont(Cursor & cur, Font const & font, bool toggleall)
// Ok, we have a selection. // Ok, we have a selection.
recordUndoSelection(cur); recordUndoSelection(cur);
setFont(cur.buffer(), cur.selectionBegin().top(), setFont(cur.bv(), cur.selectionBegin().top(),
cur.selectionEnd().top(), font, toggleall); cur.selectionEnd().top(), font, toggleall);
} }
void Text::setFont(Buffer const & buffer, CursorSlice const & begin, void Text::setFont(BufferView const & bv, CursorSlice const & begin,
CursorSlice const & end, Font const & font, CursorSlice const & end, Font const & font,
bool toggleall) bool toggleall)
{ {
Buffer const & buffer = bv.buffer();
// Don't use forwardChar here as ditend might have // Don't use forwardChar here as ditend might have
// pos() == lastpos() and forwardChar would miss it. // pos() == lastpos() and forwardChar would miss it.
// Can't use forwardPos either as this descends into // Can't use forwardPos either as this descends into
@ -449,10 +365,11 @@ void Text::setFont(Buffer const & buffer, CursorSlice const & begin,
// text cells of the inset (bug 1973). // text cells of the inset (bug 1973).
// FIXME: This should change, see documentation // FIXME: This should change, see documentation
// of noFontChange in Inset.h // of noFontChange in Inset.h
setInsetFont(buffer, pit, pos, font, toggleall); setInsetFont(bv, pit, pos, font, toggleall);
Font f = getFont(buffer, dit.paragraph(), pos); TextMetrics const & tm = bv.textMetrics(this);
Font f = tm.getDisplayFont(dit.paragraph(), pos);
f.update(font, language, toggleall); f.update(font, language, toggleall);
setCharFont(buffer, pit, pos, f); setCharFont(buffer, pit, pos, f, tm.font_);
} }
} }
} }
@ -735,10 +652,10 @@ bool Text::cursorRight(Cursor & cur)
if (checkAndActivateInset(cur, true)) if (checkAndActivateInset(cur, true))
return false; return false;
TextMetrics const & tm = cur.bv().textMetrics(this);
// if left of boundary -> just jump to right side // if left of boundary -> just jump to right side
// but for RTL boundaries don't, because: abc|DDEEFFghi -> abcDDEEF|Fghi // but for RTL boundaries don't, because: abc|DDEEFFghi -> abcDDEEF|Fghi
if (cur.boundary() && if (cur.boundary() && !tm.isRTLBoundary(cur.paragraph(), cur.pos()))
!isRTLBoundary(cur.buffer(), cur.paragraph(), cur.pos()))
return setCursor(cur, cur.pit(), cur.pos(), true, false); return setCursor(cur, cur.pit(), cur.pos(), true, false);
// next position is left of boundary, // next position is left of boundary,
@ -767,7 +684,7 @@ bool Text::cursorRight(Cursor & cur)
// in front of RTL boundary? Stay on this side of the boundary because: // in front of RTL boundary? Stay on this side of the boundary because:
// ab|cDDEEFFghi -> abc|DDEEFFghi // ab|cDDEEFFghi -> abc|DDEEFFghi
if (isRTLBoundary(cur.buffer(), cur.paragraph(), cur.pos() + 1)) if (tm.isRTLBoundary(cur.paragraph(), cur.pos() + 1))
return setCursor(cur, cur.pit(), cur.pos() + 1, true, true); return setCursor(cur, cur.pit(), cur.pos() + 1, true, true);
// move right // move right

View File

@ -103,7 +103,8 @@ namespace {
if (font.language() != ignore_language || if (font.language() != ignore_language ||
font.number() != Font::IGNORE) { font.number() != Font::IGNORE) {
Paragraph & par = cur.paragraph(); Paragraph & par = cur.paragraph();
if (cur.boundary() != text->isRTLBoundary(cur.buffer(), par, TextMetrics const & tm = cur.bv().textMetrics(text);
if (cur.boundary() != tm.isRTLBoundary(par,
cur.pos(), cur.real_current_font)) cur.pos(), cur.real_current_font))
text->setCursor(cur, cur.pit(), cur.pos(), text->setCursor(cur, cur.pit(), cur.pos(),
false, !cur.boundary()); false, !cur.boundary());
@ -251,56 +252,6 @@ bool Text::isRTL(Buffer const & buffer, Paragraph const & par) const
} }
bool Text::isRTL(Buffer const & buffer, CursorSlice const & sl, bool boundary) const
{
if (!lyxrc.rtl_support && !sl.text())
return false;
int correction = 0;
if (boundary && sl.pos() > 0)
correction = -1;
Paragraph const & par = getPar(sl.pit());
return getFont(buffer, par, sl.pos() + correction).isVisibleRightToLeft();
}
bool Text::isRTLBoundary(Buffer const & buffer, Paragraph const & par,
pos_type pos) const
{
if (!lyxrc.rtl_support)
return false;
// no RTL boundary at line start
if (pos == 0)
return false;
bool left = getFont(buffer, par, pos - 1).isVisibleRightToLeft();
bool right;
if (pos == par.size())
right = par.isRightToLeftPar(buffer.params());
else
right = getFont(buffer, par, pos).isVisibleRightToLeft();
return left != right;
}
bool Text::isRTLBoundary(Buffer const & buffer, Paragraph const & par,
pos_type pos, Font const & font) const
{
if (!lyxrc.rtl_support)
return false;
bool left = font.isVisibleRightToLeft();
bool right;
if (pos == par.size())
right = par.isRightToLeftPar(buffer.params());
else
right = getFont(buffer, par, pos).isVisibleRightToLeft();
return left != right;
}
void Text::dispatch(Cursor & cur, FuncRequest & cmd) void Text::dispatch(Cursor & cur, FuncRequest & cmd)
{ {
LYXERR(Debug::ACTION) << "Text::dispatch: cmd: " << cmd << endl; LYXERR(Debug::ACTION) << "Text::dispatch: cmd: " << cmd << endl;

View File

@ -198,6 +198,135 @@ int TextMetrics::rightMargin(pit_type const pit) const
} }
void TextMetrics::applyOuterFont(Font & font) const
{
Font lf(font_);
lf.reduce(bv_->buffer().params().getFont());
lf.realize(font);
lf.setLanguage(font.language());
font = lf;
}
Font TextMetrics::getDisplayFont(Paragraph const & par,
pos_type const pos) const
{
BOOST_ASSERT(pos >= 0);
LayoutPtr const & layout = par.layout();
Buffer const & buffer = bv_->buffer();
// FIXME: broken?
BufferParams const & params = buffer.params();
pos_type const body_pos = par.beginOfBody();
// We specialize the 95% common case:
if (!par.getDepth()) {
Font f = par.getFontSettings(params, pos);
if (!text_->isMainText(buffer))
applyOuterFont(f);
Font lf;
Font rlf;
if (layout->labeltype == LABEL_MANUAL && pos < body_pos) {
lf = layout->labelfont;
rlf = layout->reslabelfont;
} else {
lf = layout->font;
rlf = layout->resfont;
}
// In case the default family has been customized
if (lf.family() == Font::INHERIT_FAMILY)
rlf.setFamily(params.getFont().family());
return f.realize(rlf);
}
// The uncommon case need not be optimized as much
Font layoutfont;
if (pos < body_pos)
layoutfont = layout->labelfont;
else
layoutfont = layout->font;
Font font = par.getFontSettings(params, pos);
font.realize(layoutfont);
if (!text_->isMainText(buffer))
applyOuterFont(font);
// Find the pit value belonging to paragraph. This will not break
// even if pars_ would not be a vector anymore.
// Performance appears acceptable.
ParagraphList const & pars = text_->paragraphs();
pit_type pit = pars.size();
for (pit_type it = 0; it < pit; ++it)
if (&pars[it] == &par) {
pit = it;
break;
}
// Realize against environment font information
// NOTE: the cast to pit_type should be removed when pit_type
// changes to a unsigned integer.
if (pit < pit_type(pars.size()))
font.realize(outerFont(pit, pars));
// Realize with the fonts of lesser depth.
font.realize(params.getFont());
return font;
}
bool TextMetrics::isRTL(CursorSlice const & sl, bool boundary) const
{
if (!lyxrc.rtl_support && !sl.text())
return false;
int correction = 0;
if (boundary && sl.pos() > 0)
correction = -1;
Paragraph const & par = text_->getPar(sl.pit());
return getDisplayFont(par, sl.pos() + correction).isVisibleRightToLeft();
}
bool TextMetrics::isRTLBoundary(Paragraph const & par,
pos_type pos) const
{
if (!lyxrc.rtl_support)
return false;
// no RTL boundary at line start
if (pos == 0)
return false;
bool left = getDisplayFont(par, pos - 1).isVisibleRightToLeft();
bool right;
if (pos == par.size())
right = par.isRightToLeftPar(bv_->buffer().params());
else
right = getDisplayFont(par, pos).isVisibleRightToLeft();
return left != right;
}
bool TextMetrics::isRTLBoundary(Paragraph const & par,
pos_type pos, Font const & font) const
{
if (!lyxrc.rtl_support)
return false;
bool left = font.isVisibleRightToLeft();
bool right;
if (pos == par.size())
right = par.isRightToLeftPar(bv_->buffer().params());
else
right = getDisplayFont(par, pos).isVisibleRightToLeft();
return left != right;
}
bool TextMetrics::redoParagraph(pit_type const pit) bool TextMetrics::redoParagraph(pit_type const pit)
{ {
Paragraph & par = text_->getPar(pit); Paragraph & par = text_->getPar(pit);
@ -243,7 +372,7 @@ bool TextMetrics::redoParagraph(pit_type const pit)
int const w = max_width_ - leftMargin(max_width_, pit, ii->pos) int const w = max_width_ - leftMargin(max_width_, pit, ii->pos)
- right_margin; - right_margin;
Font const & font = ii->inset->noFontChange() ? Font const & font = ii->inset->noFontChange() ?
bufferfont : text_->getFont(buffer, par, ii->pos); bufferfont : getDisplayFont(par, ii->pos);
MetricsInfo mi(bv_, font, w); MetricsInfo mi(bv_, font, w);
changed |= ii->inset->metrics(mi, dim); changed |= ii->inset->metrics(mi, dim);
changed |= (old_dim != dim); changed |= (old_dim != dim);
@ -531,7 +660,7 @@ pit_type TextMetrics::rowBreakPoint(int width, pit_type const pit,
// pixel width since last breakpoint // pixel width since last breakpoint
int chunkwidth = 0; int chunkwidth = 0;
FontIterator fi = FontIterator(buffer, *text_, par, pos); FontIterator fi = FontIterator(*this, par, pos);
pos_type point = end; pos_type point = end;
pos_type i = pos; pos_type i = pos;
for ( ; i < end; ++i, ++fi) { for ( ; i < end; ++i, ++fi) {
@ -622,7 +751,7 @@ int TextMetrics::rowWidth(int right_margin, pit_type const pit,
pos_type i = first; pos_type i = first;
if (i < end) { if (i < end) {
FontIterator fi = FontIterator(buffer, *text_, par, i); FontIterator fi = FontIterator(*this, par, i);
for ( ; i < end; ++i, ++fi) { for ( ; i < end; ++i, ++fi) {
if (body_pos > 0 && i == body_pos) { if (body_pos > 0 && i == body_pos) {
FontMetrics const & fm = theFontMetrics( FontMetrics const & fm = theFontMetrics(
@ -668,7 +797,7 @@ boost::tuple<int, int> TextMetrics::rowHeight(pit_type const pit, pos_type const
// start with so we don't have to do the assignment below too // start with so we don't have to do the assignment below too
// often. // often.
Buffer const & buffer = bv_->buffer(); Buffer const & buffer = bv_->buffer();
Font font = text_->getFont(buffer, par, first); Font font = getDisplayFont(par, first);
Font::FONT_SIZE const tmpsize = font.size(); Font::FONT_SIZE const tmpsize = font.size();
font = text_->getLayoutFont(buffer, pit); font = text_->getLayoutFont(buffer, pit);
Font::FONT_SIZE const size = font.size(); Font::FONT_SIZE const size = font.size();
@ -933,7 +1062,7 @@ pos_type TextMetrics::getColumnNearX(pit_type const pit,
bool const rtl = (bidi.level(c) % 2 == 1); bool const rtl = (bidi.level(c) % 2 == 1);
if (left_side == rtl) { if (left_side == rtl) {
++c; ++c;
boundary = text_->isRTLBoundary(buffer, par, c); boundary = isRTLBoundary(par, c);
} }
} }
@ -1319,7 +1448,7 @@ int TextMetrics::cursorX(CursorSlice const & sl,
// Use font span to speed things up, see above // Use font span to speed things up, see above
if (pos < font_span.first || pos > font_span.last) { if (pos < font_span.first || pos > font_span.last) {
font_span = par.fontSpan(pos); font_span = par.fontSpan(pos);
font = text_->getFont(buffer, par, pos); font = getDisplayFont(par, pos);
} }
x += pm.singleWidth(pos, font); x += pm.singleWidth(pos, font);
@ -1332,7 +1461,7 @@ int TextMetrics::cursorX(CursorSlice const & sl,
// see correction above // see correction above
if (boundary_correction) { if (boundary_correction) {
if (text_->isRTL(buffer, sl, boundary)) if (isRTL(sl, boundary))
x -= singleWidth(pit, ppos); x -= singleWidth(pit, ppos);
else else
x += singleWidth(pit, ppos); x += singleWidth(pit, ppos);
@ -1648,10 +1777,9 @@ int TextMetrics::leftMargin(int max_width,
int TextMetrics::singleWidth(pit_type pit, pos_type pos) const int TextMetrics::singleWidth(pit_type pit, pos_type pos) const
{ {
Buffer const & buffer = bv_->buffer();
ParagraphMetrics const & pm = par_metrics_[pit]; ParagraphMetrics const & pm = par_metrics_[pit];
return pm.singleWidth(pos, text_->getFont(buffer, text_->getPar(pit), pos)); return pm.singleWidth(pos, getDisplayFont(text_->getPar(pit), pos));
} }
@ -1886,7 +2014,7 @@ void TextMetrics::drawRowSelection(PainterInfo & pi, int x, Row const & row,
// but for RTL boundaries don't, because: abc|DDEEFFghi -> abcDDEEF|Fghi // but for RTL boundaries don't, because: abc|DDEEFFghi -> abcDDEEF|Fghi
if (cur.boundary()) { if (cur.boundary()) {
cur.boundary(false); cur.boundary(false);
} else if (text_->isRTLBoundary(buffer, cur.paragraph(), cur.pos() + 1)) { } else if (isRTLBoundary(cur.paragraph(), cur.pos() + 1)) {
// in front of RTL boundary -> Stay on this side of the boundary because: // in front of RTL boundary -> Stay on this side of the boundary because:
// ab|cDDEEFFghi -> abc|DDEEFFghi // ab|cDDEEFFghi -> abc|DDEEFFghi
++cur.pos(); ++cur.pos();

View File

@ -14,6 +14,7 @@
#ifndef TEXT_METRICS_H #ifndef TEXT_METRICS_H
#define TEXT_METRICS_H #define TEXT_METRICS_H
#include "Font.h"
#include "ParagraphMetrics.h" #include "ParagraphMetrics.h"
#include "support/types.h" #include "support/types.h"
@ -48,6 +49,33 @@ public:
/// compute text metrics. /// compute text metrics.
bool metrics(MetricsInfo & mi, Dimension & dim); bool metrics(MetricsInfo & mi, Dimension & dim);
/// Gets the fully instantiated font at a given position in a paragraph
/// Basically the same routine as Paragraph::getFont() in Paragraph.cpp.
/// The difference is that this one is used for displaying, and thus we
/// are allowed to make cosmetic improvements. For instance make footnotes
/// smaller. (Asger)
Font getDisplayFont(Paragraph const & par,
pos_type pos) const;
/// There are currently two font mechanisms in LyX:
/// 1. The font attributes in a lyxtext, and
/// 2. The inset-specific font properties, defined in an inset's
/// metrics() and draw() methods and handed down the inset chain through
/// the pi/mi parameters, and stored locally in a lyxtext in font_.
/// This is where the two are integrated in the final fully realized
/// font.
void applyOuterFont(Font &) const;
/// is this position in the paragraph right-to-left?
bool isRTL(CursorSlice const & sl, bool boundary) const;
/// is between pos-1 and pos an RTL<->LTR boundary?
bool isRTLBoundary(Paragraph const & par,
pos_type pos) const;
/// would be a RTL<->LTR boundary between pos and the given font?
bool isRTLBoundary(Paragraph const & par,
pos_type pos, Font const & font) const;
/// Rebreaks the given paragraph. /// Rebreaks the given paragraph.
/// \retval true if a full screen redraw is needed. /// \retval true if a full screen redraw is needed.
/// \retval false if a single paragraph redraw is enough. /// \retval false if a single paragraph redraw is enough.
@ -227,6 +255,16 @@ private:
/// Paragraph grouped by owning text /// Paragraph grouped by owning text
ParPosCache pars_; ParPosCache pars_;
*/ */
// temporary public:
public:
/// our 'outermost' font.
/// This is handed down from the surrounding
/// inset through the pi/mi parameter (pi.base.font)
/// It is used in applyOuterFont() and setCharFont() for reasons
/// that are not clear... to hand hand the outermost language and
/// also for char style apparently.
Font font_;
}; };
/// return the default height of a row in pixels, considering font zoom /// return the default height of a row in pixels, considering font zoom

View File

@ -175,7 +175,7 @@ Point coordOffset(BufferView const & bv, DocIterator const & dit,
// of xx:yy // of xx:yy
if (sl.text()) { if (sl.text()) {
bool boundary_i = boundary && i + 1 == dit.depth(); bool boundary_i = boundary && i + 1 == dit.depth();
bool rtl = sl.text()->isRTL(bv.buffer(), sl, boundary_i); bool rtl = bv.textMetrics(sl.text()).isRTL(sl, boundary_i);
if (rtl) if (rtl)
x -= lastw; x -= lastw;
} }
@ -211,15 +211,16 @@ Point coordOffset(BufferView const & bv, DocIterator const & dit,
y += pm.rows()[rit].height(); y += pm.rows()[rit].height();
y += pm.rows()[rend].ascent(); y += pm.rows()[rend].ascent();
TextMetrics const & bottom_tm = bv.textMetrics(dit.bottom().text());
// Make relative position from the nested inset now bufferview absolute. // Make relative position from the nested inset now bufferview absolute.
int xx = bv.textMetrics(dit.bottom().text()).cursorX( int xx = bottom_tm.cursorX(dit.bottom(), boundary && dit.depth() == 1);
dit.bottom(), boundary && dit.depth() == 1);
x += xx; x += xx;
// In the RTL case place the nested inset at the left of the cursor in // In the RTL case place the nested inset at the left of the cursor in
// the outer paragraph // the outer paragraph
bool boundary_1 = boundary && 1 == dit.depth(); bool boundary_1 = boundary && 1 == dit.depth();
bool rtl = dit.bottom().text()->isRTL(bv.buffer(), dit.bottom(), boundary_1); bool rtl = bottom_tm.isRTL(dit.bottom(), boundary_1);
if (rtl) if (rtl)
x -= lastw; x -= lastw;

View File

@ -4747,7 +4747,8 @@ bool InsetTabular::insertPlaintextString(BufferView & bv, docstring const & buf,
if (cols < columns) { if (cols < columns) {
shared_ptr<InsetText> inset = loctab->getCellInset(cell); shared_ptr<InsetText> inset = loctab->getCellInset(cell);
Paragraph & par = inset->text_.getPar(0); Paragraph & par = inset->text_.getPar(0);
Font const font = inset->text_.getFont(buffer, par, 0); Font const font = bv.textMetrics(&inset->text_).
getDisplayFont(par, 0);
inset->setText(buf.substr(op, p - op), font, inset->setText(buf.substr(op, p - op), font,
buffer.params().trackChanges); buffer.params().trackChanges);
++cols; ++cols;
@ -4759,7 +4760,8 @@ bool InsetTabular::insertPlaintextString(BufferView & bv, docstring const & buf,
if (cols < columns) { if (cols < columns) {
shared_ptr<InsetText> inset = tabular.getCellInset(cell); shared_ptr<InsetText> inset = tabular.getCellInset(cell);
Paragraph & par = inset->text_.getPar(0); Paragraph & par = inset->text_.getPar(0);
Font const font = inset->text_.getFont(buffer, par, 0); Font const font = bv.textMetrics(&inset->text_).
getDisplayFont(par, 0);
inset->setText(buf.substr(op, p - op), font, inset->setText(buf.substr(op, p - op), font,
buffer.params().trackChanges); buffer.params().trackChanges);
} }
@ -4776,7 +4778,7 @@ bool InsetTabular::insertPlaintextString(BufferView & bv, docstring const & buf,
if (cell < cells && op < len) { if (cell < cells && op < len) {
shared_ptr<InsetText> inset = loctab->getCellInset(cell); shared_ptr<InsetText> inset = loctab->getCellInset(cell);
Paragraph & par = inset->text_.getPar(0); Paragraph & par = inset->text_.getPar(0);
Font const font = inset->text_.getFont(buffer, par, 0); Font const font = bv.textMetrics(&inset->text_).getDisplayFont(par, 0);
inset->setText(buf.substr(op, len - op), font, inset->setText(buf.substr(op, len - op), font,
buffer.params().trackChanges); buffer.params().trackChanges);
} }

View File

@ -165,7 +165,7 @@ bool InsetText::metrics(MetricsInfo & mi, Dimension & dim) const
//lyxerr << "InsetText::metrics: width: " << mi.base.textwidth << endl; //lyxerr << "InsetText::metrics: width: " << mi.base.textwidth << endl;
// Hand font through to contained lyxtext: // Hand font through to contained lyxtext:
text_.font_ = mi.base.font; tm.font_ = mi.base.font;
mi.base.textwidth -= 2 * border_; mi.base.textwidth -= 2 * border_;
tm.metrics(mi, dim); tm.metrics(mi, dim);
mi.base.textwidth += 2 * border_; mi.base.textwidth += 2 * border_;

View File

@ -123,7 +123,7 @@ void RowPainter::paintHfill(pos_type const pos, pos_type const body_pos)
void RowPainter::paintInset(Inset const * inset, pos_type const pos) void RowPainter::paintInset(Inset const * inset, pos_type const pos)
{ {
Font font = text_.getFont(pi_.base.bv->buffer(), par_, pos); Font font = text_metrics_.getDisplayFont(par_, pos);
BOOST_ASSERT(inset); BOOST_ASSERT(inset);
// FIXME: We should always use font, see documentation of // FIXME: We should always use font, see documentation of
@ -194,7 +194,7 @@ void RowPainter::paintHebrewComposeChar(pos_type & vpos, Font const & font)
if (!Encodings::isComposeChar_hebrew(c)) { if (!Encodings::isComposeChar_hebrew(c)) {
if (isPrintableNonspace(c)) { if (isPrintableNonspace(c)) {
int const width2 = pm_.singleWidth(i, int const width2 = pm_.singleWidth(i,
text_.getFont(pi_.base.bv->buffer(), par_, i)); text_metrics_.getDisplayFont(par_, i));
dx = (c == 0x05e8 || // resh dx = (c == 0x05e8 || // resh
c == 0x05d3) // dalet c == 0x05d3) // dalet
? width2 - width ? width2 - width
@ -228,7 +228,7 @@ void RowPainter::paintArabicComposeChar(pos_type & vpos, Font const & font)
if (!Encodings::isComposeChar_arabic(c)) { if (!Encodings::isComposeChar_arabic(c)) {
if (isPrintableNonspace(c)) { if (isPrintableNonspace(c)) {
int const width2 = pm_.singleWidth(i, int const width2 = pm_.singleWidth(i,
text_.getFont(pi_.base.bv->buffer(), par_, i)); text_metrics_.getDisplayFont(par_, i));
dx = (width2 - width) / 2; dx = (width2 - width) / 2;
} }
break; break;
@ -348,7 +348,7 @@ void RowPainter::paintForeignMark(double orig_x, Font const & font, int desc)
void RowPainter::paintFromPos(pos_type & vpos) void RowPainter::paintFromPos(pos_type & vpos)
{ {
pos_type const pos = bidi_.vis2log(vpos); pos_type const pos = bidi_.vis2log(vpos);
Font orig_font = text_.getFont(pi_.base.bv->buffer(), par_, pos); Font orig_font = text_metrics_.getDisplayFont(par_, pos);
double const orig_x = x_; double const orig_x = x_;
// usual characters, no insets // usual characters, no insets
@ -701,7 +701,6 @@ void RowPainter::paintText()
// Use font span to speed things up, see below // Use font span to speed things up, see below
FontSpan font_span; FontSpan font_span;
Font font; Font font;
Buffer const & buffer = pi_.base.bv->buffer();
// If the last logical character is a separator, don't paint it, unless // If the last logical character is a separator, don't paint it, unless
// it's in the last row of a paragraph; see skipped_sep_vpos declaration // it's in the last row of a paragraph; see skipped_sep_vpos declaration
@ -728,7 +727,7 @@ void RowPainter::paintText()
// Use font span to speed things up, see above // Use font span to speed things up, see above
if (vpos < font_span.first || vpos > font_span.last) { if (vpos < font_span.first || vpos > font_span.last) {
font_span = par_.fontSpan(vpos); font_span = par_.fontSpan(vpos);
font = text_.getFont(buffer, par_, vpos); font = text_metrics_.getDisplayFont(par_, vpos);
} }
const int width_pos = pm_.singleWidth(pos, font); const int width_pos = pm_.singleWidth(pos, font);
@ -773,7 +772,7 @@ void RowPainter::paintText()
++vpos; ++vpos;
} else if (par_.isSeparator(pos)) { } else if (par_.isSeparator(pos)) {
Font orig_font = text_.getFont(buffer, par_, pos); Font orig_font = text_metrics_.getDisplayFont(par_, pos);
double const orig_x = x_; double const orig_x = x_;
x_ += width_pos; x_ += width_pos;
if (pos >= body_pos) if (pos >= body_pos)