source: trunk/src/gui/painting/qdrawutil.cpp@ 127

Last change on this file since 127 was 2, checked in by Dmitry A. Kuminov, 17 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 37.0 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qdrawutil.h"
43#include "qbitmap.h"
44#include "qpixmapcache.h"
45#include "qapplication.h"
46#include "qpainter.h"
47#include "qpalette.h"
48
49QT_BEGIN_NAMESPACE
50
51/*!
52 \fn void qDrawShadeLine(QPainter *painter, int x1, int y1, int x2, int y2,
53 const QPalette &palette, bool sunken,
54 int lineWidth, int midLineWidth)
55 \relates QPainter
56
57 Draws a horizontal (\a y1 == \a y2) or vertical (\a x1 == \a x2)
58 shaded line using the given \a painter. Note that nothing is
59 drawn if \a y1 != \a y2 and \a x1 != \a x2 (i.e. the line is
60 neither horizontal nor vertical).
61
62 The provided \a palette specifies the shading colors (\l
63 {QPalette::light()}{light}, \l {QPalette::dark()}{dark} and \l
64 {QPalette::mid()}{middle} colors). The given \a lineWidth
65 specifies the line width for each of the lines; it is not the
66 total line width. The given \a midLineWidth specifies the width of
67 a middle line drawn in the QPalette::mid() color.
68
69 The line appears sunken if \a sunken is true, otherwise raised.
70
71 \warning This function does not look at QWidget::style() or
72 QApplication::style(). Use the drawing functions in QStyle to
73 make widgets that follow the current GUI style.
74
75
76 Alternatively you can use a QFrame widget and apply the
77 QFrame::setFrameStyle() function to display a shaded line:
78
79 \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 0
80
81 \sa qDrawShadeRect(), qDrawShadePanel(), QStyle
82*/
83
84void qDrawShadeLine(QPainter *p, int x1, int y1, int x2, int y2,
85 const QPalette &pal, bool sunken,
86 int lineWidth, int midLineWidth)
87{
88 if (!(p && lineWidth >= 0 && midLineWidth >= 0)) {
89 qWarning("qDrawShadeLine: Invalid parameters");
90 return;
91 }
92 int tlw = lineWidth*2 + midLineWidth; // total line width
93 QPen oldPen = p->pen(); // save pen
94 if (sunken)
95 p->setPen(pal.color(QPalette::Dark));
96 else
97 p->setPen(pal.light().color());
98 QPolygon a;
99 int i;
100 if (y1 == y2) { // horizontal line
101 int y = y1 - tlw/2;
102 if (x1 > x2) { // swap x1 and x2
103 int t = x1;
104 x1 = x2;
105 x2 = t;
106 }
107 x2--;
108 for (i=0; i<lineWidth; i++) { // draw top shadow
109 a.setPoints(3, x1+i, y+tlw-1-i,
110 x1+i, y+i,
111 x2-i, y+i);
112 p->drawPolyline(a);
113 }
114 if (midLineWidth > 0) {
115 p->setPen(pal.mid().color());
116 for (i=0; i<midLineWidth; i++) // draw lines in the middle
117 p->drawLine(x1+lineWidth, y+lineWidth+i,
118 x2-lineWidth, y+lineWidth+i);
119 }
120 if (sunken)
121 p->setPen(pal.light().color());
122 else
123 p->setPen(pal.dark().color());
124 for (i=0; i<lineWidth; i++) { // draw bottom shadow
125 a.setPoints(3, x1+i, y+tlw-i-1,
126 x2-i, y+tlw-i-1,
127 x2-i, y+i+1);
128 p->drawPolyline(a);
129 }
130 }
131 else if (x1 == x2) { // vertical line
132 int x = x1 - tlw/2;
133 if (y1 > y2) { // swap y1 and y2
134 int t = y1;
135 y1 = y2;
136 y2 = t;
137 }
138 y2--;
139 for (i=0; i<lineWidth; i++) { // draw left shadow
140 a.setPoints(3, x+i, y2,
141 x+i, y1+i,
142 x+tlw-1, y1+i);
143 p->drawPolyline(a);
144 }
145 if (midLineWidth > 0) {
146 p->setPen(pal.mid().color());
147 for (i=0; i<midLineWidth; i++) // draw lines in the middle
148 p->drawLine(x+lineWidth+i, y1+lineWidth, x+lineWidth+i, y2);
149 }
150 if (sunken)
151 p->setPen(pal.light().color());
152 else
153 p->setPen(pal.dark().color());
154 for (i=0; i<lineWidth; i++) { // draw right shadow
155 a.setPoints(3, x+lineWidth, y2-i,
156 x+tlw-i-1, y2-i,
157 x+tlw-i-1, y1+lineWidth);
158 p->drawPolyline(a);
159 }
160 }
161 p->setPen(oldPen);
162}
163
164/*!
165 \fn void qDrawShadeRect(QPainter *painter, int x, int y, int width, int height,
166 const QPalette &palette, bool sunken,
167 int lineWidth, int midLineWidth,
168 const QBrush *fill)
169 \relates QPainter
170
171 Draws the shaded rectangle beginning at (\a x, \a y) with the
172 given \a width and \a height using the provided \a painter.
173
174 The provide \a palette specifies the shading colors (\l
175 {QPalette::light()}{light}, \l {QPalette::dark()}{dark} and \l
176 {QPalette::mid()}{middle} colors. The given \a lineWidth
177 specifies the line width for each of the lines; it is not the
178 total line width. The \a midLineWidth specifies the width of a
179 middle line drawn in the QPalette::mid() color. The rectangle's
180 interior is filled with the \a fill brush unless \a fill is 0.
181
182 The rectangle appears sunken if \a sunken is true, otherwise
183 raised.
184
185 \warning This function does not look at QWidget::style() or
186 QApplication::style(). Use the drawing functions in QStyle to make
187 widgets that follow the current GUI style.
188
189 Alternatively you can use a QFrame widget and apply the
190 QFrame::setFrameStyle() function to display a shaded rectangle:
191
192 \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 1
193
194 \sa qDrawShadeLine(), qDrawShadePanel(), qDrawPlainRect(), QStyle
195*/
196
197void qDrawShadeRect(QPainter *p, int x, int y, int w, int h,
198 const QPalette &pal, bool sunken,
199 int lineWidth, int midLineWidth,
200 const QBrush *fill)
201{
202 if (w == 0 || h == 0)
203 return;
204 if (! (w > 0 && h > 0 && lineWidth >= 0 && midLineWidth >= 0)) {
205 qWarning("qDrawShadeRect: Invalid parameters");
206 return;
207 }
208 QPen oldPen = p->pen();
209 if (sunken)
210 p->setPen(pal.dark().color());
211 else
212 p->setPen(pal.light().color());
213 int x1=x, y1=y, x2=x+w-1, y2=y+h-1;
214
215 if (lineWidth == 1 && midLineWidth == 0) {// standard shade rectangle
216 p->drawRect(x1, y1, w-2, h-2);
217 if (sunken)
218 p->setPen(pal.light().color());
219 else
220 p->setPen(pal.dark().color());
221 QLineF lines[4] = { QLineF(x1+1, y1+1, x2-2, y1+1),
222 QLineF(x1+1, y1+2, x1+1, y2-2),
223 QLineF(x1, y2, x2, y2),
224 QLineF(x2,y1, x2,y2-1) };
225 p->drawLines(lines, 4); // draw bottom/right lines
226 } else { // more complicated
227 int m = lineWidth+midLineWidth;
228 int i, j=0, k=m;
229 for (i=0; i<lineWidth; i++) { // draw top shadow
230 QLineF lines[4] = { QLineF(x1+i, y2-i, x1+i, y1+i),
231 QLineF(x1+i, y1+i, x2-i, y1+i),
232 QLineF(x1+k, y2-k, x2-k, y2-k),
233 QLineF(x2-k, y2-k, x2-k, y1+k) };
234 p->drawLines(lines, 4);
235 k++;
236 }
237 p->setPen(pal.mid().color());
238 j = lineWidth*2;
239 for (i=0; i<midLineWidth; i++) { // draw lines in the middle
240 p->drawRect(x1+lineWidth+i, y1+lineWidth+i, w-j-1, h-j-1);
241 j += 2;
242 }
243 if (sunken)
244 p->setPen(pal.light().color());
245 else
246 p->setPen(pal.dark().color());
247 k = m;
248 for (i=0; i<lineWidth; i++) { // draw bottom shadow
249 QLineF lines[4] = { QLineF(x1+1+i, y2-i, x2-i, y2-i),
250 QLineF(x2-i, y2-i, x2-i, y1+i+1),
251 QLineF(x1+k, y2-k, x1+k, y1+k),
252 QLineF(x1+k, y1+k, x2-k, y1+k) };
253 p->drawLines(lines, 4);
254 k++;
255 }
256 }
257 if (fill) {
258 QBrush oldBrush = p->brush();
259 int tlw = lineWidth + midLineWidth;
260 p->setPen(Qt::NoPen);
261 p->setBrush(*fill);
262 p->drawRect(x+tlw, y+tlw, w-2*tlw, h-2*tlw);
263 p->setBrush(oldBrush);
264 }
265 p->setPen(oldPen); // restore pen
266}
267
268
269/*!
270 \fn void qDrawShadePanel(QPainter *painter, int x, int y, int width, int height,
271 const QPalette &palette, bool sunken,
272 int lineWidth, const QBrush *fill)
273 \relates QPainter
274
275 Draws the shaded panel beginning at (\a x, \a y) with the given \a
276 width and \a height using the provided \a painter and the given \a
277 lineWidth.
278
279 The given \a palette specifies the shading colors (\l
280 {QPalette::light()}{light}, \l {QPalette::dark()}{dark} and \l
281 {QPalette::mid()}{middle} colors). The panel's interior is filled
282 with the \a fill brush unless \a fill is 0.
283
284 The panel appears sunken if \a sunken is true, otherwise raised.
285
286 \warning This function does not look at QWidget::style() or
287 QApplication::style(). Use the drawing functions in QStyle to make
288 widgets that follow the current GUI style.
289
290 Alternatively you can use a QFrame widget and apply the
291 QFrame::setFrameStyle() function to display a shaded panel:
292
293 \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 2
294
295 \sa qDrawWinPanel(), qDrawShadeLine(), qDrawShadeRect(), QStyle
296*/
297
298void qDrawShadePanel(QPainter *p, int x, int y, int w, int h,
299 const QPalette &pal, bool sunken,
300 int lineWidth, const QBrush *fill)
301{
302 if (w == 0 || h == 0)
303 return;
304 if (!(w > 0 && h > 0 && lineWidth >= 0)) {
305 qWarning("qDrawShadePanel: Invalid parameters");
306 }
307 QColor shade = pal.dark().color();
308 QColor light = pal.light().color();
309 if (fill) {
310 if (fill->color() == shade)
311 shade = pal.shadow().color();
312 if (fill->color() == light)
313 light = pal.midlight().color();
314 }
315 QPen oldPen = p->pen(); // save pen
316 QVector<QLineF> lines;
317 lines.reserve(2*lineWidth);
318
319 if (sunken)
320 p->setPen(shade);
321 else
322 p->setPen(light);
323 int x1, y1, x2, y2;
324 int i;
325 x1 = x;
326 y1 = y2 = y;
327 x2 = x+w-2;
328 for (i=0; i<lineWidth; i++) { // top shadow
329 lines << QLineF(x1, y1++, x2--, y2++);
330 }
331 x2 = x1;
332 y1 = y+h-2;
333 for (i=0; i<lineWidth; i++) { // left shado
334 lines << QLineF(x1++, y1, x2++, y2--);
335 }
336 p->drawLines(lines);
337 lines.clear();
338 if (sunken)
339 p->setPen(light);
340 else
341 p->setPen(shade);
342 x1 = x;
343 y1 = y2 = y+h-1;
344 x2 = x+w-1;
345 for (i=0; i<lineWidth; i++) { // bottom shadow
346 lines << QLineF(x1++, y1--, x2, y2--);
347 }
348 x1 = x2;
349 y1 = y;
350 y2 = y+h-lineWidth-1;
351 for (i=0; i<lineWidth; i++) { // right shadow
352 lines << QLineF(x1--, y1++, x2--, y2);
353 }
354 p->drawLines(lines);
355 if (fill) // fill with fill color
356 p->fillRect(x+lineWidth, y+lineWidth, w-lineWidth*2, h-lineWidth*2, *fill);
357 p->setPen(oldPen); // restore pen
358}
359
360
361/*!
362 \internal
363 This function draws a rectangle with two pixel line width.
364 It is called from qDrawWinButton() and qDrawWinPanel().
365
366 c1..c4 and fill are used:
367
368 1 1 1 1 1 2
369 1 3 3 3 4 2
370 1 3 F F 4 2
371 1 3 F F 4 2
372 1 4 4 4 4 2
373 2 2 2 2 2 2
374*/
375
376static void qDrawWinShades(QPainter *p,
377 int x, int y, int w, int h,
378 const QColor &c1, const QColor &c2,
379 const QColor &c3, const QColor &c4,
380 const QBrush *fill)
381{
382 if (w < 2 || h < 2) // can't do anything with that
383 return;
384 QPen oldPen = p->pen();
385 QPoint a[3] = { QPoint(x, y+h-2), QPoint(x, y), QPoint(x+w-2, y) };
386 p->setPen(c1);
387 p->drawPolyline(a, 3);
388 QPoint b[3] = { QPoint(x, y+h-1), QPoint(x+w-1, y+h-1), QPoint(x+w-1, y) };
389 p->setPen(c2);
390 p->drawPolyline(b, 3);
391 if (w > 4 && h > 4) {
392 QPoint c[3] = { QPoint(x+1, y+h-3), QPoint(x+1, y+1), QPoint(x+w-3, y+1) };
393 p->setPen(c3);
394 p->drawPolyline(c, 3);
395 QPoint d[3] = { QPoint(x+1, y+h-2), QPoint(x+w-2, y+h-2), QPoint(x+w-2, y+1) };
396 p->setPen(c4);
397 p->drawPolyline(d, 3);
398 if (fill)
399 p->fillRect(QRect(x+2, y+2, w-4, h-4), *fill);
400 }
401 p->setPen(oldPen);
402}
403
404
405/*!
406 \fn void qDrawWinButton(QPainter *painter, int x, int y, int width, int height,
407 const QPalette &palette, bool sunken,
408 const QBrush *fill)
409 \relates QPainter
410
411 Draws the Windows-style button specified by the given point (\a x,
412 \a y}, \a width and \a height using the provided \a painter with a
413 line width of 2 pixels. The button's interior is filled with the
414 \a{fill} brush unless \a fill is 0.
415
416 The given \a palette specifies the shading colors (\l
417 {QPalette::light()}{light}, \l {QPalette::dark()}{dark} and \l
418 {QPalette::mid()}{middle} colors).
419
420 The button appears sunken if \a sunken is true, otherwise raised.
421
422 \warning This function does not look at QWidget::style() or
423 QApplication::style()-> Use the drawing functions in QStyle to make
424 widgets that follow the current GUI style.
425
426 \sa qDrawWinPanel(), QStyle
427*/
428
429void qDrawWinButton(QPainter *p, int x, int y, int w, int h,
430 const QPalette &pal, bool sunken,
431 const QBrush *fill)
432{
433 if (sunken)
434 qDrawWinShades(p, x, y, w, h,
435 pal.shadow().color(), pal.light().color(), pal.dark().color(),
436 pal.button().color(), fill);
437 else
438 qDrawWinShades(p, x, y, w, h,
439 pal.light().color(), pal.shadow().color(), pal.button().color(),
440 pal.dark().color(), fill);
441}
442
443/*!
444 \fn void qDrawWinPanel(QPainter *painter, int x, int y, int width, int height,
445 const QPalette &palette, bool sunken,
446 const QBrush *fill)
447 \relates QPainter
448
449 Draws the Windows-style panel specified by the given point(\a x,
450 \a y), \a width and \a height using the provided \a painter with a
451 line width of 2 pixels. The button's interior is filled with the
452 \a fill brush unless \a fill is 0.
453
454 The given \a palette specifies the shading colors. The panel
455 appears sunken if \a sunken is true, otherwise raised.
456
457 \warning This function does not look at QWidget::style() or
458 QApplication::style(). Use the drawing functions in QStyle to make
459 widgets that follow the current GUI style.
460
461 Alternatively you can use a QFrame widget and apply the
462 QFrame::setFrameStyle() function to display a shaded panel:
463
464 \snippet doc/src/snippets/code/src_gui_painting_qdrawutil.cpp 3
465
466 \sa qDrawShadePanel(), qDrawWinButton(), QStyle
467*/