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

Last change on this file since 1166 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

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