]> git.lyx.org Git - features.git/blob - src/frontends/qt4/QLPainter.C
This is the merging of the GUI API cleanup branch that was developed in svn+ssh:...
[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 "QLPainter.h"
15
16 #include "GuiWorkArea.h"
17 #include "QLImage.h"
18
19 #include "ColorCache.h"
20 #include "FontLoader.h"
21
22 #include "debug.h"
23 #include "language.h"
24 #include "LColor.h"
25
26 #include "frontends/font_metrics.h"
27
28 #include <QPainter>
29 #include <QPicture>
30 #include <QPixmap>
31 #include <QImage>
32
33 using std::endl;
34 using std::string;
35
36 namespace lyx {
37 namespace frontend {
38
39 QLPainter::~QLPainter()
40 {
41 }
42
43 QLPainter::QLPainter(GuiWorkArea * qwa)
44         : Painter(), qwa_(qwa)
45 {
46 }
47
48
49 int QLPainter::paperWidth() const
50 {
51         return qwa_->viewport()->width();
52 }
53
54
55 int QLPainter::paperHeight() const
56 {
57         return qwa_->viewport()->height();
58 }
59
60 void QLPainter::setQPainterPen(QPainter & qp, LColor_color col,
61         Painter::line_style ls, Painter::line_width lw)
62 {
63         if (col == current_color_ && ls == current_ls_ && lw == current_lw_)
64                 return;
65
66         current_color_ = col;
67         current_ls_ = ls;
68         current_lw_ = lw;
69
70         QPen pen = qp.pen();
71
72         pen.setColor(lcolorcache.get(col));
73
74         switch (ls) {
75                 case line_solid: pen.setStyle(Qt::SolidLine); break;
76                 case line_onoffdash: pen.setStyle(Qt::DotLine); break;
77         }
78
79         switch (lw) {
80                 case line_thin: pen.setWidth(0); break;
81                 case line_thick: pen.setWidth(3); break;
82         }
83
84         qp.setPen(pen);
85 }
86
87 void QLPainter::point(int x, int y, LColor_color col)
88 {
89         QPainter qp(qwa_->paintDevice());
90         setQPainterPen(qp, col);
91         qp.drawPoint(x, y);
92 }
93
94
95 void QLPainter::line(int x1, int y1, int x2, int y2,
96         LColor_color col,
97         line_style ls,
98         line_width lw)
99 {
100         QPainter qp(qwa_->paintDevice());
101         setQPainterPen(qp, col, ls, lw);
102         qp.drawLine(x1, y1, x2, y2);
103 }
104
105
106 void QLPainter::lines(int const * xp, int const * yp, int np,
107         LColor_color col,
108         line_style ls,
109         line_width lw)
110 {
111         // FIXME ?
112
113         // Must use new as np is not known at compile time.
114         boost::scoped_array<QPoint> points(new QPoint[np]);
115
116         for (int i = 0; i < np; ++i) {
117                 points[i].setX(xp[i]);
118                 points[i].setY(yp[i]);
119         }
120
121         QPainter qp(qwa_->paintDevice());
122         setQPainterPen(qp, col, ls, lw);
123         qp.drawPolyline(points.get(), np);
124 }
125
126
127 void QLPainter::rectangle(int x, int y, int w, int h,
128         LColor_color col,
129         line_style ls,
130         line_width lw)
131 {
132         QPainter qp(qwa_->paintDevice());
133         setQPainterPen(qp, col, ls, lw);
134         qp.drawRect(x, y, w, h);
135 }
136
137
138 void QLPainter::fillRectangle(int x, int y, int w, int h, LColor_color col)
139 {
140         QPainter qp(qwa_->paintDevice());
141         qp.fillRect(x, y, w, h, lcolorcache.get(col));
142 }
143
144
145 void QLPainter::fillPolygon(int const * xp, int const * yp,
146         int np, LColor_color col)
147 {
148         // Must use new as np is not known at compile time.
149         boost::scoped_array<QPoint> points(new QPoint[np]);
150
151         for (int i = 0; i < np; ++i) {
152                 points[i].setX(xp[i]);
153                 points[i].setY(yp[i]);
154         }
155
156         QPainter qp(qwa_->paintDevice());
157         setQPainterPen(qp, col);
158         qp.setBrush(lcolorcache.get(col));
159         qp.drawPolygon(points.get(), np);
160         qp.setBrush(Qt::NoBrush);
161 }
162
163
164 void QLPainter::arc(int x, int y, unsigned int w, unsigned int h,
165         int a1, int a2, LColor_color col)
166 {
167         // LyX usings 1/64ths degree, Qt usings 1/16th
168         QPainter qp(qwa_->paintDevice());
169         setQPainterPen(qp, col);
170         qp.drawArc(x, y, w, h, a1 / 4, a2 / 4);
171 }
172
173
174 void QLPainter::image(int x, int y, int w, int h,
175         lyx::graphics::Image const & i)
176 {
177         lyx::graphics::QLImage const & qlimage =
178                 static_cast<lyx::graphics::QLImage const &>(i);
179
180         fillRectangle(x, y, w, h, LColor::graphicsbg);
181
182         QPainter qp(qwa_->paintDevice());
183         qp.drawImage(x, y, qlimage.qimage(), 0, 0, w, h);
184 }
185
186
187 void QLPainter::text(int x, int y, string const & s, LyXFont const & f)
188 {
189         return text(x, y, s.data(), s.length(), f);
190 }
191
192
193 void QLPainter::text(int x, int y, char c, LyXFont const & f)
194 {
195         char s[2] = { c, '\0' };
196         return text(x, y, s, 1, f);
197 }
198
199
200 void QLPainter::smallCapsText(int x, int y,
201         QString const & s, LyXFont const & f)
202 {
203         LyXFont smallfont(f);
204         smallfont.decSize().decSize().setShape(LyXFont::UP_SHAPE);
205
206         QFont const & qfont = fontloader.get(f);
207         QFont const & qsmallfont = fontloader.get(smallfont);
208         QFontMetrics const & qfontm = QFontMetrics(qfont);
209         QFontMetrics const & qsmallfontm = QFontMetrics(qsmallfont);
210
211         QPainter qp(qwa_->paintDevice());
212         setQPainterPen(qp, f.realColor());
213         int tmpx = x;
214         size_t ls = s.length();
215         for (size_t i = 0; i < ls; ++i) {
216                 QChar const c = s[i].upper();
217                 if (c != s.at(i)) {
218                         qp.setFont(qsmallfont);
219                         qp.drawText(tmpx, y, c);
220                         tmpx += qsmallfontm.width(c);
221                 } else {
222                         qp.setFont(qfont);
223                         qp.drawText(tmpx, y, c);
224                         tmpx += qfontm.width(c);
225                 }
226         }
227 }
228
229
230 void QLPainter::text(int x, int y, char const * s, size_t ls,
231         LyXFont const & f)
232 {
233         Encoding const * encoding = f.language()->encoding();
234         if (f.isSymbolFont())
235                 encoding = encodings.symbol_encoding();
236
237         QString str;
238         str.setLength(ls);
239         for (size_t i = 0; i < ls; ++i)
240                 str[i] = QChar(encoding->ucs(s[i]));
241
242         // HACK: QT3 refuses to show single compose characters
243         //       Still needed with Qt4?
244         if (ls == 1 && str[0].unicode() >= 0x05b0 && str[0].unicode() <= 0x05c2)
245                 str = ' ' + str;
246
247         if (f.realShape() != LyXFont::SMALLCAPS_SHAPE) {
248                 QPainter qp(qwa_->paintDevice());
249                 setQPainterPen(qp, f.realColor());
250                 qp.setFont(fontloader.get(f));
251                 // We need to draw the text as LTR as we use our own bidi code.
252                 qp.setLayoutDirection(Qt::LeftToRight);
253                 qp.drawText(x, y, str);
254         } else {
255                 smallCapsText(x, y, str, f);
256         }
257
258         if (f.underbar() == LyXFont::ON) {
259                 underline(f, x, y, font_metrics::width(s, ls, f));
260         }
261
262 }
263 /// draw a pixmap from the image cache
264 void QLPainter::drawPixmap(int x, int y, QPixmap const & pixmap)
265 {
266         QPainter qp(qwa_->paintDevice());
267         qp.drawPixmap(x, y, pixmap);
268 }
269
270 void QLPainter::drawImage(int x, int y, QImage const & image)
271 {
272         QPainter qp(qwa_->paintDevice());
273         qp.drawImage(x, y, image);
274 }
275
276 } // namespace frontend
277 } // namespace lyx
278