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_ = LColor::black;
42 current_ls_ = line_solid;
43 current_lw_ = line_thin;
47 QLPainter::~QLPainter()
50 //lyxerr << "QLPainter::end()" << endl;
54 void QLPainter::setQPainterPen(LColor_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, LColor_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 drawLine(x1, y1, x2, y2);
105 void QLPainter::lines(int const * xp, int const * yp, int np,
112 // Must use new as np is not known at compile time.
113 boost::scoped_array<QPoint> points(new QPoint[np]);
115 for (int i = 0; i < np; ++i) {
116 points[i].setX(xp[i]);
117 points[i].setY(yp[i]);
120 if (!isDrawingEnabled())
123 setQPainterPen(col, ls, lw);
124 drawPolyline(points.get(), np);
128 void QLPainter::rectangle(int x, int y, int w, int h,
133 if (!isDrawingEnabled())
136 setQPainterPen(col, ls, lw);
137 drawRect(x, y, w, h);
141 void QLPainter::fillRectangle(int x, int y, int w, int h, LColor_color col)
143 fillRect(x, y, w, h, guiApp->colorCache().get(col));
147 void QLPainter::arc(int x, int y, unsigned int w, unsigned int h,
148 int a1, int a2, LColor_color col)
150 if (!isDrawingEnabled())
153 // LyX usings 1/64ths degree, Qt usings 1/16th
155 drawArc(x, y, w, h, a1 / 4, a2 / 4);
159 void QLPainter::image(int x, int y, int w, int h, graphics::Image const & i)
161 graphics::QLImage const & qlimage =
162 static_cast<graphics::QLImage const &>(i);
164 fillRectangle(x, y, w, h, LColor::graphicsbg);
166 if (!isDrawingEnabled())
169 drawImage(x, y, qlimage.qimage(), 0, 0, w, h);
173 int QLPainter::text(int x, int y, char_type c, LyXFont const & f)
176 return text(x, y, s, f);
180 int QLPainter::smallCapsText(int x, int y,
181 QString const & s, LyXFont const & f)
183 LyXFont smallfont(f);
184 smallfont.decSize().decSize().setShape(LyXFont::UP_SHAPE);
186 QFont const & qfont = guiApp->guiFontLoader().get(f);
187 QFont const & qsmallfont = guiApp->guiFontLoader().get(smallfont);
189 setQPainterPen(f.realColor());
191 size_t const ls = s.length();
192 for (unsigned int i = 0; i < ls; ++i) {
193 QChar const c = s[i].toUpper();
199 if (isDrawingEnabled())
200 drawText(x + textwidth, y, c);
201 textwidth += fontMetrics().width(c);
207 int QLPainter::text(int x, int y, docstring const & s,
210 /* Caution: The following ucs4 to QString conversions work for symbol fonts
211 only because they are no real conversions but simple casts in reality.
212 When we want to draw a symbol or calculate the metrics we pass the position
213 of the symbol in the font (as given in lib/symbols) as a char_type to the
214 frontend. This is just wrong, because the symbol is no UCS4 character at
215 all. You can think of this number as the code point of the symbol in a
216 custom symbol encoding. It works because this char_type is lateron again
217 interpreted as a position in the font again.
218 The correct solution would be to have extra functions for symbols, but that
219 would require to duplicate a lot of frontend and mathed support code.
221 QString str = toqstr(s);
224 // HACK: QT3 refuses to show single compose characters
225 // Still needed with Qt4?
226 if (ls == 1 && str[0].unicode() >= 0x05b0 && str[0].unicode() <= 0x05c2)
230 QLFontInfo & fi = guiApp->guiFontLoader().fontinfo(f);
234 if (f.realShape() != LyXFont::SMALLCAPS_SHAPE) {
235 setQPainterPen(f.realColor());
236 if (font() != fi.font)
238 // We need to draw the text as LTR as we use our own bidi code.
239 setLayoutDirection(Qt::LeftToRight);
240 if (isDrawingEnabled()) {
241 if (lyxerr.debugging(Debug::PAINTING)) {
242 lyxerr[Debug::PAINTING] << "draw " << std::string(str.toUtf8())
243 << " at " << x << "," << y << std::endl;
245 // Qt4 does not display a glyph whose codepoint is the
246 // same as that of a soft-hyphen (0x00ad), unless it
247 // occurs at a line-break. As a kludge, we force Qt to
248 // render this glyph using a one-column line.
249 if (s.size() == 1 && str[0].unicode() == 0x00ad) {
250 QTextLayout adsymbol(str);
251 adsymbol.setFont(fi.font);
252 adsymbol.beginLayout();
253 QTextLine line = adsymbol.createLine();
254 line.setNumColumns(1);
255 line.setPosition(QPointF(0, -line.ascent()));
256 adsymbol.endLayout();
257 line.draw(this, QPointF(x, y));
261 // Here we use the font width cache instead of
262 // textwidth = fontMetrics().width(str);
263 // because the above is awfully expensive on MacOSX
264 textwidth = fi.metrics->width(str);
266 textwidth = smallCapsText(x, y, str, f);
269 if (f.underbar() == LyXFont::ON) {
270 underline(f, x, y, textwidth);
277 } // namespace frontend