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 setRenderHint(Antialiasing, x1 != x2 && y1 != y2);
102 drawLine(x1, y1, x2, y2);
103 setRenderHint(Antialiasing, false);
107 void QLPainter::lines(int const * xp, int const * yp, int np,
114 // Must use new as np is not known at compile time.
115 boost::scoped_array<QPoint> points(new QPoint[np]);
117 bool antialias = false;
118 for (int i = 0; i < np; ++i) {
119 points[i].setX(xp[i]);
120 points[i].setY(yp[i]);
122 antialias |= xp[i-1] != xp[i] && yp[i-1] != yp[i];
125 if (!isDrawingEnabled())
128 setQPainterPen(col, ls, lw);
129 setRenderHint(Antialiasing, antialias);
130 drawPolyline(points.get(), np);
131 setRenderHint(Antialiasing, false);
135 void QLPainter::rectangle(int x, int y, int w, int h,
140 if (!isDrawingEnabled())
143 setQPainterPen(col, ls, lw);
144 drawRect(x, y, w, h);
148 void QLPainter::fillRectangle(int x, int y, int w, int h, Color_color col)
150 fillRect(x, y, w, h, guiApp->colorCache().get(col));
154 void QLPainter::arc(int x, int y, unsigned int w, unsigned int h,
155 int a1, int a2, Color_color col)
157 if (!isDrawingEnabled())
160 // LyX usings 1/64ths degree, Qt usings 1/16th
162 setRenderHint(Antialiasing, true);
163 drawArc(x, y, w, h, a1 / 4, a2 / 4);
164 setRenderHint(Antialiasing, false);
168 void QLPainter::image(int x, int y, int w, int h, graphics::Image const & i)
170 graphics::QLImage const & qlimage =
171 static_cast<graphics::QLImage const &>(i);
173 fillRectangle(x, y, w, h, Color::graphicsbg);
175 if (!isDrawingEnabled())
178 drawImage(x, y, qlimage.qimage(), 0, 0, w, h);
182 int QLPainter::text(int x, int y, char_type c, LyXFont const & f)
185 return text(x, y, s, f);
189 int QLPainter::smallCapsText(int x, int y,
190 QString const & s, LyXFont const & f)
192 LyXFont smallfont(f);
193 smallfont.decSize().decSize().setShape(LyXFont::UP_SHAPE);
195 QFont const & qfont = guiApp->guiFontLoader().get(f);
196 QFont const & qsmallfont = guiApp->guiFontLoader().get(smallfont);
198 setQPainterPen(f.realColor());
200 size_t const ls = s.length();
201 for (unsigned int i = 0; i < ls; ++i) {
202 QChar const c = s[i].toUpper();
208 if (isDrawingEnabled())
209 drawText(x + textwidth, y, c);
210 textwidth += fontMetrics().width(c);
216 int QLPainter::text(int x, int y, docstring const & s,
219 /* Caution: The following ucs4 to QString conversions work for symbol fonts
220 only because they are no real conversions but simple casts in reality.
221 When we want to draw a symbol or calculate the metrics we pass the position
222 of the symbol in the font (as given in lib/symbols) as a char_type to the
223 frontend. This is just wrong, because the symbol is no UCS4 character at
224 all. You can think of this number as the code point of the symbol in a
225 custom symbol encoding. It works because this char_type is lateron again
226 interpreted as a position in the font again.
227 The correct solution would be to have extra functions for symbols, but that
228 would require to duplicate a lot of frontend and mathed support code.
230 QString str = toqstr(s);
233 // HACK: QT3 refuses to show single compose characters
234 // Still needed with Qt4?
235 if (ls == 1 && str[0].unicode() >= 0x05b0 && str[0].unicode() <= 0x05c2)
239 QLFontInfo & fi = guiApp->guiFontLoader().fontinfo(f);
243 if (f.realShape() != LyXFont::SMALLCAPS_SHAPE) {
244 setQPainterPen(f.realColor());
245 if (font() != fi.font)
247 // We need to draw the text as LTR as we use our own bidi code.
248 setLayoutDirection(Qt::LeftToRight);
249 if (isDrawingEnabled()) {
250 LYXERR(Debug::PAINTING) << "draw " << std::string(str.toUtf8())
251 << " at " << x << "," << y << std::endl;
252 // Qt4 does not display a glyph whose codepoint is the
253 // same as that of a soft-hyphen (0x00ad), unless it
254 // occurs at a line-break. As a kludge, we force Qt to
255 // render this glyph using a one-column line.
256 if (s.size() == 1 && str[0].unicode() == 0x00ad) {
257 QTextLayout adsymbol(str);
258 adsymbol.setFont(fi.font);
259 adsymbol.beginLayout();
260 QTextLine line = adsymbol.createLine();
261 line.setNumColumns(1);
262 line.setPosition(QPointF(0, -line.ascent()));
263 adsymbol.endLayout();
264 line.draw(this, QPointF(x, y));
268 // Here we use the font width cache instead of
269 // textwidth = fontMetrics().width(str);
270 // because the above is awfully expensive on MacOSX
271 textwidth = fi.metrics->width(str);
273 textwidth = smallCapsText(x, y, str, f);
276 if (f.underbar() == LyXFont::ON) {
277 underline(f, x, y, textwidth);
284 } // namespace frontend