]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiPainter.cpp
On-screen justification: stretch in proportion with the em, up to a limit
[lyx.git] / src / frontends / qt4 / GuiPainter.cpp
1 /**
2  * \file GuiPainter.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author John Levon
7  * \author Abdelrazak Younes
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include "GuiPainter.h"
15
16 #include "ColorCache.h"
17 #include "GuiApplication.h"
18 #include "GuiFontLoader.h"
19 #include "GuiFontMetrics.h"
20 #include "GuiImage.h"
21 #include "qt_helpers.h"
22
23 #include "Font.h"
24 #include "Language.h"
25 #include "LyXRC.h"
26
27 #include "insets/Inset.h"
28
29 #include "support/lassert.h"
30 #include "support/debug.h"
31
32 #include <algorithm>
33
34 #include <QPixmapCache>
35 #include <QTextLayout>
36
37 // Set USE_PIXMAP_CACHE to 1 for enabling the use of a Pixmap cache when
38 // drawing text. This is especially useful for older PPC/Mac systems.
39 #if defined(Q_WS_X11) || defined(QPA_XCB)
40 #define USE_PIXMAP_CACHE 0
41 #else
42 #define USE_PIXMAP_CACHE 1
43 #endif
44
45 using namespace std;
46 using namespace lyx::support;
47
48 namespace lyx {
49 namespace frontend {
50
51 const int Painter::thin_line = 1;
52
53 GuiPainter::GuiPainter(QPaintDevice * device, double pixel_ratio)
54         : QPainter(device), Painter(pixel_ratio),
55           use_pixmap_cache_(lyxrc.use_pixmap_cache && USE_PIXMAP_CACHE)
56 {
57         // new QPainter has default QPen:
58         current_color_ = guiApp->colorCache().get(Color_black);
59         current_ls_ = line_solid;
60         current_lw_ = thin_line;
61 }
62
63
64 GuiPainter::~GuiPainter()
65 {
66         QPainter::end();
67         //lyxerr << "GuiPainter::end()" << endl;
68 }
69
70
71 void GuiPainter::setQPainterPen(QColor const & col,
72         Painter::line_style ls, int lw)
73 {
74         if (col == current_color_ && ls == current_ls_ && lw == current_lw_)
75                 return;
76
77         current_color_ = col;
78         current_ls_ = ls;
79         current_lw_ = lw;
80
81         QPen pen = QPainter::pen();
82         pen.setColor(col);
83
84         switch (ls) {
85         case line_solid:
86         case line_solid_aliased:
87                 pen.setStyle(Qt::SolidLine); break;
88         case line_onoffdash:
89                 pen.setStyle(Qt::DotLine); break;
90         }
91
92         pen.setWidth(lw);
93
94         setPen(pen);
95 }
96
97
98 QString GuiPainter::generateStringSignature(QString const & str,
99                                             FontInfo const & f,
100                                             double wordspacing)
101 {
102         QString sig = str;
103         sig.append(QChar(static_cast<short>(f.family())));
104         sig.append(QChar(static_cast<short>(f.series())));
105         sig.append(QChar(static_cast<short>(f.realShape())));
106         sig.append(QChar(static_cast<short>(f.size())));
107         Color const & color = f.realColor();
108         sig.append(QChar(static_cast<short>(color.baseColor)));
109         sig.append(QChar(static_cast<short>(color.mergeColor)));
110         sig.append(QString::number(wordspacing));
111         if (!monochrome_min_.empty()) {
112                 QColor const & min = monochrome_min_.top();
113                 QColor const & max = monochrome_max_.top();
114                 sig.append(QChar(static_cast<short>(min.red())));
115                 sig.append(QChar(static_cast<short>(min.green())));
116                 sig.append(QChar(static_cast<short>(min.blue())));
117                 sig.append(QChar(static_cast<short>(max.red())));
118                 sig.append(QChar(static_cast<short>(max.green())));
119                 sig.append(QChar(static_cast<short>(max.blue())));
120         }
121         return sig;
122 }
123
124
125 QColor GuiPainter::computeColor(Color col)
126 {
127         return filterColor(guiApp->colorCache().get(col));
128 }
129
130
131 QColor GuiPainter::filterColor(QColor const & col)
132 {
133         if (monochrome_min_.empty())
134                 return col;
135
136         // map into [min,max] interval
137         QColor const & min = monochrome_min_.top();
138         QColor const & max = monochrome_max_.top();
139                         
140         qreal v = col.valueF();
141         v *= v; // make it a bit steeper (i.e. darker)
142                 
143         qreal minr, ming, minb;
144         qreal maxr, maxg, maxb;
145         min.getRgbF(&minr, &ming, &minb);
146         max.getRgbF(&maxr, &maxg, &maxb);
147                         
148         QColor c;
149         c.setRgbF(
150                 v * (minr - maxr) + maxr,
151                 v * (ming - maxg) + maxg,
152                 v * (minb - maxb) + maxb);
153         return c;
154 }
155
156
157 void GuiPainter::enterMonochromeMode(Color const & min, Color const & max)
158 {
159         QColor qmin = filterColor(guiApp->colorCache().get(min));
160         QColor qmax = filterColor(guiApp->colorCache().get(max));
161         monochrome_min_.push(qmin);
162         monochrome_max_.push(qmax);
163 }
164
165
166 void GuiPainter::leaveMonochromeMode()
167 {
168         LASSERT(!monochrome_min_.empty(), return);
169         monochrome_min_.pop();
170         monochrome_max_.pop();
171 }
172
173
174 void GuiPainter::point(int x, int y, Color col)
175 {
176         if (!isDrawingEnabled())
177                 return;
178
179         setQPainterPen(computeColor(col));
180         drawPoint(x, y);
181 }
182
183
184 void GuiPainter::line(int x1, int y1, int x2, int y2,
185         Color col,
186         line_style ls,
187         int lw)
188 {
189         if (!isDrawingEnabled())
190                 return;
191
192         setQPainterPen(computeColor(col), ls, lw);
193         bool const do_antialiasing = renderHints() & TextAntialiasing
194                 && x1 != x2 && y1 != y2 && ls != line_solid_aliased;
195         setRenderHint(Antialiasing, do_antialiasing);
196         drawLine(x1, y1, x2, y2);
197         setRenderHint(Antialiasing, false);
198 }
199
200
201 void GuiPainter::lines(int const * xp, int const * yp, int np,
202         Color col,
203         fill_style fs,
204         line_style ls,
205         int lw)
206 {
207         if (!isDrawingEnabled())
208                 return;
209
210         // double the size if needed
211         // FIXME THREAD
212         static QVector<QPoint> points(32);
213         if (np > points.size())
214                 points.resize(2 * np);
215
216         // Note: the proper way to not get blurry vertical and horizontal lines is
217         // to add 0.5 to all coordinates.
218         bool antialias = false;
219         for (int i = 0; i < np; ++i) {
220                 points[i].setX(xp[i]);
221                 points[i].setY(yp[i]);
222                 if (i != 0)
223                         antialias |= xp[i-1] != xp[i] && yp[i-1] != yp[i];
224         }
225         QColor const color = computeColor(col);
226         setQPainterPen(color, ls, lw);
227         bool const text_is_antialiased = renderHints() & TextAntialiasing;
228         setRenderHint(Antialiasing,
229                       antialias && text_is_antialiased && ls != line_solid_aliased);
230         if (fs == fill_none) {
231                 drawPolyline(points.data(), np);
232         } else {
233                 QBrush const oldbrush = brush();
234                 setBrush(QBrush(color));
235                 drawPolygon(points.data(), np, fs == fill_oddeven ?
236                             Qt::OddEvenFill : Qt::WindingFill);
237                 setBrush(oldbrush);
238         }
239         setRenderHint(Antialiasing, false);
240 }
241
242
243 void GuiPainter::path(int const * xp, int const * yp,
244         int const * c1x, int const * c1y,
245         int const * c2x, int const * c2y,
246         int np,
247         Color col,
248         fill_style fs,
249         line_style ls,
250         int lw)
251 {
252         if (!isDrawingEnabled())
253                 return;
254
255         QPainterPath bpath;
256         // This is the starting point, so its control points are meaningless
257         bpath.moveTo(xp[0], yp[0]);
258
259         for (int i = 1; i < np; ++i) {
260                 bool line = c1x[i] == xp[i - 1] && c1y[i] == yp[i - 1] &&
261                             c2x[i] == xp[i] && c2y[i] == yp[i];
262                 if (line)
263                         bpath.lineTo(xp[i], yp[i]);
264                 else
265                         bpath.cubicTo(c1x[i], c1y[i],  c2x[i], c2y[i], xp[i], yp[i]);
266         }
267         QColor const color = computeColor(col);
268         setQPainterPen(color, ls, lw);
269         bool const text_is_antialiased = renderHints() & TextAntialiasing;
270         setRenderHint(Antialiasing, text_is_antialiased && ls != line_solid_aliased);
271         drawPath(bpath);
272         if (fs != fill_none)
273                 fillPath(bpath, QBrush(color));
274         setRenderHint(Antialiasing, false);
275 }
276
277
278 void GuiPainter::rectangle(int x, int y, int w, int h,
279         Color col,
280         line_style ls,
281         int lw)
282 {
283         if (!isDrawingEnabled())
284                 return;
285
286         setQPainterPen(computeColor(col), ls, lw);
287         drawRect(x, y, w, h);
288 }
289
290
291 void GuiPainter::fillRectangle(int x, int y, int w, int h, Color col)
292 {
293         if (!isDrawingEnabled())
294                 return;
295
296         fillRect(x, y, w, h, guiApp->colorCache().get(col));
297 }
298
299
300 void GuiPainter::arc(int x, int y, unsigned int w, unsigned int h,
301         int a1, int a2, Color col)
302 {
303         if (!isDrawingEnabled())
304                 return;
305
306         // LyX usings 1/64ths degree, Qt usings 1/16th
307         setQPainterPen(computeColor(col));
308         bool const do_antialiasing = renderHints() & TextAntialiasing;
309         setRenderHint(Antialiasing, do_antialiasing);
310         drawArc(x, y, w, h, a1 / 4, a2 / 4);
311         setRenderHint(Antialiasing, false);
312 }
313
314
315 void GuiPainter::image(int x, int y, int w, int h, graphics::Image const & i)
316 {
317         graphics::GuiImage const & qlimage =
318                 static_cast<graphics::GuiImage const &>(i);
319
320         fillRectangle(x, y, w, h, Color_graphicsbg);
321
322         if (!isDrawingEnabled())
323                 return;
324
325         QImage const image = qlimage.image();
326         QRectF const drect = QRectF(x, y, w, h);
327         QRectF const srect = QRectF(0, 0, image.width(), image.height());
328         // Bilinear filtering is needed on a rare occasion for instant previews when
329         // the user's configuration mixes low-dpi and high-dpi monitors (#10114).
330         // This filter is optimised by qt on pixel-aligned images, so this does not
331         // affect performances in other cases.
332         setRenderHint(SmoothPixmapTransform);
333         drawImage(drect, image, srect);
334         setRenderHint(SmoothPixmapTransform, false);
335 }
336
337
338 void GuiPainter::text(int x, int y, char_type c, FontInfo const & f)
339 {
340         text(x, y, docstring(1, c), f);
341 }
342
343
344 void GuiPainter::text(int x, int y, docstring const & s, FontInfo const & f)
345 {
346         text(x, y, s, f, Auto, 0.0, 0.0);
347 }
348
349
350 void GuiPainter::do_drawText(int x, int y, QString str,
351                              GuiPainter::Direction const dir,
352                              FontInfo const & f, QFont ff)
353 {
354         setQPainterPen(computeColor(f.realColor()));
355         if (font() != ff)
356                 setFont(ff);
357
358          /* In LyX, the character direction is forced by the language.
359           * Therefore, we have to signal that fact to Qt.
360           */
361 #if 1
362         /* Use unicode override characters to enforce drawing direction
363          * Source: http://www.iamcal.com/understanding-bidirectional-text/
364          */
365         if (dir == RtL)
366                 // Right-to-left override: forces to draw text right-to-left
367                 str = QChar(0x202E) + str;
368         else if (dir == LtR)
369                 // Left-to-right override: forces to draw text left-to-right
370                 str =  QChar(0x202D) + str;
371         drawText(x, y, str);
372 #else
373         /* This looks like a cleaner solution, but it has drawbacks
374          * - does not work reliably (Mac OS X, ...)
375          * - it is not really documented
376          * Keep it here for now, in case it can be helpful
377          */
378         //This is much stronger than setLayoutDirection.
379         int flag = 0;
380         if (dir == RtL)
381                 flag = Qt::TextForceRightToLeft;
382         else if (dir == LtR)
383                 flag = Qt::TextForceLeftToRight;
384         drawText(x + ((dir == RtL) ? textwidth : 0), y - fm.maxAscent(), 0, 0,
385                  flag | Qt::TextDontClip,
386                  str);
387 #endif
388 }
389
390
391 void GuiPainter::text(int x, int y, docstring const & s,
392                       FontInfo const & f, Direction const dir,
393                       double const wordspacing, double const tw)
394 {
395         //LYXERR0("text: x=" << x << ", s=" << s);
396         if (s.empty() || !isDrawingEnabled())
397                 return;
398
399         /* Caution: The following ucs4 to QString conversions work for symbol fonts
400         only because they are no real conversions but simple casts in reality.
401         When we want to draw a symbol or calculate the metrics we pass the position
402         of the symbol in the font (as given in lib/symbols) as a char_type to the
403         frontend. This is just wrong, because the symbol is no UCS4 character at
404         all. You can think of this number as the code point of the symbol in a
405         custom symbol encoding. It works because this char_type is later on again
406         interpreted as a position in the font.
407         The correct solution would be to have extra functions for symbols, but that
408         would require to duplicate a lot of frontend and mathed support code.
409         */
410         QString str = toqstr(s);
411
412 #if 0
413         // HACK: QT3 refuses to show single compose characters
414         //       Still needed with Qt4?
415         if (ls == 1 && str[0].unicode() >= 0x05b0 && str[0].unicode() <= 0x05c2)
416                 str = ' ' + str;
417 #endif
418
419         QFont ff = getFont(f);
420         ff.setWordSpacing(wordspacing);
421         GuiFontMetrics const & fm = getFontMetrics(f);
422
423         int textwidth = 0;
424         if (tw == 0.0)
425                 // Note that we have to take in account space stretching (word spacing)
426                 textwidth = fm.width(s) +
427                         static_cast<int>(fm.countExpanders(s) * wordspacing);
428         else
429                 textwidth = static_cast<int>(tw);
430
431         textDecoration(f, x, y, textwidth);
432
433         if (use_pixmap_cache_) {
434                 QPixmap pm;
435                 QString key = generateStringSignature(str, f, wordspacing);
436
437                 // Warning: Left bearing is in general negative! Only the case
438                 // where left bearing is negative is of interest WRT the
439                 // pixmap width and the text x-position.
440                 // Only the left bearing of the first character is important
441                 // as we always write from left to right, even for
442                 // right-to-left languages.
443                 // FIXME: this is probably broken for RTL now that we draw full strings.
444                 // Morover the first/last element is possibly not the right one since the glyph may have changed.
445                 int const lb = min(fm.lbearing(s[0]), 0);
446                 int const mA = fm.maxAscent();
447                 if (QPixmapCache::find(key, pm)) {
448                         // Draw the cached pixmap.
449                         drawPixmap(x + lb, y - mA, pm);
450                         return;
451                 }
452
453                 // Only the right bearing of the last character is
454                 // important as we always write from left to right,
455                 // even for right-to-left languages.
456                 int const rb = fm.rbearing(s[s.size()-1]);
457                 int const w = textwidth + rb - lb;
458                 int const mD = fm.maxDescent();
459                 int const h = mA + mD;
460                 if (w > 0 && h > 0) {
461                         pm = QPixmap(static_cast<int>(pixelRatio() * w),
462                                                  static_cast<int>(pixelRatio() * h));
463 #if QT_VERSION >= 0x050000
464                         pm.setDevicePixelRatio(pixelRatio());
465 #endif
466                         pm.fill(Qt::transparent);
467                         GuiPainter p(&pm, pixelRatio());
468                         p.do_drawText(-lb, mA, str, dir, f, ff);
469                         QPixmapCache::insert(key, pm);
470                         //LYXERR(Debug::PAINTING, "h=" << h << "  mA=" << mA << "  mD=" << mD
471                         //      << "  w=" << w << "  lb=" << lb << "  tw=" << textwidth
472                         //      << "  rb=" << rb);
473
474                         // Draw the new cached pixmap.
475                         drawPixmap(x + lb, y - mA, pm);
476                         //rectangle(x-lb, y-mA, w, h, Color_green);
477                 }
478                 return;
479         }
480
481         // don't use the pixmap cache,
482         do_drawText(x, y, str, dir, f, ff);
483         //LYXERR(Debug::PAINTING, "draw " << string(str.toUtf8())
484         //      << " at " << x << "," << y);
485 }
486
487
488 void GuiPainter::text(int x, int y, docstring const & str, Font const & f,
489                       double const wordspacing, double const tw)
490 {
491         text(x, y, str, f.fontInfo(), f.isVisibleRightToLeft() ? RtL : LtR,
492              wordspacing, tw);
493 }
494
495
496 void GuiPainter::text(int x, int y, docstring const & str, Font const & f,
497                       Color other, size_type const from, size_type const to,
498                       double const wordspacing, double const tw)
499 {
500         GuiFontMetrics const & fm = getFontMetrics(f.fontInfo());
501         FontInfo fi = f.fontInfo();
502         Direction const dir = f.isVisibleRightToLeft() ? RtL : LtR;
503
504         // dimensions
505         int const ascent = fm.maxAscent();
506         int const height = fm.maxAscent() + fm.maxDescent();
507         int xmin = fm.pos2x(str, from, dir == RtL, wordspacing);
508         int xmax = fm.pos2x(str, to, dir == RtL, wordspacing);
509         if (xmin > xmax)
510                 swap(xmin, xmax);
511
512         // First the part in other color
513         Color const orig = fi.realColor();
514         fi.setPaintColor(other);
515         QRegion const clip(x + xmin, y - ascent, xmax - xmin, height);
516         setClipRegion(clip);
517         text(x, y, str, fi, dir, wordspacing, tw);
518
519         // Then the part in normal color
520         // Note that in Qt5, it is not possible to use Qt::UniteClip,
521         // therefore QRegion is used.
522         fi.setPaintColor(orig);
523         QRegion region(viewport());
524         setClipRegion(region - clip);
525         text(x, y, str, fi, dir, wordspacing, tw);
526         setClipping(false);
527 }
528
529
530 void GuiPainter::textDecoration(FontInfo const & f, int x, int y, int width)
531 {
532         if (f.underbar() == FONT_ON)
533                 underline(f, x, y, width);
534         if (f.strikeout() == FONT_ON)
535                 strikeoutLine(f, x, y, width);
536         if (f.uuline() == FONT_ON)
537                 doubleUnderline(f, x, y, width);
538         if (f.uwave() == FONT_ON)
539                 // f.color() doesn't work on some circumstances
540                 wavyHorizontalLine(x, y, width,  f.realColor().baseColor);
541 }
542
543
544 static int max(int a, int b) { return a > b ? a : b; }
545
546
547 void GuiPainter::button(int x, int y, int w, int h, bool mouseHover)
548 {
549         if (mouseHover)
550                 fillRectangle(x, y, w, h, Color_buttonhoverbg);
551         else
552                 fillRectangle(x, y, w, h, Color_buttonbg);
553         buttonFrame(x, y, w, h);
554 }
555
556
557 void GuiPainter::buttonFrame(int x, int y, int w, int h)
558 {
559         line(x, y, x, y + h - 1, Color_buttonframe);
560         line(x - 1 + w, y, x - 1 + w, y + h - 1, Color_buttonframe);
561         line(x, y - 1, x - 1 + w, y - 1, Color_buttonframe);
562         line(x, y + h - 1, x - 1 + w, y + h - 1, Color_buttonframe);
563 }
564
565
566 void GuiPainter::rectText(int x, int y, docstring const & str,
567         FontInfo const & font, Color back, Color frame)
568 {
569         int width;
570         int ascent;
571         int descent;
572
573         FontMetrics const & fm = theFontMetrics(font);
574         fm.rectText(str, width, ascent, descent);
575
576         if (back != Color_none)
577                 fillRectangle(x + 1, y - ascent + 1, width - 1,
578                               ascent + descent - 1, back);
579
580         if (frame != Color_none)
581                 rectangle(x, y - ascent, width, ascent + descent, frame);
582
583         text(x + 3, y, str, font);
584 }
585
586
587 void GuiPainter::buttonText(int x, int y, docstring const & str,
588         FontInfo const & font, bool mouseHover)
589 {
590         int width;
591         int ascent;
592         int descent;
593
594         FontMetrics const & fm = theFontMetrics(font);
595         fm.buttonText(str, width, ascent, descent);
596
597         static int const d = Inset::TEXT_TO_INSET_OFFSET / 2;
598
599         button(x + d, y - ascent, width - Inset::TEXT_TO_INSET_OFFSET, descent + ascent, mouseHover);
600         text(x + Inset::TEXT_TO_INSET_OFFSET, y, str, font);
601 }
602
603
604 int GuiPainter::preeditText(int x, int y, char_type c,
605         FontInfo const & font, preedit_style style)
606 {
607         FontInfo temp_font = font;
608         FontMetrics const & fm = theFontMetrics(font);
609         int ascent = fm.maxAscent();
610         int descent = fm.maxDescent();
611         int height = ascent + descent;
612         int width = fm.width(c);
613
614         switch (style) {
615                 case preedit_default:
616                         // default unselecting mode.
617                         fillRectangle(x, y - height + 1, width, height, Color_background);
618                         dashedUnderline(font, x, y - descent + 1, width);
619                         break;
620                 case preedit_selecting:
621                         // We are in selecting mode: white text on black background.
622                         fillRectangle(x, y - height + 1, width, height, Color_black);
623                         temp_font.setColor(Color_white);
624                         break;
625                 case preedit_cursor:
626                         // The character comes with a cursor.
627                         fillRectangle(x, y - height + 1, width, height, Color_background);
628                         underline(font, x, y - descent + 1, width);
629                         break;
630         }
631         text(x, y - descent + 1, c, temp_font);
632
633         return width;
634 }
635
636
637 void GuiPainter::underline(FontInfo const & f, int x, int y, int width,
638                            line_style ls)
639 {
640         FontMetrics const & fm = theFontMetrics(f);
641         int const pos = fm.underlinePos();
642
643         line(x, y + pos, x + width, y + pos,
644              f.realColor(), ls, fm.lineWidth());
645 }
646
647
648 void GuiPainter::strikeoutLine(FontInfo const & f, int x, int y, int width)
649 {
650         FontMetrics const & fm = theFontMetrics(f);
651         int const pos = fm.strikeoutPos();
652
653         line(x, y - pos, x + width, y - pos,
654              f.realColor(), line_solid, fm.lineWidth());
655 }
656
657
658 void GuiPainter::doubleUnderline(FontInfo const & f, int x, int y, int width)
659 {
660         FontMetrics const & fm = theFontMetrics(f);
661         int const pos1 = fm.underlinePos() + fm.lineWidth();
662         int const pos2 = fm.underlinePos() - fm.lineWidth() + 1;
663
664         line(x, y + pos1, x + width, y + pos1,
665                  f.realColor(), line_solid, fm.lineWidth());
666         line(x, y + pos2, x + width, y + pos2,
667                  f.realColor(), line_solid, fm.lineWidth());
668 }
669
670
671 void GuiPainter::dashedUnderline(FontInfo const & f, int x, int y, int width)
672 {
673         FontMetrics const & fm = theFontMetrics(f);
674
675         int const below = max(fm.maxDescent() / 2, 2);
676         int height = max((fm.maxDescent() / 4) - 1, 1);
677
678         if (height >= 2)
679                 height += below;
680
681         for (int n = 0; n != height; ++n)
682                 line(x, y + below + n, x + width, y + below + n, f.realColor(), line_onoffdash);
683 }
684
685
686 void GuiPainter::wavyHorizontalLine(int x, int y, int width, ColorCode col)
687 {
688         setQPainterPen(computeColor(col));
689         int const step = 2;
690         int const xend = x + width;
691         int height = 1;
692         //FIXME: I am not sure if Antialiasing gives the best effect.
693         //setRenderHint(Antialiasing, true);
694         while (x < xend) {
695                 height = - height;
696                 drawLine(x, y - height, x + step, y + height);
697                 x += step;
698                 drawLine(x, y + height, x + step/2, y + height);
699                 x += step/2;
700         }
701         //setRenderHint(Antialiasing, false);
702 }
703
704 } // namespace frontend
705 } // namespace lyx