From d35d25460b57c14e67a26c593881dfff31b35da5 Mon Sep 17 00:00:00 2001 From: Abdelrazak Younes Date: Sun, 2 Sep 2007 21:48:49 +0000 Subject: [PATCH] * 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 --- src/Cursor.cpp | 10 ++- src/FontIterator.cpp | 11 ++- src/FontIterator.h | 9 +-- src/Text.cpp | 17 +++-- src/Text.h | 27 +------ src/Text2.cpp | 115 ++++------------------------ src/Text3.cpp | 53 +------------ src/TextMetrics.cpp | 148 +++++++++++++++++++++++++++++++++--- src/TextMetrics.h | 38 +++++++++ src/bufferview_funcs.cpp | 9 ++- src/insets/InsetTabular.cpp | 8 +- src/insets/InsetText.cpp | 2 +- src/rowpainter.cpp | 13 ++-- 13 files changed, 238 insertions(+), 222 deletions(-) diff --git a/src/Cursor.cpp b/src/Cursor.cpp index 7b4bc6a4e3..363114ef5a 100644 --- a/src/Cursor.cpp +++ b/src/Cursor.cpp @@ -1459,9 +1459,10 @@ Font Cursor::getFont() const // on space? Take the font before (only for RTL boundary stay) if (pos > 0) { + TextMetrics const & tm = bv().textMetrics(&text); if (pos == sl.lastpos() || (par.isSeparator(pos) && - !text.isRTLBoundary(buffer(), par, pos))) + !tm.isRTLBoundary(par, pos))) --pos; } @@ -1509,6 +1510,7 @@ void Cursor::setCurrentFont() pos_type cpos = pos(); Paragraph & par = paragraph(); Text const & ctext = *text(); + TextMetrics const & tm = bv().textMetrics(&ctext); // are we behind previous char in fact? -> go to that char if (cpos > 0 && boundary()) @@ -1524,7 +1526,7 @@ void Cursor::setCurrentFont() // abc| def -> font of c // abc |[WERBEH], i.e. boundary==true -> font of c // abc [WERBEH]| def, font of the space - if (!ctext.isRTLBoundary(buffer(), par, cpos)) + if (!tm.isRTLBoundary(par, cpos)) --cpos; } } @@ -1532,11 +1534,11 @@ void Cursor::setCurrentFont() // get font BufferParams const & bufparams = buffer().params(); 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 if (pos() == lastpos() - && ctext.isRTLBoundary(buffer(), par, pos()) + && tm.isRTLBoundary(par, pos()) && !boundary()) { Language const * lang = par.getParLanguage(bufparams); current_font.setLanguage(lang); diff --git a/src/FontIterator.cpp b/src/FontIterator.cpp index b14e29df2d..116523f430 100644 --- a/src/FontIterator.cpp +++ b/src/FontIterator.cpp @@ -14,18 +14,17 @@ #include "FontIterator.h" -#include "Buffer.h" -#include "Text.h" +#include "TextMetrics.h" #include "Paragraph.h" namespace lyx { -FontIterator::FontIterator(Buffer const & buffer, Text const & text, +FontIterator::FontIterator(TextMetrics const & tm, Paragraph const & par, pos_type pos) - : buffer_(buffer), text_(text), par_(par), pos_(pos), - font_(text.getFont(buffer, par, pos)), + : tm_(tm), par_(par), pos_(pos), + font_(tm.getDisplayFont(par, pos)), endspan_(par.fontSpan(pos).last), bodypos_(par.beginOfBody()) {} @@ -47,7 +46,7 @@ FontIterator & FontIterator::operator++() { ++pos_; if (pos_ > endspan_ || pos_ == bodypos_) { - font_ = text_.getFont(buffer_, par_, pos_); + font_ = tm_.getDisplayFont(par_, pos_); endspan_ = par_.fontSpan(pos_).last; } return *this; diff --git a/src/FontIterator.h b/src/FontIterator.h index 04d05dde7a..b5417877df 100644 --- a/src/FontIterator.h +++ b/src/FontIterator.h @@ -27,16 +27,15 @@ namespace lyx { -class Buffer; -class Text; class Paragraph; +class TextMetrics; class FontIterator : std::iterator { public: /// - FontIterator(Buffer const & buffer, Text const & text, + FontIterator(TextMetrics const & tm, Paragraph const & par, pos_type pos); /// Font const & operator*() const; @@ -47,9 +46,7 @@ public: private: /// - Buffer const & buffer_; - /// - Text const & text_; + TextMetrics const & tm_; /// Paragraph const & par_; /// diff --git a/src/Text.cpp b/src/Text.cpp index 8250030e36..a5103a613b 100644 --- a/src/Text.cpp +++ b/src/Text.cpp @@ -440,6 +440,7 @@ void Text::insertChar(Cursor & cur, char_type c) recordUndo(cur, Undo::INSERT); + TextMetrics const & tm = cur.bv().textMetrics(this); Buffer const & buffer = cur.buffer(); Paragraph & par = cur.paragraph(); // try to remove this @@ -458,8 +459,8 @@ void Text::insertChar(Cursor & cur, char_type c) !(contains(number_seperators, c) && cur.pos() != 0 && cur.pos() != cur.lastpos() && - getFont(buffer, par, cur.pos()).number() == Font::ON && - getFont(buffer, par, cur.pos() - 1).number() == Font::ON) + tm.getDisplayFont(par, cur.pos()).number() == Font::ON && + tm.getDisplayFont(par, cur.pos() - 1).number() == Font::ON) ) number(cur); // Set current_font.number to OFF } else if (isDigit(c) && @@ -473,11 +474,13 @@ void Text::insertChar(Cursor & cur, char_type c) || par.isSeparator(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) && cur.pos() >= 2 - && getFont(buffer, par, cur.pos() - 2).number() == Font::ON) { - setCharFont(buffer, pit, cur.pos() - 1, cur.current_font); + && tm.getDisplayFont(par, cur.pos() - 2).number() == Font::ON) { + 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))) { // 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 - 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; bool pre_space_rtl = pre_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_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); par.setFont(cur.pos() - 1, space_font); } diff --git a/src/Text.h b/src/Text.h index a586998225..ba665b7f3b 100644 --- a/src/Text.h +++ b/src/Text.h @@ -52,11 +52,6 @@ public: // count as empty. 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; /// @@ -67,7 +62,7 @@ public: * and the inset is not allowed inside a font change (see below). */ 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 * that are not allowed inside a font change (bug 1973). @@ -76,7 +71,7 @@ public: * FIXME: This should be removed, see documentation of noFontChange * 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); /// what you expect when pressing \ at cursor position @@ -106,7 +101,7 @@ public: /// FIXME: replace Cursor with DocIterator. void setFont(Cursor & cur, Font const &, bool toggleall = false); /// 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 &, bool toggleall = false); @@ -257,14 +252,6 @@ public: docstring getPossibleLabel(Cursor & cur) const; /// is this paragraph right-to-left? 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); @@ -289,14 +276,6 @@ public: /// 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_; private: diff --git a/src/Text2.cpp b/src/Text2.cpp index 0d4358d8f3..4cac71b487 100644 --- a/src/Text2.cpp +++ b/src/Text2.cpp @@ -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 { 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, - pos_type pos, Font const & fnt) + pos_type pos, Font const & fnt, Font const & display_font) { Font font = fnt; 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 // (charstyle!) if (!isMainText(buffer)) - layoutfont.realize(font_); + layoutfont.realize(display_font); 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) { BOOST_ASSERT(pars_[pit].isInset(pos) && @@ -263,7 +177,7 @@ void Text::setInsetFont(Buffer const & buffer, pit_type pit, CursorSlice cellend = cs; cellend.pit() = cellend.lastpit(); 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. recordUndoSelection(cur); - setFont(cur.buffer(), cur.selectionBegin().top(), + setFont(cur.bv(), cur.selectionBegin().top(), 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, bool toggleall) { + Buffer const & buffer = bv.buffer(); + // Don't use forwardChar here as ditend might have // pos() == lastpos() and forwardChar would miss it. // 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). // FIXME: This should change, see documentation // of noFontChange in Inset.h - setInsetFont(buffer, pit, pos, font, toggleall); - Font f = getFont(buffer, dit.paragraph(), pos); + setInsetFont(bv, pit, pos, font, toggleall); + TextMetrics const & tm = bv.textMetrics(this); + Font f = tm.getDisplayFont(dit.paragraph(), pos); 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)) return false; + TextMetrics const & tm = cur.bv().textMetrics(this); // if left of boundary -> just jump to right side - // but for RTL boundaries don't, because: abc|DDEEFFghi -> abcDDEEF|Fghi - if (cur.boundary() && - !isRTLBoundary(cur.buffer(), cur.paragraph(), cur.pos())) + // but for RTL boundaries don't, because: abc|DDEEFFghi -> abcDDEEF|Fghi + if (cur.boundary() && !tm.isRTLBoundary(cur.paragraph(), cur.pos())) return setCursor(cur, cur.pit(), cur.pos(), true, false); // 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: // 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); // move right diff --git a/src/Text3.cpp b/src/Text3.cpp index 438f059939..e89f81e77a 100644 --- a/src/Text3.cpp +++ b/src/Text3.cpp @@ -103,7 +103,8 @@ namespace { if (font.language() != ignore_language || font.number() != Font::IGNORE) { 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)) text->setCursor(cur, cur.pit(), cur.pos(), 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) { LYXERR(Debug::ACTION) << "Text::dispatch: cmd: " << cmd << endl; diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp index 22d3f4bbcd..2d820c4cae 100644 --- a/src/TextMetrics.cpp +++ b/src/TextMetrics.cpp @@ -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) { 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) - right_margin; Font const & font = ii->inset->noFontChange() ? - bufferfont : text_->getFont(buffer, par, ii->pos); + bufferfont : getDisplayFont(par, ii->pos); MetricsInfo mi(bv_, font, w); changed |= ii->inset->metrics(mi, dim); changed |= (old_dim != dim); @@ -531,7 +660,7 @@ pit_type TextMetrics::rowBreakPoint(int width, pit_type const pit, // pixel width since last breakpoint int chunkwidth = 0; - FontIterator fi = FontIterator(buffer, *text_, par, pos); + FontIterator fi = FontIterator(*this, par, pos); pos_type point = end; pos_type i = pos; for ( ; i < end; ++i, ++fi) { @@ -622,7 +751,7 @@ int TextMetrics::rowWidth(int right_margin, pit_type const pit, pos_type i = first; if (i < end) { - FontIterator fi = FontIterator(buffer, *text_, par, i); + FontIterator fi = FontIterator(*this, par, i); for ( ; i < end; ++i, ++fi) { if (body_pos > 0 && i == body_pos) { FontMetrics const & fm = theFontMetrics( @@ -668,7 +797,7 @@ boost::tuple TextMetrics::rowHeight(pit_type const pit, pos_type const // 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, first); + Font font = getDisplayFont(par, first); Font::FONT_SIZE const tmpsize = font.size(); font = text_->getLayoutFont(buffer, pit); 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); if (left_side == rtl) { ++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 if (pos < font_span.first || pos > font_span.last) { font_span = par.fontSpan(pos); - font = text_->getFont(buffer, par, pos); + font = getDisplayFont(par, pos); } x += pm.singleWidth(pos, font); @@ -1332,7 +1461,7 @@ int TextMetrics::cursorX(CursorSlice const & sl, // see correction above if (boundary_correction) { - if (text_->isRTL(buffer, sl, boundary)) + if (isRTL(sl, boundary)) x -= singleWidth(pit, ppos); else x += singleWidth(pit, ppos); @@ -1648,10 +1777,9 @@ int TextMetrics::leftMargin(int max_width, int TextMetrics::singleWidth(pit_type pit, pos_type pos) const { - Buffer const & buffer = bv_->buffer(); 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 if (cur.boundary()) { 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: // ab|cDDEEFFghi -> abc|DDEEFFghi ++cur.pos(); diff --git a/src/TextMetrics.h b/src/TextMetrics.h index 77f4166f53..556ca64b02 100644 --- a/src/TextMetrics.h +++ b/src/TextMetrics.h @@ -14,6 +14,7 @@ #ifndef TEXT_METRICS_H #define TEXT_METRICS_H +#include "Font.h" #include "ParagraphMetrics.h" #include "support/types.h" @@ -48,6 +49,33 @@ public: /// compute text metrics. 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. /// \retval true if a full screen redraw is needed. /// \retval false if a single paragraph redraw is enough. @@ -227,6 +255,16 @@ private: /// Paragraph grouped by owning text 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 diff --git a/src/bufferview_funcs.cpp b/src/bufferview_funcs.cpp index 437ef71c57..9130ec76e3 100644 --- a/src/bufferview_funcs.cpp +++ b/src/bufferview_funcs.cpp @@ -175,7 +175,7 @@ Point coordOffset(BufferView const & bv, DocIterator const & dit, // of xx:yy if (sl.text()) { 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) x -= lastw; } @@ -211,15 +211,16 @@ Point coordOffset(BufferView const & bv, DocIterator const & dit, y += pm.rows()[rit].height(); y += pm.rows()[rend].ascent(); + TextMetrics const & bottom_tm = bv.textMetrics(dit.bottom().text()); + // Make relative position from the nested inset now bufferview absolute. - int xx = bv.textMetrics(dit.bottom().text()).cursorX( - dit.bottom(), boundary && dit.depth() == 1); + int xx = bottom_tm.cursorX(dit.bottom(), boundary && dit.depth() == 1); x += xx; // In the RTL case place the nested inset at the left of the cursor in // the outer paragraph 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) x -= lastw; diff --git a/src/insets/InsetTabular.cpp b/src/insets/InsetTabular.cpp index 94ee0b130a..815d52826d 100644 --- a/src/insets/InsetTabular.cpp +++ b/src/insets/InsetTabular.cpp @@ -4747,7 +4747,8 @@ bool InsetTabular::insertPlaintextString(BufferView & bv, docstring const & buf, if (cols < columns) { shared_ptr inset = loctab->getCellInset(cell); 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, buffer.params().trackChanges); ++cols; @@ -4759,7 +4760,8 @@ bool InsetTabular::insertPlaintextString(BufferView & bv, docstring const & buf, if (cols < columns) { shared_ptr inset = tabular.getCellInset(cell); 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, buffer.params().trackChanges); } @@ -4776,7 +4778,7 @@ bool InsetTabular::insertPlaintextString(BufferView & bv, docstring const & buf, if (cell < cells && op < len) { shared_ptr inset = loctab->getCellInset(cell); 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, buffer.params().trackChanges); } diff --git a/src/insets/InsetText.cpp b/src/insets/InsetText.cpp index 653029844f..93de904c43 100644 --- a/src/insets/InsetText.cpp +++ b/src/insets/InsetText.cpp @@ -165,7 +165,7 @@ bool InsetText::metrics(MetricsInfo & mi, Dimension & dim) const //lyxerr << "InsetText::metrics: width: " << mi.base.textwidth << endl; // Hand font through to contained lyxtext: - text_.font_ = mi.base.font; + tm.font_ = mi.base.font; mi.base.textwidth -= 2 * border_; tm.metrics(mi, dim); mi.base.textwidth += 2 * border_; diff --git a/src/rowpainter.cpp b/src/rowpainter.cpp index f85af08eef..1c47e6981c 100644 --- a/src/rowpainter.cpp +++ b/src/rowpainter.cpp @@ -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) { - Font font = text_.getFont(pi_.base.bv->buffer(), par_, pos); + Font font = text_metrics_.getDisplayFont(par_, pos); BOOST_ASSERT(inset); // 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 (isPrintableNonspace(c)) { int const width2 = pm_.singleWidth(i, - text_.getFont(pi_.base.bv->buffer(), par_, i)); + text_metrics_.getDisplayFont(par_, i)); dx = (c == 0x05e8 || // resh c == 0x05d3) // dalet ? width2 - width @@ -228,7 +228,7 @@ void RowPainter::paintArabicComposeChar(pos_type & vpos, Font const & font) if (!Encodings::isComposeChar_arabic(c)) { if (isPrintableNonspace(c)) { int const width2 = pm_.singleWidth(i, - text_.getFont(pi_.base.bv->buffer(), par_, i)); + text_metrics_.getDisplayFont(par_, i)); dx = (width2 - width) / 2; } break; @@ -348,7 +348,7 @@ void RowPainter::paintForeignMark(double orig_x, Font const & font, int desc) void RowPainter::paintFromPos(pos_type & 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_; // usual characters, no insets @@ -701,7 +701,6 @@ void RowPainter::paintText() // Use font span to speed things up, see below FontSpan font_span; Font font; - Buffer const & buffer = pi_.base.bv->buffer(); // 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 @@ -728,7 +727,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(buffer, par_, vpos); + font = text_metrics_.getDisplayFont(par_, vpos); } const int width_pos = pm_.singleWidth(pos, font); @@ -773,7 +772,7 @@ void RowPainter::paintText() ++vpos; } 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_; x_ += width_pos; if (pos >= body_pos)