3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
7 * \author Abdelrazak Younes
9 * Full author contact details are available in file CREDITS.
14 #include <QTextLayout>
16 #include "QLPainter.h"
18 #include "GuiApplication.h"
19 #include "GuiFontMetrics.h"
22 #include "GuiApplication.h"
23 #include "qt_helpers.h"
29 #include "support/unicode.h"
37 QLPainter::QLPainter(QPaintDevice * device)
38 : QPainter(device), Painter()
40 // new QPainter has default QPen:
41 current_color_ = Color::black;
42 current_ls_ = line_solid;
43 current_lw_ = line_thin;
47 QLPainter::~QLPainter()
50 //lyxerr << "QLPainter::end()" << endl;
54 void QLPainter::setQPainterPen(Color_color col,
55 Painter::line_style ls, Painter::line_width lw)
57 if (col == current_color_ && ls == current_ls_ && lw == current_lw_)
64 QPen pen = QPainter::pen();
66 pen.setColor(guiApp->colorCache().get(col));
69 case line_solid: pen.setStyle(Qt::SolidLine); break;
70 case line_onoffdash: pen.setStyle(Qt::DotLine); break;
74 case line_thin: pen.setWidth(0); break;
75 case line_thick: pen.setWidth(3); break;
82 void QLPainter::point(int x, int y, Color_color col)
84 if (!isDrawingEnabled())
92 void QLPainter::line(int x1, int y1, int x2, int y2,
97 if (!isDrawingEnabled())
100 setQPainterPen(col, ls, lw);
101 bool const do_antialiasing = renderHints() & TextAntialiasing
102 && x1 != x2 && y1 != y2;
103 setRenderHint(Antialiasing, do_antialiasing);
104 drawLine(x1, y1, x2, y2);
105 setRenderHint(Antialiasing, false);
109 void QLPainter::lines(int const * xp, int const * yp, int np,
114 if (!isDrawingEnabled())
117 bool const text_is_antialiased = renderHints() & TextAntialiasing;
118 setQPainterPen(col, ls, lw);
119 for (int i = 1; i < np; ++i) {
120 bool const do_antialiasing = text_is_antialiased
121 && xp[i-1] != xp[i] && yp[i-1] != yp[i];
122 setRenderHint(Antialiasing, do_antialiasing);
123 drawLine(xp[i-1], yp[i-1], xp[i], yp[i]);
124 setRenderHint(Antialiasing, false);
129 void QLPainter::rectangle(int x, int y, int w, int h,
134 if (!isDrawingEnabled())
137 setQPainterPen(col, ls, lw);
138 drawRect(x, y, w, h);
142 void QLPainter::fillRectangle(int x, int y, int w, int h, Color_color col)
144 fillRect(x, y, w, h, guiApp->colorCache().get(col));
148 void QLPainter::arc(int x, int y, unsigned int w, unsigned int h,
149 int a1, int a2, Color_color col)
151 if (!isDrawingEnabled())
154 // LyX usings 1/64ths degree, Qt usings 1/16th
156 bool const do_antialiasing = renderHints() & TextAntialiasing;
157 setRenderHint(Antialiasing, do_antialiasing);
158 drawArc(x, y, w, h, a1 / 4, a2 / 4);
159 setRenderHint(Antialiasing, false);
163 void QLPainter::image(int x, int y, int w, int h, graphics::Image const & i)
165 graphics::QLImage const & qlimage =
166 static_cast<graphics::QLImage const &>(i);
168 fillRectangle(x, y, w, h, Color::graphicsbg);
170 if (!isDrawingEnabled())
173 drawImage(x, y, qlimage.qimage(), 0, 0, w, h);
177 int QLPainter::text(int x, int y, char_type c, Font const & f)
180 return text(x, y, s, f);
184 int QLPainter::smallCapsText(int x, int y,
185 QString const & s, Font const & f)
188 smallfont.decSize().decSize().setShape(Font::UP_SHAPE);
190 QFont const & qfont = guiApp->guiFontLoader().get(f);
191 QFont const & qsmallfont = guiApp->guiFontLoader().get(smallfont);
193 setQPainterPen(f.realColor());
195 size_t const ls = s.length();
196 for (unsigned int i = 0; i < ls; ++i) {
197 QChar const c = s[i].toUpper();
203 if (isDrawingEnabled())
204 drawText(x + textwidth, y, c);
205 textwidth += fontMetrics().width(c);
211 int QLPainter::text(int x, int y, docstring const & s,
214 /* Caution: The following ucs4 to QString conversions work for symbol fonts
215 only because they are no real conversions but simple casts in reality.
216 When we want to draw a symbol or calculate the metrics we pass the position
217 of the symbol in the font (as given in lib/symbols) as a char_type to the
218 frontend. This is just wrong, because the symbol is no UCS4 character at
219 all. You can think of this number as the code point of the symbol in a
220 custom symbol encoding. It works because this char_type is lateron again
221 interpreted as a position in the font again.
222 The correct solution would be to have extra functions for symbols, but that
223 would require to duplicate a lot of frontend and mathed support code.
225 QString str = toqstr(s);
228 // HACK: QT3 refuses to show single compose characters
229 // Still needed with Qt4?
230 if (ls == 1 && str[0].unicode() >= 0x05b0 && str[0].unicode() <= 0x05c2)
234 QLFontInfo & fi = guiApp->guiFontLoader().fontinfo(f);
238 if (f.realShape() != Font::SMALLCAPS_SHAPE) {
239 setQPainterPen(f.realColor());
240 if (font() != fi.font)
242 // We need to draw the text as LTR as we use our own bidi code.
243 setLayoutDirection(Qt::LeftToRight);
244 if (isDrawingEnabled()) {
245 LYXERR(Debug::PAINTING) << "draw " << std::string(str.toUtf8())
246 << " at " << x << "," << y << std::endl;
247 // Qt4 does not display a glyph whose codepoint is the
248 // same as that of a soft-hyphen (0x00ad), unless it
249 // occurs at a line-break. As a kludge, we force Qt to
250 // render this glyph using a one-column line.
251 if (s.size() == 1 && str[0].unicode() == 0x00ad) {
252 QTextLayout adsymbol(str);
253 adsymbol.setFont(fi.font);
254 adsymbol.beginLayout();
255 QTextLine line = adsymbol.createLine();
256 line.setNumColumns(1);
257 line.setPosition(QPointF(0, -line.ascent()));
258 adsymbol.endLayout();
259 line.draw(this, QPointF(x, y));
263 // Here we use the font width cache instead of
264 // textwidth = fontMetrics().width(str);
265 // because the above is awfully expensive on MacOSX
266 textwidth = fi.metrics->width(str);
268 textwidth = smallCapsText(x, y, str, f);
271 if (f.underbar() == Font::ON) {
272 underline(f, x, y, textwidth);
279 } // namespace frontend