Hi!

For my dynamic macros I need an extension to the Painter for monochrome rendering. This is independent of my other patch, so I post it here first:

Basically all colors are mapped into an interval [min,max] of two colors. By this subformulas can be greyed out easily without touching the inset at all. All the needed logic is in GuiPainter::enterMonochromeMode and GuiPainter::leaveMonochromeMode and the GuiPainter::computeColor/filterColor methods.

Objections? Improvements?

Stefan

=== src/frontends/qt4/GuiPainter.h
==================================================================
--- src/frontends/qt4/GuiPainter.h      (/mirror/lyx)   (revision 15044)
+++ src/frontends/qt4/GuiPainter.h      (/lyx)  (revision 15044)
@@ -18,6 +18,7 @@
 #include "Color.h"

 #include <QPainter>
+#include <stack>

 class QString;

@@ -95,6 +96,12 @@
        /// draw a char at position x, y (y is the baseline)
        virtual int text(int x, int y, char_type c, Font const & f);

+ /// start monochrome painting mode, i.e. map every color into [min,max]
+       virtual void enterMonochromeMode(Color_color const & min,
+               Color_color const & max);
+       /// leave monochrome painting mode
+       virtual void leaveMonochromeMode();
+       
 private:
        /// draw small caps text
        /**
@@ -104,13 +111,23 @@
                QString const & str, Font const & f);

        /// set pen parameters
-       void setQPainterPen(Color_color col,
+       void setQPainterPen(QColor const & col,
                line_style ls = line_solid,
                line_width lw = line_thin);

-       Color::color current_color_;
+       QColor current_color_;
        Painter::line_style current_ls_;
        Painter::line_width current_lw_;
+       ///
+       std::stack<QColor> monochrome_min_;
+       ///
+       std::stack<QColor> monochrome_max_;
+       /// convert into Qt color, possibly applying the monochrome mode
+       QColor computeColor(Color_color col);
+       /// possibly apply monochrome mode
+       QColor filterColor(QColor const & col);
+       ///
+       QString generateStringSignature(QString const & str, Font const & f);   
 };

 } // namespace frontend
=== src/frontends/qt4/GuiPainter.cpp
==================================================================
--- src/frontends/qt4/GuiPainter.cpp    (/mirror/lyx)   (revision 15044)
+++ src/frontends/qt4/GuiPainter.cpp    (/lyx)  (revision 15044)
@@ -47,24 +47,13 @@

 bool const usePixmapCache = USE_PIXMAP_CACHE;

-QString generateStringSignature(QString const & str, Font const & f)
-{
-       QString sig = str;
-       sig.append(QChar(static_cast<short>(f.family())));
-       sig.append(QChar(static_cast<short>(f.series())));
-       sig.append(QChar(static_cast<short>(f.realShape())));
-       sig.append(QChar(static_cast<short>(f.size())));
-       sig.append(QChar(static_cast<short>(f.color())));
-       return sig;
-}
-
 } // anon namespace

 GuiPainter::GuiPainter(QPaintDevice * device)
        : QPainter(device), Painter()
 {
        // new QPainter has default QPen:
-       current_color_ = Color::black;
+       current_color_ = guiApp->colorCache().get(Color::black);
        current_ls_ = line_solid;
        current_lw_ = line_thin;
 }
@@ -77,7 +66,7 @@
 }


-void GuiPainter::setQPainterPen(Color_color col,
+void GuiPainter::setQPainterPen(QColor const & col,
        Painter::line_style ls, Painter::line_width lw)
 {
        if (col == current_color_ && ls == current_ls_ && lw == current_lw_)
@@ -88,9 +77,8 @@
        current_lw_ = lw;

        QPen pen = QPainter::pen();
+       pen.setColor(col);

-       pen.setColor(guiApp->colorCache().get(col));
-
        switch (ls) {
                case line_solid: pen.setStyle(Qt::SolidLine); break;
                case line_onoffdash: pen.setStyle(Qt::DotLine); break;
@@ -105,12 +93,78 @@
 }


+QString GuiPainter::generateStringSignature(QString const & str, Font const & f)
+{
+       QString sig = str;
+       sig.append(QChar(static_cast<short>(f.family())));
+       sig.append(QChar(static_cast<short>(f.series())));
+       sig.append(QChar(static_cast<short>(f.realShape())));
+       sig.append(QChar(static_cast<short>(f.size())));
+       sig.append(QChar(static_cast<short>(f.color())));
+       if (!monochrome_min_.empty()) {
+               QColor const & min = monochrome_min_.top();
+               QColor const & max = monochrome_max_.top();
+               sig.append(QChar(static_cast<short>(min.red())));
+               sig.append(QChar(static_cast<short>(min.green())));
+               sig.append(QChar(static_cast<short>(min.blue())));
+               sig.append(QChar(static_cast<short>(max.red())));
+               sig.append(QChar(static_cast<short>(max.green())));
+               sig.append(QChar(static_cast<short>(max.blue())));
+       }
+       return sig;
+}
+
+
+QColor GuiPainter::computeColor(Color_color col)
+{
+       return filterColor(guiApp->colorCache().get(col));
+}
+
+
+QColor GuiPainter::filterColor(QColor const & col)
+{
+       if (monochrome_min_.empty())
+               return col;
+
+       // map into [min,max] interval
+       QColor const & min = monochrome_min_.top();
+       QColor const & max = monochrome_max_.top();
+                       
+       qreal v = col.valueF();
+       v = v * v; // make it a bit steeper (i.e. darker)
+               
+       qreal minr, ming, minb;
+       qreal maxr, maxg, maxb;
+       min.getRgbF(&minr, &ming, &minb);
+       max.getRgbF(&maxr, &maxg, &maxb);
+                       
+ return QColor(v*minr+(1-v)*maxr, v*ming+(1-v)*maxg, v*minb+(1-v) *maxb);
+}
+
+
+void GuiPainter::enterMonochromeMode(Color_color const & min, Color_color const & max)
+{
+       QColor qmin = filterColor(guiApp->colorCache().get(min));
+       QColor qmax = filterColor(guiApp->colorCache().get(max));
+       monochrome_min_.push(qmin);
+       monochrome_max_.push(qmax);
+}
+
+
+void GuiPainter::leaveMonochromeMode()
+{
+       BOOST_ASSERT(!monochrome_min_.empty());
+       monochrome_min_.pop();
+       monochrome_max_.pop();
+}
+
+
 void GuiPainter::point(int x, int y, Color_color col)
 {
        if (!isDrawingEnabled())
                return;

-       setQPainterPen(col);
+       setQPainterPen(computeColor(col));
        drawPoint(x, y);
 }

@@ -123,7 +177,7 @@
        if (!isDrawingEnabled())
                return;

-       setQPainterPen(col, ls, lw);
+       setQPainterPen(computeColor(col), ls, lw);
        bool const do_antialiasing = renderHints() & TextAntialiasing
                && x1 != x2 && y1 != y2;
        setRenderHint(Antialiasing, do_antialiasing);
@@ -152,7 +206,7 @@
                if (i != 0)
                        antialias |= xp[i-1] != xp[i] && yp[i-1] != yp[i];
        }
-       setQPainterPen(col, ls, lw);
+       setQPainterPen(computeColor(col), ls, lw);
        bool const text_is_antialiased = renderHints() & TextAntialiasing;
        setRenderHint(Antialiasing, antialias && text_is_antialiased);
        drawPolyline(points.data(), np);
@@ -168,7 +222,7 @@
        if (!isDrawingEnabled())
                return;

-       setQPainterPen(col, ls, lw);
+       setQPainterPen(computeColor(col), ls, lw);
        drawRect(x, y, w, h);
 }

@@ -186,7 +240,7 @@
                return;

        // LyX usings 1/64ths degree, Qt usings 1/16th
-       setQPainterPen(col);
+       setQPainterPen(computeColor(col));
        bool const do_antialiasing = renderHints() & TextAntialiasing;
        setRenderHint(Antialiasing, do_antialiasing);
        drawArc(x, y, w, h, a1 / 4, a2 / 4);
@@ -224,7 +278,7 @@
        QFont const & qfont = guiApp->guiFontLoader().get(f);
        QFont const & qsmallfont = guiApp->guiFontLoader().get(smallfont);

-       setQPainterPen(f.realColor());
+       setQPainterPen(computeColor(f.realColor()));
        int textwidth = 0;
        size_t const ls = s.length();
        for (unsigned int i = 0; i < ls; ++i) {
@@ -294,7 +348,7 @@
        // occurs at a line-break. As a kludge, we force Qt to
        // render this glyph using a one-column line.
        if (s.size() == 1 && str[0].unicode() == 0x00ad) {
-               setQPainterPen(f.realColor());
+               setQPainterPen(computeColor(f.realColor()));
                QTextLayout adsymbol(str);
                adsymbol.setFont(fi.font);
                adsymbol.beginLayout();
@@ -309,7 +363,7 @@
        if (!usePixmapCache) {
                // don't use the pixmap cache,
                // draw directly onto the painting device
-               setQPainterPen(f.realColor());
+               setQPainterPen(computeColor(f.realColor()));
                if (font() != fi.font)
                        setFont(fi.font);
                // We need to draw the text as LTR as we use our own bidi code.
@@ -343,7 +397,7 @@
                pm = QPixmap(w, h);
                pm.fill(Qt::transparent);
                GuiPainter p(&pm);
-               p.setQPainterPen(f.realColor());
+               p.setQPainterPen(computeColor(f.realColor()));
                if (p.font() != fi.font)
                        p.setFont(fi.font);
                // We need to draw the text as LTR as we use our own bidi code.
=== src/frontends/Painter.h
==================================================================
--- src/frontends/Painter.h     (/mirror/lyx)   (revision 15044)
+++ src/frontends/Painter.h     (/lyx)  (revision 15044)
@@ -169,6 +169,12 @@
        int preeditText(int x, int y,
                char_type c, Font const & f, preedit_style style);

+ /// start monochrome painting mode, i.e. map every color into [min,max]
+       virtual void enterMonochromeMode(Color_color const & min,
+               Color_color const & max) = 0;
+       /// leave monochrome painting mode
+       virtual void leaveMonochromeMode() = 0;
+
 protected:
        /// check the font, and if set, draw an underline
        void underline(Font const & f,



Attachment: monochrome.patch
Description: Binary data

Attachment: PGP.sig
Description: Signierter Teil der Nachricht

Reply via email to