]> git.lyx.org Git - lyx.git/blobdiff - src/TextMetrics.cpp
Win installer: updates and fixes
[lyx.git] / src / TextMetrics.cpp
index 82b9ebb1609c4f56377bd2ba26e906d83ee00c07..edc9f6919cf188fd288db892985becdb48f337c0 100644 (file)
@@ -48,6 +48,7 @@
 #include "support/convert.h"
 #include "support/debug.h"
 #include "support/lassert.h"
+#include "support/lyxlib.h"
 
 #include <stdlib.h>
 #include <cmath>
@@ -61,6 +62,10 @@ using frontend::FontMetrics;
 
 namespace {
 
+// the somewhat arbitrary leading added between rows. This is 20% of
+// the characters height, inluding the possible leading of the font.
+// 20% is a standard value used by LaTeX and word processors.
+double const extra_leading = 0.2;
 
 int numberOfLabelHfills(Paragraph const & par, Row const & row)
 {
@@ -182,13 +187,21 @@ bool TextMetrics::metrics(MetricsInfo & mi, Dimension & dim, int min_width,
        bool changed = false;
        unsigned int h = 0;
        for (pit_type pit = 0; pit != npar; ++pit) {
-               changed |= redoParagraph(pit);
+               // create rows, but do not set alignment yet
+               changed |= redoParagraph(pit, false);
                ParagraphMetrics const & pm = par_metrics_[pit];
                h += pm.height();
                if (dim_.wid < pm.width())
                        dim_.wid = pm.width();
        }
 
+       // Now set alignment for all rows (the width might not have been known before).
+       for (pit_type pit = 0; pit != npar; ++pit) {
+               ParagraphMetrics & pm = par_metrics_[pit];
+               for (Row & row : pm.rows())
+                       setRowAlignment(row, dim_.wid);
+       }
+
        dim_.asc = par_metrics_[0].ascent();
        dim_.des = h - dim_.asc;
        //lyxerr << "dim_.wid " << dim_.wid << endl;
@@ -354,7 +367,7 @@ bool TextMetrics::isRTLBoundary(pit_type pit, pos_type pos,
 }
 
 
-bool TextMetrics::redoParagraph(pit_type const pit)
+bool TextMetrics::redoParagraph(pit_type const pit, bool const align_rows)
 {
        Paragraph & par = text_->getPar(pit);
        // IMPORTANT NOTE: We pass 'false' explicitly in order to not call
@@ -474,14 +487,14 @@ bool TextMetrics::redoParagraph(pit_type const pit)
                        /* If there is more than one row or the row has been
                         * broken by a display inset or a newline, expand the text
                         * to the full allowable width. This setting here is
-                        * needed for the computeRowMetrics() below.
+                        * needed for the setRowAlignment() below.
                         * We do nothing when inside a table cell.
                         */
                        if (dim_.wid < max_width_)
                                dim_.wid = max_width_;
                }
-               int const max_row_width = max(dim_.wid, row.width());
-               computeRowMetrics(row, max_row_width);
+               if (align_rows)
+                       setRowAlignment(row, max(dim_.wid, row.width()));
                first = row.endpos();
                ++row_index;
 
@@ -588,7 +601,7 @@ LyXAlignment TextMetrics::getAlign(Paragraph const & par, Row const & row) const
 }
 
 
-void TextMetrics::computeRowMetrics(Row & row, int width) const
+void TextMetrics::setRowAlignment(Row & row, int width) const
 {
        row.label_hfill = 0;
        row.separator = 0;
@@ -892,17 +905,8 @@ bool TextMetrics::breakRow(Row & row, int const right_margin) const
                        // ΒΆ U+00B6 PILCROW SIGN
                        char_type const screen_char = (c == 0x2028) ? 0x2936 : 0x00B6;
                        row.add(i, screen_char, *fi, par.lookupChange(i));
-               } else {
-                       // FIXME: please someone fix the Hebrew/Arabic parenthesis mess!
-                       // see also Paragraph::getUChar.
-                       if (fi->language()->lang() == "hebrew") {
-                               if (c == '(')
-                                       c = ')';
-                               else if (c == ')')
-                                       c = '(';
-                       }
+               } else
                        row.add(i, c, *fi, par.lookupChange(i));
-               }
 
                // add inline completion width
                // draw logically behind the previous character
@@ -1089,27 +1093,19 @@ void TextMetrics::setRowHeight(Row & row) const
        // Initial value for ascent (useful if row is empty).
        Font const font = displayFont(row.pit(), row.pos());
        FontMetrics const & fm = theFontMetrics(font);
-       int maxasc = int(fm.maxAscent() * spacing_val);
-       int maxdes = int(fm.maxDescent() * spacing_val);
+       int maxasc = fm.maxAscent() + fm.leading();
+       int maxdes = fm.maxDescent();
 
        // Find the ascent/descent of the row contents
        for (Row::Element const & e : row) {
-               if (e.inset) {
-                       maxasc = max(maxasc, e.dim.ascent());
-                       maxdes = max(maxdes, e.dim.descent());
-               } else {
-                       FontMetrics const & fm2 = theFontMetrics(e.font);
-                       maxasc = max(maxasc, int(fm2.maxAscent() * spacing_val));
-                       maxdes = max(maxdes, int(fm2.maxDescent() * spacing_val));
-               }
+               maxasc = max(maxasc, e.dim.ascent());
+               maxdes = max(maxdes, e.dim.descent());
        }
 
-       // This is nicer with box insets
-       ++maxasc;
-       ++maxdes;
-
-       row.dimension().asc = maxasc;
-       row.dimension().des = maxdes;
+       // Add some leading (split between before and after)
+       int const leading = support::iround(extra_leading * (maxasc + maxdes));
+       row.dimension().asc = int((maxasc + leading - leading / 2) * spacing_val);
+       row.dimension().des = int((maxdes + leading / 2) * spacing_val);
 }
 
 
@@ -1564,7 +1560,7 @@ void TextMetrics::deleteLineForward(Cursor & cur)
                if (!cur.selection())
                        text_->deleteWordForward(cur);
                else
-                       cap::cutSelection(cur, true, false);
+                       cap::cutSelection(cur, false);
                cur.checkBufferStructure();
        }
 }
@@ -1938,15 +1934,11 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type const pit, int const
                rp.paintDepthBar();
                if (row.needsChangeBar())
                        rp.paintChangeBar();
-               if (i == 0 && !row.isRTL())
+               if (i == 0)
                        rp.paintFirst();
-               if (i == nrows - 1 && row.isRTL())
+               if (i == nrows - 1)
                        rp.paintLast();
                rp.paintText();
-               if (i == nrows - 1 && !row.isRTL())
-                       rp.paintLast();
-               if (i == 0 && row.isRTL())
-                       rp.paintFirst();
                rp.paintTooLargeMarks(row_x + row.left_x() < 0,
                                      row_x + row.right_x() > bv_->workWidth());
                y += row.descent();
@@ -2010,7 +2002,8 @@ void TextMetrics::completionPosAndDim(Cursor const & cur, int & x, int & y,
 
 int defaultRowHeight()
 {
-       return int(theFontMetrics(sane_font).maxHeight() *  1.2);
+       FontMetrics const & fm = theFontMetrics(sane_font);
+       return support::iround(fm.maxHeight() * (1 + extra_leading) + fm.leading());
 }
 
 } // namespace lyx