source: trunk/src/gui/painting/qpaintengine.cpp@ 203

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

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

File size: 29.2 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#include "qpaintengine.h"
42#include "qpaintengine_p.h"
43#include "qpainter_p.h"
44#include "qpolygon.h"
45#include "qbitmap.h"
46#include "qapplication.h"
47#include <qdebug.h>
48#include <qmath.h>
49#include <private/qtextengine_p.h>
50#include <qvarlengtharray.h>
51#include <private/qfontengine_p.h>
52
53
54QT_BEGIN_NAMESPACE
55
56/*!
57 \class QTextItem
58
59 \brief The QTextItem class provides all the information required to draw
60 text in a custom paint engine.
61
62 When you reimplement your own paint engine, you must reimplement
63 QPaintEngine::drawTextItem(), a function that takes a QTextItem as
64 one of its arguments.
65*/
66
67/*!
68 \enum QTextItem::RenderFlag
69
70 \value RightToLeft Render the text from right to left.
71 \value Overline Paint a line above the text.
72 \value Underline Paint a line under the text.
73 \value StrikeOut Paint a line through the text.
74 \omitvalue Dummy
75*/
76
77
78/*!
79 \fn qreal QTextItem::descent() const
80
81 Corresponds to the \l{QFontMetrics::descent()}{descent} of the piece of text that is drawn.
82*/
83qreal QTextItem::descent() const
84{
85 const QTextItemInt *ti = static_cast<const QTextItemInt *>(this);
86 return ti->descent.toReal();
87}
88
89/*!
90 \fn qreal QTextItem::ascent() const
91
92 Corresponds to the \l{QFontMetrics::ascent()}{ascent} of the piece of text that is drawn.
93*/
94qreal QTextItem::ascent() const
95{
96 const QTextItemInt *ti = static_cast<const QTextItemInt *>(this);
97 return ti->ascent.toReal();
98}
99
100/*!
101 \fn qreal QTextItem::width() const
102
103 Specifies the total width of the text to be drawn.
104*/
105qreal QTextItem::width() const
106{
107 const QTextItemInt *ti = static_cast<const QTextItemInt *>(this);
108 return ti->width.toReal();
109}
110
111/*!
112 \fn QTextItem::RenderFlags QTextItem::renderFlags() const
113
114 Returns the render flags used.
115*/
116QTextItem::RenderFlags QTextItem::renderFlags() const
117{
118 const QTextItemInt *ti = static_cast<const QTextItemInt *>(this);
119 return ti->flags;
120}
121
122/*!
123 \fn QString QTextItem::text() const
124
125 Returns the text that should be drawn.
126*/
127QString QTextItem::text() const
128{
129 const QTextItemInt *ti = static_cast<const QTextItemInt *>(this);
130 return QString(ti->chars, ti->num_chars);
131}
132
133/*!
134 \fn QFont QTextItem::font() const
135
136 Returns the font that should be used to draw the text.
137*/
138QFont QTextItem::font() const
139{
140 const QTextItemInt *ti = static_cast<const QTextItemInt *>(this);
141 return ti->f ? *ti->f : QApplication::font();
142}
143
144
145/*!
146 \class QPaintEngine
147 \ingroup multimedia
148
149 \brief The QPaintEngine class provides an abstract definition of how
150 QPainter draws to a given device on a given platform.
151
152 Qt 4.0 provides several premade implementations of QPaintEngine for the
153 different painter backends we support. We provide one paint engine for each
154 window system and painting framework we support. This includes X11 on
155 Unix/Linux and CoreGraphics on Mac OS X. In addition we provide QPaintEngine
156 implementations for OpenGL (accessible through QGLWidget) and PostScript
157 (accessible through QPSPrinter on X11). Additionally there is a raster-based
158 paint engine that is a fallback for when an engine does not support a certain
159 capability.
160
161 If one wants to use QPainter to draw to a different backend,
162 one must subclass QPaintEngine and reimplement all its virtual
163 functions. The QPaintEngine implementation is then made available by
164 subclassing QPaintDevice and reimplementing the virtual function
165 QPaintDevice::paintEngine().
166
167 QPaintEngine is created and owned by the QPaintDevice that created it.
168
169 The big advantage of the QPaintEngine approach opposed to
170 Qt 3's QPainter/QPaintDevice::cmd() approach is that it is now
171 possible to adapt to multiple technologies on each platform and take
172 advantage of each to the fullest.
173
174 \sa QPainter, QPaintDevice::paintEngine(), {The Paint System}
175*/
176
177/*!
178 \enum QPaintEngine::PaintEngineFeature
179
180 This enum is used to describe the features or capabilities that the
181 paint engine has. If a feature is not supported by the engine,
182 QPainter will do a best effort to emulate that feature through other
183 means and pass on an alpha blended QImage to the engine with the
184 emulated results. Some features cannot be emulated: AlphaBlend and PorterDuff.
185
186 \value AlphaBlend The engine can alpha blend primitives.
187 \value Antialiasing The engine can use antialising to improve the appearance
188 of rendered primitives.
189 \value BlendModes The engine supports blending modes.
190 \value BrushStroke The engine supports drawing strokes that
191 contain brushes as fills, not just solid
192 colors (e.g. a dashed gradient line of
193 width 2).
194 \value ConicalGradientFill The engine supports conical gradient fills.
195 \value ConstantOpacity The engine supports the feature provided by
196 QPainter::setOpacity().
197 \value LinearGradientFill The engine supports linear gradient fills.
198 \value MaskedBrush The engine is capable of rendering brushes that has a
199 texture with an alpha channel or a mask.
200 \value ObjectBoundingModeGradients The engine has native support for gradients
201 with coordinate mode QGradient::ObjectBoundingMode.
202 Otherwise, if QPaintEngine::PatternTransform is
203 supported, object bounding mode gradients are
204 converted to gradients with coordinate mode
205 QGradient::LogicalMode and a brush transform for
206 the coordinate mapping.
207 \value PainterPaths The engine has path support.
208 \value PaintOutsidePaintEvent The engine is capable of painting outside of
209 paint events.
210 \value PatternBrush The engine is capable of rendering brushes with
211 the brush patterns specified in Qt::BrushStyle.
212 \value PatternTransform The engine has support for transforming brush
213 patterns.
214 \value PerspectiveTransform The engine has support for performing perspective
215 transformations on primitives.
216 \value PixmapTransform The engine can transform pixmaps, including
217 rotation and shearing.
218 \value PorterDuff The engine supports Porter-Duff operations
219 \value PrimitiveTransform The engine has support for transforming
220 drawing primitives.
221 \value RadialGradientFill The engine supports radial gradient fills.
222 \value RasterOpModes The engine supports bitwise raster operations.
223 \value AllFeatures All of the above features. This enum value is usually
224 used as a bit mask.
225*/
226
227/*!
228 \enum QPaintEngine::PolygonDrawMode
229
230 \value OddEvenMode The polygon should be drawn using OddEven fill
231 rule.
232
233 \value WindingMode The polygon should be drawn using Winding fill rule.
234
235 \value ConvexMode The polygon is a convex polygon and can be drawn
236 using specialized algorithms where available.
237
238 \value PolylineMode Only the outline of the polygon should be
239 drawn.
240
241*/
242
243/*!
244 \enum QPaintEngine::DirtyFlag
245
246 \value DirtyPen The pen is dirty and needs to be updated.
247
248 \value DirtyBrush The brush is dirty and needs to be updated.
249
250 \value DirtyBrushOrigin The brush origin is dirty and needs to
251 updated.
252
253 \value DirtyFont The font is dirty and needs to be updated.
254
255 \value DirtyBackground The background is dirty and needs to be
256 updated.
257
258 \value DirtyBackgroundMode The background mode is dirty and needs
259 to be updated.
260
261 \value DirtyTransform The transform is dirty and needs to be
262 updated.
263
264 \value DirtyClipRegion The clip region is dirty and needs to be
265 updated.
266
267 \value DirtyClipPath The clip path is dirty and needs to be
268 updated.
269
270 \value DirtyHints The render hints is dirty and needs to be
271 updated.
272
273 \value DirtyCompositionMode The composition mode is dirty and
274 needs to be updated.
275
276 \value DirtyClipEnabled Whether clipping is enabled or not is
277 dirty and needs to be updated.
278
279 \value DirtyOpacity The constant opacity has changed and needs to
280 be updated as part of the state change in
281 QPaintEngine::updateState().
282
283 \value AllDirty Convenience enum used internally.
284
285 These types are used by QPainter to trigger lazy updates of the
286 various states in the QPaintEngine using
287 QPaintEngine::updateState().
288
289 A paint engine must update every dirty state.
290*/
291
292/*!
293 \fn void QPaintEngine::syncState()
294
295 \internal
296
297 Updates all dirty states in this engine. This function should ONLY
298 be used when drawing with native handles directly and immediate sync
299 from QPainters state to the native state is required.
300*/
301void QPaintEngine::syncState()
302{
303 Q_ASSERT(state);
304 updateState(*state);
305}
306
307static QPaintEngine *qt_polygon_recursion = 0;
308struct QT_Point {
309 int x;
310 int y;
311};
312
313/*!
314 \fn void QPaintEngine::drawPolygon(const QPointF *points, int pointCount,
315 PolygonDrawMode mode)
316
317 Reimplement this virtual function to draw the polygon defined
318 by the \a pointCount first points in \a points, using mode \a
319 mode.
320
321 \note At least one of the drawPolygon() functions must be reimplemented.
322*/
323void QPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode)
324{
325 Q_ASSERT_X(qt_polygon_recursion != this, "QPaintEngine::drawPolygon",
326 "At least one drawPolygon function must be implemented");
327 qt_polygon_recursion = this;
328 Q_ASSERT(sizeof(QT_Point) == sizeof(QPoint));
329 QVarLengthArray<QT_Point> p(pointCount);
330 for (int i = 0; i < pointCount; ++i) {
331 p[i].x = qRound(points[i].x());
332 p[i].y = qRound(points[i].y());
333 }
334 drawPolygon((QPoint *)p.data(), pointCount, mode);
335 qt_polygon_recursion = 0;
336}
337
338struct QT_PointF {
339 qreal x;
340 qreal y;
341};
342/*!
343 \overload
344
345 Reimplement this virtual function to draw the polygon defined by the
346 \a pointCount first points in \a points, using mode \a mode.
347
348 \note At least one of the drawPolygon() functions must be reimplemented.
349*/
350void QPaintEngine::drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode)
351{
352 Q_ASSERT_X(qt_polygon_recursion != this, "QPaintEngine::drawPolygon",
353 "At least one drawPolygon function must be implemented");
354 qt_polygon_recursion = this;
355 Q_ASSERT(sizeof(QT_PointF) == sizeof(QPointF));
356 QVarLengthArray<QT_PointF> p(pointCount);
357 for (int i=0; i<pointCount; ++i) {
358 p[i].x = points[i].x();
359 p[i].y = points[i].y();
360 }
361 drawPolygon((QPointF *)p.data(), pointCount, mode);
362 qt_polygon_recursion = 0;
363}
364
365/*!
366 \enum QPaintEngine::Type
367
368 \value X11
369 \value Windows
370 \value MacPrinter
371 \value CoreGraphics Mac OS X's Quartz2D (CoreGraphics)
372 \value QuickDraw Mac OS X's QuickDraw
373 \value QWindowSystem Qt for Embedded Linux
374 \value PostScript
375 \value OpenGL
376 \value Picture QPicture format
377 \value SVG Scalable Vector Graphics XML format
378 \value Raster
379 \value Direct3D Windows only, Direct3D based engine
380 \value Pdf Portable Document Format
381 \value OpenVG
382 \value User First user type ID
383 \value MaxUser Last user type ID
384*/
385
386/*!
387 \fn bool QPaintEngine::isActive() const
388
389 Returns true if the paint engine is actively drawing; otherwise
390 returns false.
391
392 \sa setActive()
393*/
394
395/*!
396 \fn void QPaintEngine::setActive(bool state)
397
398 Sets the active state of the paint engine to \a state.
399
400 \sa isActive()
401*/
402
403/*!
404 \fn bool QPaintEngine::begin(QPaintDevice *pdev)
405
406 Reimplement this function to initialise your paint engine when
407 painting is to start on the paint device \a pdev. Return true if
408 the initialization was successful; otherwise return false.
409
410 \sa end() isActive()
411*/
412
413/*!
414 \fn bool QPaintEngine::end()
415
416 Reimplement this function to finish painting on the current paint
417 device. Return true if painting was finished successfully;
418 otherwise return false.
419
420 \sa begin() isActive()
421*/
422
423
424/*!
425 Draws the first \a pointCount points in the buffer \a points
426*/
427void QPaintEngine::drawPoints(const QPointF *points, int pointCount)
428{
429 QPainter *p = painter();
430 if (!p)
431 return;
432
433 qreal penWidth = p->pen().widthF();
434 if (penWidth == 0)
435 penWidth = 1;
436
437 bool ellipses = p->pen().capStyle() == Qt::RoundCap;
438
439 p->save();
440
441 QTransform transform;
442 if (p->pen().isCosmetic()) {
443 transform = p->transform();
444 p->setTransform(QTransform());
445 }
446
447 p->setBrush(p->pen().brush());
448 p->setPen(Qt::NoPen);
449
450 for (int i=0; i<pointCount; ++i) {
451 QPointF pos = transform.map(points[i]);
452 QRectF rect(pos.x() - penWidth / 2, pos.y() - penWidth / 2, penWidth, penWidth);
453
454 if (ellipses)
455 p->drawEllipse(rect);
456 else
457 p->drawRect(rect);
458 }
459
460 p->restore();
461}
462
463
464/*!
465 Draws the first \a pointCount points in the buffer \a points
466
467 The default implementation converts the first \a pointCount QPoints in \a points
468 to QPointFs and calls the floating point version of drawPoints.
469
470*/
471void QPaintEngine::drawPoints(const QPoint *points, int pointCount)
472{
473 Q_ASSERT(sizeof(QT_PointF) == sizeof(QPointF));
474 QT_PointF fp[256];
475 while (pointCount) {
476 int i = 0;
477 while (i < pointCount && i < 256) {
478 fp[i].x = points[i].x();
479 fp[i].y = points[i].y();
480 ++i;
481 }
482 drawPoints((QPointF *)(void *)fp, i);
483 points += i;
484 pointCount -= i;
485 }
486}
487
488/*!
489 \fn void QPaintEngine::drawEllipse(const QRectF &rect)
490
491 Reimplement this function to draw the largest ellipse that can be
492 contained within rectangle \a rect.
493
494 The default implementation calls drawPolygon().
495*/
496void QPaintEngine::drawEllipse(const QRectF &rect)
497{
498 QPainterPath path;
499 path.addEllipse(rect);
500 if (hasFeature(PainterPaths)) {
501 drawPath(path);
502 } else {
503 QPolygonF polygon = path.toFillPolygon();
504 drawPolygon(polygon.data(), polygon.size(), ConvexMode);
505 }
506}
507
508/*!
509 The default implementation of this function calls the floating
510 point version of this function
511*/
512void QPaintEngine::drawEllipse(const QRect &rect)
513{
514 drawEllipse(QRectF(rect));
515}
516
517/*!
518 \fn void QPaintEngine::drawPixmap(const QRectF &r, const QPixmap
519 &pm, const QRectF &sr)
520
521 Reimplement this function to draw the part of the \a pm
522 specified by the \a sr rectangle in the given \a r.
523*/
524
525
526void qt_fill_tile(QPixmap *tile, const QPixmap &pixmap)
527{
528 QPainter p(tile);
529 p.drawPixmap(0, 0, pixmap);
530 int x = pixmap.width();
531 while (x < tile->width()) {
532 p.drawPixmap(x, 0, *tile, 0, 0, x, pixmap.height());
533 x *= 2;
534 }
535 int y = pixmap.height();
536 while (y < tile->height()) {
537 p.drawPixmap(0, y, *tile, 0, 0, tile->width(), y);
538 y *= 2;
539 }
540}
541
542void qt_draw_tile(QPaintEngine *gc, qreal x, qreal y, qreal w, qreal h,
543 const QPixmap &pixmap, qreal xOffset, qreal yOffset)
544{
545 qreal yPos, xPos, drawH, drawW, yOff, xOff;
546 yPos = y;
547 yOff = yOffset;
548 while(yPos < y + h) {
549 drawH = pixmap.height() - yOff; // Cropping first row
550 if (yPos + drawH > y + h) // Cropping last row
551 drawH = y + h - yPos;
552 xPos = x;
553 xOff = xOffset;
554 while(xPos < x + w) {
555 drawW = pixmap.width() - xOff; // Cropping first column
556 if (xPos + drawW > x + w) // Cropping last column
557 drawW = x + w - xPos;
558 if (drawW > 0 && drawH > 0)
559 gc->drawPixmap(QRectF(xPos, yPos, drawW, drawH), pixmap, QRectF(xOff, yOff, drawW, drawH));
560 xPos += drawW;
561 xOff = 0;
562 }
563 yPos += drawH;
564 yOff = 0;
565 }
566}
567
568
569/*!
570 Reimplement this function to draw the \a pixmap in the given \a
571 rect, starting at the given \a p. The pixmap will be
572 drawn repeatedly until the \a rect is filled.
573*/
574void QPaintEngine::drawTiledPixmap(const QRectF &rect, const QPixmap &pixmap, const QPointF &p)
575{
576 int sw = pixmap.width();
577 int sh = pixmap.height();
578
579 if (sw*sh < 8192 && sw*sh < 16*rect.width()*rect.height()) {
580 int tw = sw, th = sh;
581 while (tw*th < 32678 && tw < rect.width()/2)
582 tw *= 2;
583 while (tw*th < 32678 && th < rect.height()/2)
584 th *= 2;
585 QPixmap tile;
586 if (pixmap.depth() == 1) {
587 tile = QBitmap(tw, th);
588 } else {
589 tile = QPixmap(tw, th);
590 if (pixmap.hasAlphaChannel())
591 tile.fill(Qt::transparent);
592 }
593 qt_fill_tile(&tile, pixmap);
594 qt_draw_tile(this, rect.x(), rect.y(), rect.width(), rect.height(), tile, p.x(), p.y());
595 } else {
596 qt_draw_tile(this, rect.x(), rect.y(), rect.width(), rect.height(), pixmap, p.x(), p.y());
597 }
598}
599
600/*!
601 \fn void QPaintEngine::drawImage(const QRectF &rectangle, const QImage
602 &image, const QRectF &sr, Qt::ImageConversionFlags flags)
603
604 Reimplement this function to draw the part of the \a image
605 specified by the \a sr rectangle in the given \a rectangle using
606 the given conversion flags \a flags, to convert it to a pixmap.
607*/
608
609void QPaintEngine::drawImage(const QRectF &r, const QImage &image, const QRectF &sr,
610 Qt::ImageConversionFlags flags)
611{
612 QRectF baseSize(0, 0, image.width(), image.height());
613 QImage im = image;
614 if (baseSize != sr)
615 im = im.copy(qFloor(sr.x()), qFloor(sr.y()),
616 qCeil(sr.width()), qCeil(sr.height()));
617 QPixmap pm = QPixmap::fromImage(im, flags);
618 drawPixmap(r, pm, QRectF(QPointF(0, 0), pm.size()));
619}
620
621/*!
622 \fn Type QPaintEngine::type() const
623
624 Reimplement this function to return the paint engine \l{Type}.
625*/
626
627/*!
628 \fn void QPaintEngine::fix_neg_rect(int *x, int *y, int *w, int *h);
629
630 \internal
631*/
632
633/*!
634 \fn bool QPaintEngine::testDirty(DirtyFlags df)
635
636 \internal
637*/
638
639/*!
640 \fn void QPaintEngine::clearDirty(DirtyFlags df)
641
642 \internal
643*/
644
645/*!
646 \fn void QPaintEngine::setDirty(DirtyFlags df)
647
648 \internal
649*/
650
651/*!
652 \fn bool QPaintEngine::hasFeature(PaintEngineFeatures feature) const
653
654 Returns true if the paint engine supports the specified \a
655 feature; otherwise returns false.
656*/
657
658/*!
659 \fn bool QPaintEngine::isExtended() const
660
661 \internal
662
663 Returns true if the paint engine is a QPaintEngineEx derivative.
664*/
665
666/*!
667 \fn void QPaintEngine::updateState(const QPaintEngineState &state)
668
669 Reimplement this function to update the state of a paint engine.
670
671 When implemented, this function is responsible for checking the
672 paint engine's current \a state and update the properties that are
673 changed. Use the QPaintEngineState::state() function to find out
674 which properties that must be updated, then use the corresponding
675 \l {GetFunction}{get function} to retrieve the current values for
676 the given properties.
677
678 \sa QPaintEngineState
679*/
680
681/*!
682 Creates a paint engine with the featureset specified by \a caps.
683*/
684
685QPaintEngine::QPaintEngine(PaintEngineFeatures caps)
686 : state(0),
687 gccaps(caps),
688 active(0),
689 selfDestruct(false),
690 extended(false),
691 d_ptr(new QPaintEnginePrivate)
692{
693 d_ptr->q_ptr = this;
694}
695
696/*!
697 \internal
698*/
699
700QPaintEngine::QPaintEngine(QPaintEnginePrivate &dptr, PaintEngineFeatures caps)
701 : state(0),
702 gccaps(caps),
703 active(0),
704 selfDestruct(false),
705 extended(false),
706 d_ptr(&dptr)
707{
708 d_ptr->q_ptr = this;
709}
710
711/*!
712 Destroys the paint engine.
713*/
714QPaintEngine::~QPaintEngine()
715{
716 delete d_ptr;
717}
718
719/*!
720 Returns the paint engine's painter.
721*/
722QPainter *QPaintEngine::painter() const
723{
724 return state ? state->painter() : 0;
725}
726
727/*!
728 The default implementation ignores the \a path and does nothing.
729*/
730
731void QPaintEngine::drawPath(const QPainterPath &)
732{
733 if (hasFeature(PainterPaths)) {
734 qWarning("QPaintEngine::drawPath: Must be implemented when feature PainterPaths is set");
735 }
736}
737
738/*!
739 This function draws the text item \a textItem at position \a p. The
740 default implementation of this function converts the text to a
741 QPainterPath and paints the resulting path.
742*/
743
744void QPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem)
745{
746 const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
747
748 QPainterPath path;
749#ifndef Q_WS_MAC
750 path.setFillRule(Qt::WindingFill);
751#endif
752 if (ti.glyphs.numGlyphs)
753 ti.fontEngine->addOutlineToPath(p.x(), p.y(), ti.glyphs, &path, ti.flags);
754 if (!path.isEmpty()) {
755 bool oldAA = painter()->renderHints() & QPainter::Antialiasing;
756 painter()->setRenderHint(QPainter::Antialiasing,
757 bool((painter()->renderHints() & QPainter::TextAntialiasing)
758 && !(painter()->font().styleStrategy() & QFont::NoAntialias)));
759 painter()->fillPath(path, state->pen().brush());
760 painter()->setRenderHint(QPainter::Antialiasing, oldAA);
761 }
762}
763
764/*!
765 The default implementation splits the list of lines in \a lines
766 into \a lineCount separate calls to drawPath() or drawPolygon()
767 depending on the feature set of the paint engine.
768*/
769void QPaintEngine::drawLines(const QLineF *lines, int lineCount)
770{
771 for (int i=0; i<lineCount; ++i) {
772 QPointF pts[2] = { lines[i].p1(), lines[i].p2() };
773
774 if (pts[0] == pts[1]) {
775 if (state->pen().capStyle() != Qt::FlatCap)
776 drawPoints(pts, 1);
777 continue;
778 }
779
780 drawPolygon(pts, 2, PolylineMode);
781 }
782}
783
784/*!
785 \overload
786
787 The default implementation converts the first \a lineCount lines
788 in \a lines to a QLineF and calls the floating point version of
789 this function.
790*/
791void QPaintEngine::drawLines(const QLine *lines, int lineCount)
792{
793 struct PointF {
794 qreal x;
795 qreal y;
796 };
797 struct LineF {
798 PointF p1;
799 PointF p2;
800 };
801 Q_ASSERT(sizeof(PointF) == sizeof(QPointF));
802 Q_ASSERT(sizeof(LineF) == sizeof(QLineF));
803 LineF fl[256];
804 while (lineCount) {
805 int i = 0;
806 while (i < lineCount && i < 256) {
807 fl[i].p1.x = lines[i].x1();
808 fl[i].p1.y = lines[i].y1();
809 fl[i].p2.x = lines[i].x2();
810 fl[i].p2.y = lines[i].y2();
811 ++i;
812 }
813 drawLines((QLineF *)(void *)fl, i);
814 lines += i;
815 lineCount -= i;
816 }
817}
818
819
820/*!
821 \overload
822
823 The default implementation converts the first \a rectCount
824 rectangles in the buffer \a rects to a QRectF and calls the
825 floating point version of this function.
826*/
827void QPaintEngine::drawRects(const QRect *rects, int rectCount)
828{
829 struct RectF {
830 qreal x;
831 qreal y;
832 qreal w;
833 qreal h;
834 };
835 Q_ASSERT(sizeof(RectF) == sizeof(QRectF));
836 RectF fr[256];
837 while (rectCount) {
838 int i = 0;
839 while (i < rectCount && i < 256) {
840 fr[i].x = rects[i].x();
841 fr[i].y = rects[i].y();
842 fr[i].w = rects[i].width();
843 fr[i].h = rects[i].height();
844 ++i;
845 }
846 drawRects((QRectF *)(void *)fr, i);
847 rects += i;
848 rectCount -= i;
849 }
850}
851
852/*!
853 Draws the first \a rectCount rectangles in the buffer \a
854 rects. The default implementation of this function calls drawPath()
855 or drawPolygon() depending on the feature set of the paint engine.
856*/
857void QPaintEngine::drawRects(const QRectF *rects, int rectCount)
858{
859 if (hasFeature(PainterPaths) &&
860 !state->penNeedsResolving() &&
861 !state->brushNeedsResolving()) {
862 for (int i=0; i<rectCount; ++i) {
863 QPainterPath path;
864 path.addRect(rects[i]);
865 if (path.isEmpty())
866 continue;
867 drawPath(path);
868 }
869 } else {
870 for (int i=0; i<rectCount; ++i) {
871 QRectF rf = rects[i];
872 QPointF pts[4] = { QPointF(rf.x(), rf.y()),
873 QPointF(rf.x() + rf.width(), rf.y()),
874 QPointF(rf.x() + rf.width(), rf.y() + rf.height()),
875 QPointF(rf.x(), rf.y() + rf.height()) };
876 drawPolygon(pts, 4, ConvexMode);
877 }
878 }
879}
880
881/*!
882 \internal
883 Sets the paintdevice that this engine operates on to \a device
884*/
885void QPaintEngine::setPaintDevice(QPaintDevice *device)
886{
887 d_func()->pdev = device;
888}
889
890/*!
891 Returns the device that this engine is painting on, if painting is
892 active; otherwise returns 0.
893*/
894QPaintDevice *QPaintEngine::paintDevice() const
895{
896 return d_func()->pdev;
897}
898
899#ifdef Q_WS_WIN
900/*!
901 \internal
902
903 Empty default implementation.
904*/
905
906HDC QPaintEngine::getDC() const
907{
908 return 0;
909}
910
911
912/*!
913 \internal
914
915 Empty default implementation.
916*/
917
918void QPaintEngine::releaseDC(HDC) const
919{
920}
921
922#endif
923
924/*!
925 \internal
926
927 Returns the offset from the painters origo to the engines
928 origo. This value is used by QPainter for engines who have
929 internal double buffering.
930
931 This function only makes sense when the engine is active.
932*/
933QPoint QPaintEngine::coordinateOffset() const
934{
935 return QPoint();
936}
937
938/*!
939 \internal
940
941 Sets the system clip for this engine. The system clip defines the
942 basis area that the engine has to draw in. All clips that are
943 set will be be an intersection with the system clip.
944
945 Reset the systemclip to no clip by setting an empty region.
946*/
947void QPaintEngine::setSystemClip(const QRegion &region)
948{
949 Q_D(QPaintEngine);
950 d->systemClip = region;
951 // Be backward compatible and only call d->systemStateChanged()
952 // if we currently have a system transform set.
953 if (d->hasSystemTransform) {
954 d->transformSystemClip();
955 d->systemStateChanged();
956 }
957}
958
959/*!
960 \internal
961
962 Returns the system clip. The system clip is read only while the
963 painter is active. An empty region indicates that system clip
964 is not in use.
965*/
966
967QRegion QPaintEngine::systemClip() const
968{
969 return d_func()->systemClip;
970}
971
972/*!
973 \internal
974
975 Sets the target rect for drawing within the backing store. This
976 function should ONLY be used by the backing store.
977*/
978void QPaintEngine::setSystemRect(const QRect &rect)
979{
980 if (isActive()) {
981 qWarning("QPaintEngine::setSystemRect: Should not be changed while engine is active");
982 return;
983 }
984 d_func()->systemRect = rect;
985}
986
987/*!
988 \internal
989
990 Retreives the rect for drawing within the backing store. This
991 function should ONLY be used by the backing store.
992 */
993QRect QPaintEngine::systemRect() const
994{
995 return d_func()->systemRect;
996}
997
998void QPaintEnginePrivate::drawBoxTextItem(const QPointF &p, const QTextItemInt &ti)
999{
1000 if (!ti.glyphs.numGlyphs)
1001 return;
1002
1003 // any fixes here should probably also be done in QFontEngineBox::draw
1004 const int size = qRound(ti.fontEngine->ascent());
1005 QVarLengthArray<QFixedPoint> positions;
1006 QVarLengthArray<glyph_t> glyphs;
1007 QTransform matrix;
1008 matrix.translate(p.x(), p.y() - size);
1009 ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
1010 if (glyphs.size() == 0)
1011 return;
1012
1013 QSize s(size - 3, size - 3);
1014
1015 QPainter *painter = q_func()->state->painter();
1016 painter->save();
1017 painter->setBrush(Qt::NoBrush);
1018 QPen pen = painter->pen();
1019 pen.setWidthF(ti.fontEngine->lineThickness().toReal());
1020 painter->setPen(pen);
1021 for (int k = 0; k < positions.size(); k++)
1022 painter->drawRect(QRectF(positions[k].toPointF(), s));
1023 painter->restore();
1024}
1025
1026QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.