]> git.lyx.org Git - features.git/blob - src/frontends/qt4/QLPainter.C
c7e0f7f811d774d2aa929ac51a0ca417e39e8708
[features.git] / src / frontends / qt4 / QLPainter.C
1 /**
2  * \file QLPainter.C
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 <QTextLayout>
15
16 #include "QLPainter.h"
17
18 #include "GuiApplication.h"
19 #include "GuiFontMetrics.h"
20 #include "QLImage.h"
21
22 #include "GuiApplication.h"
23 #include "qt_helpers.h"
24
25 #include "debug.h"
26 #include "language.h"
27 #include "LColor.h"
28
29 #include "support/unicode.h"
30
31 using std::endl;
32 using std::string;
33
34 namespace lyx {
35 namespace frontend {
36
37 QLPainter::QLPainter(QPaintDevice * device)
38         : QPainter(device), Painter()
39 {
40         // new QPainter has default QPen:
41         current_color_ = LColor::black;
42         current_ls_ = line_solid;
43         current_lw_ = line_thin;
44 }
45
46
47 QLPainter::~QLPainter()
48 {
49         QPainter::end();
50         //lyxerr << "QLPainter::end()" << endl;
51 }
52
53
54 void QLPainter::setQPainterPen(LColor_color col,
55         Painter::line_style ls, Painter::line_width lw)
56 {
57         if (col == current_color_ && ls == current_ls_ && lw == current_lw_)
58                 return;
59
60         current_color_ = col;
61         current_ls_ = ls;
62         current_lw_ = lw;
63
64         QPen pen = QPainter::pen();
65
66         pen.setColor(guiApp->colorCache().get(col));
67
68         switch (ls) {
69                 case line_solid: pen.setStyle(Qt::SolidLine); break;
70                 case line_onoffdash: pen.setStyle(Qt::DotLine); break;
71         }
72
73         switch (lw) {
74                 case line_thin: pen.setWidth(0); break;
75                 case line_thick: pen.setWidth(3); break;
76         }
77
78         setPen(pen);
79 }
80
81
82 void QLPainter::point(int x, int y, LColor_color col)
83 {
84         if (!isDrawingEnabled())
85                 return;
86
87         setQPainterPen(col);
88         drawPoint(x, y);
89 }
90
91
92 void QLPainter::line(int x1, int y1, int x2, int y2,
93         LColor_color col,
94         line_style ls,
95         line_width lw)
96 {
97         if (!isDrawingEnabled())
98                 return;
99
100         setQPainterPen(col, ls, lw);
101         drawLine(x1, y1, x2, y2);
102 }
103
104
105 void QLPainter::lines(int const * xp, int const * yp, int np,
106         LColor_color col,
107         line_style ls,
108         line_width lw)
109 {
110         // FIXME ?
111
112         // Must use new as np is not known at compile time.
113         boost::scoped_array<QPoint> points(new QPoint[np]);
114
115         for (int i = 0; i < np; ++i) {
116                 points[i].setX(xp[i]);
117                 points[i].setY(yp[i]);
118         }
119
120         if (!isDrawingEnabled())
121                 return;
122
123         setQPainterPen(col, ls, lw);
124         drawPolyline(points.get(), np);
125 }
126
127
128 void QLPainter::rectangle(int x, int y, int w, int h,
129         LColor_color col,
130         line_style ls,
131         line_width lw)
132 {
133         if (!isDrawingEnabled())
134                 return;
135
136         setQPainterPen(col, ls, lw);
137         drawRect(x, y, w, h);
138 }
139
140
141 void QLPainter::fillRectangle(int x, int y, int w, int h, LColor_color col)
142 {
143         fillRect(x, y, w, h, guiApp->colorCache().get(col));
144 }
145
146
147 void QLPainter::arc(int x, int y, unsigned int w, unsigned int h,
148         int a1, int a2, LColor_color col)
149 {
150         if (!isDrawingEnabled())
151                 return;
152
153         // LyX usings 1/64ths degree, Qt usings 1/16th
154         setQPainterPen(col);
155         drawArc(x, y, w, h, a1 / 4, a2 / 4);
156 }
157
158
159 void QLPainter::image(int x, int y, int w, int h, graphics::Image const & i)
160 {
161         graphics::QLImage const & qlimage =
162                 static_cast<graphics::QLImage const &>(i);
163
164         fillRectangle(x, y, w, h, LColor::graphicsbg);
165
166         if (!isDrawingEnabled())
167                 return;
168
169         drawImage(x, y, qlimage.qimage(), 0, 0, w, h);
170 }
171
172
173 int QLPainter::text(int x, int y, char_type c, LyXFont const & f)
174 {
175         docstring s(1, c);
176         return text(x, y, s, f);
177 }
178
179
180 int QLPainter::smallCapsText(int x, int y,
181         QString const & s, LyXFont const & f)
182 {
183         LyXFont smallfont(f);
184         smallfont.decSize().decSize().setShape(LyXFont::UP_SHAPE);
185
186         QFont const & qfont = guiApp->guiFontLoader().get(f);
187         QFont const & qsmallfont = guiApp->guiFontLoader().get(smallfont);
188
189         setQPainterPen(f.realColor());
190         int textwidth = 0;
191         size_t const ls = s.length();
192         for (unsigned int i = 0; i < ls; ++i) {
193                 QChar const c = s[i].toUpper();
194                 if (c != s.at(i)) {
195                         setFont(qsmallfont);
196                 } else {
197                         setFont(qfont);
198                 }
199                 if (isDrawingEnabled())
200                         drawText(x + textwidth, y, c);
201                 textwidth += fontMetrics().width(c);
202         }
203         return textwidth;
204 }
205
206
207 int QLPainter::text(int x, int y, docstring const & s,
208                 LyXFont const & f)
209 {
210         QString str = toqstr(s);
211
212 #if 0
213         // HACK: QT3 refuses to show single compose characters
214         //       Still needed with Qt4?
215         if (ls == 1 && str[0].unicode() >= 0x05b0 && str[0].unicode() <= 0x05c2)
216                 str = ' ' + str;
217 #endif
218
219         QLFontInfo & fi = guiApp->guiFontLoader().fontinfo(f);
220
221         int textwidth;
222
223         if (f.realShape() != LyXFont::SMALLCAPS_SHAPE) {
224                 setQPainterPen(f.realColor());
225                 if (font() != fi.font)
226                         setFont(fi.font);
227                 // We need to draw the text as LTR as we use our own bidi code.
228                 setLayoutDirection(Qt::LeftToRight);
229                 if (isDrawingEnabled()) {
230                         if (lyxerr.debugging(Debug::PAINTING)) {
231                                 lyxerr[Debug::PAINTING] << "draw " << std::string(str.toUtf8())
232                                         << " at " << x << "," << y << std::endl;
233                         }
234                         // Qt4 does not display a glyph whose codepoint is the
235                         // same as that of a soft-hyphen (0x00ad), unless it
236                         // occurs at a line-break. As a kludge, we force Qt to
237                         // render this glyph using a one-column line.
238                         if (s.size() == 1 && str[0].unicode() == 0x00ad) {
239                                 QTextLayout adsymbol(str);
240                                 adsymbol.setFont(fi.font);
241                                 adsymbol.beginLayout();
242                                 QTextLine line = adsymbol.createLine();
243                                 line.setNumColumns(1);
244                                 line.setPosition(QPointF(0, -line.ascent()));
245                                 adsymbol.endLayout();
246                                 line.draw(this, QPointF(x, y));
247                         } else
248                                 drawText(x, y, str);
249                 }
250                 // Here we use the font width cache instead of
251                 //   textwidth = fontMetrics().width(str);
252                 // because the above is awfully expensive on MacOSX
253                 textwidth = fi.metrics->width(str);
254         } else {
255                 textwidth = smallCapsText(x, y, str, f);
256         }
257
258         if (f.underbar() == LyXFont::ON) {
259                 underline(f, x, y, textwidth);
260         }
261
262         return textwidth;
263 }
264
265
266 } // namespace frontend
267 } // namespace lyx
268