Qt 4.8
qpen.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 #include "qpen.h"
42 #include "qpen_p.h"
43 #include "qdatastream.h"
44 #include "qvariant.h"
45 #include "qbrush.h"
46 
47 #include <qdebug.h>
48 
50 
52 
233 inline QPenPrivate::QPenPrivate(const QBrush &_brush, qreal _width, Qt::PenStyle penStyle,
234  Qt::PenCapStyle _capStyle, Qt::PenJoinStyle _joinStyle)
235  : dashOffset(0), miterLimit(2),
236  cosmetic(false)
237 {
238  ref = 1;
239  width = _width;
240  brush = _brush;
241  style = penStyle;
242  capStyle = _capStyle;
243  joinStyle = _joinStyle;
244 }
245 
248 
249 #ifndef QT_NO_THREAD
250 // Special deleter that only deletes if the ref-count goes to zero
251 template <>
253 {
254 public:
257  : globalStatic(_globalStatic)
258  { }
259 
261  {
262  if (!globalStatic.pointer->ref.deref())
263  delete globalStatic.pointer;
264  globalStatic.pointer = 0;
265  globalStatic.destroyed = true;
266  }
267 };
268 #endif
269 
270 Q_GLOBAL_STATIC_WITH_ARGS(QPenData, defaultPenInstance,
274 
280 {
281  d = defaultPenInstance();
282  d->ref.ref();
283 }
284 
292 {
293  if (style == Qt::NoPen) {
294  d = nullPenInstance();
295  d->ref.ref();
296  } else {
298  }
299 }
300 
301 
308 QPen::QPen(const QColor &color)
309 {
311 }
312 
313 
327 {
328  d = new QPenData(brush, width, s, c, j);
329 }
330 
340 QPen::QPen(const QPen &p)
341 {
342  d = p.d;
343  d->ref.ref();
344 }
345 
346 
352 {
353  if (!d->ref.deref())
354  delete d;
355 }
356 
371 {
372  if (d->ref == 1)
373  return;
374 
375  QPenData *x = new QPenData(*static_cast<QPenData *>(d));
376  if (!d->ref.deref())
377  delete d;
378  x->ref = 1;
379  d = x;
380 }
381 
382 
394 {
395  qAtomicAssign(d, p.d);
396  return *this;
397 }
398 
413 QPen::operator QVariant() const
414 {
415  return QVariant(QVariant::Pen, this);
416 }
417 
429 {
430  return d->style;
431 }
451 {
452  if (d->style == s)
453  return;
454  detach();
455  d->style = s;
456  QPenData *dd = static_cast<QPenData *>(d);
457  dd->dashPattern.clear();
458  dd->dashOffset = 0;
459 }
460 
467 {
468  QPenData *dd = static_cast<QPenData *>(d);
469  if (d->style == Qt::SolidLine || d->style == Qt::NoPen) {
470  return QVector<qreal>();
471  } else if (dd->dashPattern.isEmpty()) {
472  const qreal space = 2;
473  const qreal dot = 1;
474  const qreal dash = 4;
475 
476  switch (d->style) {
477  case Qt::DashLine:
478  dd->dashPattern << dash << space;
479  break;
480  case Qt::DotLine:
481  dd->dashPattern << dot << space;
482  break;
483  case Qt::DashDotLine:
484  dd->dashPattern << dash << space << dot << space;
485  break;
486  case Qt::DashDotDotLine:
487  dd->dashPattern << dash << space << dot << space << dot << space;
488  break;
489  default:
490  break;
491  }
492  }
493  return dd->dashPattern;
494 }
495 
526 {
527  if (pattern.isEmpty())
528  return;
529  detach();
530 
531  QPenData *dd = static_cast<QPenData *>(d);
532  dd->dashPattern = pattern;
533  d->style = Qt::CustomDashLine;
534 
535  if ((dd->dashPattern.size() % 2) == 1) {
536  qWarning("QPen::setDashPattern: Pattern not of even length");
537  dd->dashPattern << 1;
538  }
539 }
540 
541 
548 {
549  QPenData *dd = static_cast<QPenData *>(d);
550  return dd->dashOffset;
551 }
571 {
572  if (qFuzzyCompare(offset, static_cast<QPenData *>(d)->dashOffset))
573  return;
574  detach();
575  QPenData *dd = static_cast<QPenData *>(d);
576  dd->dashOffset = offset;
577  if (d->style != Qt::CustomDashLine) {
578  dd->dashPattern = dashPattern();
579  d->style = Qt::CustomDashLine;
580  }
581 }
582 
590 {
591  const QPenData *dd = static_cast<QPenData *>(d);
592  return dd->miterLimit;
593 }
594 
612 {
613  detach();
614  QPenData *dd = static_cast<QPenData *>(d);
615  dd->miterLimit = limit;
616 }
617 
618 
630 int QPen::width() const
631 {
632  return qRound(d->width);
633 }
634 
646 {
647  return d->width;
648 }
649 
668 {
669  if (width < 0)
670  qWarning("QPen::setWidth: Setting a pen width with a negative value is not defined");
671  if ((qreal)width == d->width)
672  return;
673  detach();
674  d->width = width;
675 }
676 
691 {
692  if (width < 0.f)
693  qWarning("QPen::setWidthF: Setting a pen width with a negative value is not defined");
694  if (qAbs(d->width - width) < 0.00000001f)
695  return;
696  detach();
697  d->width = width;
698 }
699 
700 
707 {
708  return d->capStyle;
709 }
710 
724 {
725  if (d->capStyle == c)
726  return;
727  detach();
728  d->capStyle = c;
729 }
730 
737 {
738  return d->joinStyle;
739 }
740 
754 {
755  if (d->joinStyle == j)
756  return;
757  detach();
758  d->joinStyle = j;
759 }
760 
772 {
773  return d->brush.color();
774 }
775 
787 void QPen::setColor(const QColor &c)
788 {
789  detach();
790  d->brush = QBrush(c);
791 }
792 
793 
798 {
799  return d->brush;
800 }
801 
809 {
810  detach();
811  d->brush = brush;
812 }
813 
814 
820 bool QPen::isSolid() const
821 {
822  return d->brush.style() == Qt::SolidPattern;
823 }
824 
825 
840 bool QPen::isCosmetic() const
841 {
842  QPenData *dd = static_cast<QPenData *>(d);
843  return (dd->cosmetic == true) || d->width == 0;
844 }
845 
846 
855 {
856  detach();
857  QPenData *dd = static_cast<QPenData *>(d);
858  dd->cosmetic = cosmetic;
859 }
860 
861 
862 
889 bool QPen::operator==(const QPen &p) const
890 {
891  QPenData *dd = static_cast<QPenData *>(d);
892  QPenData *pdd = static_cast<QPenData *>(p.d);
893  return (p.d == d)
894  || (p.d->style == d->style
895  && p.d->capStyle == d->capStyle
896  && p.d->joinStyle == d->joinStyle
897  && p.d->width == d->width
898  && pdd->miterLimit == dd->miterLimit
899  && (d->style != Qt::CustomDashLine
900  || (qFuzzyCompare(pdd->dashOffset, dd->dashOffset) &&
901  pdd->dashPattern == dd->dashPattern))
902  && p.d->brush == d->brush
903  && pdd->cosmetic == dd->cosmetic);
904 }
905 
906 
914 {
915  return d->ref == 1;
916 }
917 
918 
919 /*****************************************************************************
920  QPen stream functions
921  *****************************************************************************/
922 #ifndef QT_NO_DATASTREAM
923 
937 {
938  QPenData *dd = static_cast<QPenData *>(p.d);
939  if (s.version() < 3) {
940  s << (quint8)p.style();
941  } else if (s.version() < QDataStream::Qt_4_3) {
942  s << (quint8)(p.style() | p.capStyle() | p.joinStyle());
943  } else {
944  s << (quint16)(p.style() | p.capStyle() | p.joinStyle());
945  s << (bool)(dd->cosmetic);
946  }
947 
948  if (s.version() < 7) {
949  s << (quint8)p.width();
950  s << p.color();
951  } else {
952  s << double(p.widthF());
953  s << p.brush();
954  s << double(p.miterLimit());
955  if (sizeof(qreal) == sizeof(double)) {
956  s << p.dashPattern();
957  } else {
958  // ensure that we write doubles here instead of streaming the pattern
959  // directly; otherwise, platforms that redefine qreal might generate
960  // data that cannot be read on other platforms.
961  QVector<qreal> pattern = p.dashPattern();
962  s << quint32(pattern.size());
963  for (int i = 0; i < pattern.size(); ++i)
964  s << double(pattern.at(i));
965  }
966  if (s.version() >= 9)
967  s << double(p.dashOffset());
968  }
969  return s;
970 }
971 
986 {
987  quint16 style;
988  quint8 width8 = 0;
989  double width = 0;
990  QColor color;
991  QBrush brush;
992  double miterLimit = 2;
994  double dashOffset = 0;
995  bool cosmetic = false;
996  if (s.version() < QDataStream::Qt_4_3) {
997  quint8 style8;
998  s >> style8;
999  style = style8;
1000  } else {
1001  s >> style;
1002  s >> cosmetic;
1003  }
1004  if (s.version() < 7) {
1005  s >> width8;
1006  s >> color;
1007  brush = color;
1008  width = width8;
1009  } else {
1010  s >> width;
1011  s >> brush;
1012  s >> miterLimit;
1013  if (sizeof(qreal) == sizeof(double)) {
1014  s >> dashPattern;
1015  } else {
1016  quint32 numDashes;
1017  s >> numDashes;
1018  double dash;
1019  for (quint32 i = 0; i < numDashes; ++i) {
1020  s >> dash;
1021  dashPattern << dash;
1022  }
1023  }
1024  if (s.version() >= 9)
1025  s >> dashOffset;
1026  }
1027 
1028  p.detach();
1029  QPenData *dd = static_cast<QPenData *>(p.d);
1030  dd->width = width;
1031  dd->brush = brush;
1032  dd->style = Qt::PenStyle(style & Qt::MPenStyle);
1033  dd->capStyle = Qt::PenCapStyle(style & Qt::MPenCapStyle);
1035  dd->dashPattern = dashPattern;
1036  dd->miterLimit = miterLimit;
1037  dd->dashOffset = dashOffset;
1038  dd->cosmetic = cosmetic;
1039 
1040  return s;
1041 }
1042 #endif //QT_NO_DATASTREAM
1043 
1044 #ifndef QT_NO_DEBUG_STREAM
1046 {
1047 #ifndef Q_BROKEN_DEBUG_STREAM
1048  const char *PEN_STYLES[] = {
1049  "NoPen",
1050  "SolidLine",
1051  "DashLine",
1052  "DotLine",
1053  "DashDotLine",
1054  "DashDotDotLine",
1055  "CustomDashLine"
1056  };
1057 
1058  dbg.nospace() << "QPen(" << p.width() << ',' << p.brush()
1059  << ',' << PEN_STYLES[p.style()] << ',' << int(p.capStyle())
1060  << ',' << int(p.joinStyle()) << ',' << p.dashPattern()
1061  << ',' << p.dashOffset()
1062  << ',' << p.miterLimit() << ')';
1063  return dbg.space();
1064 #else
1065  qWarning("This compiler doesn't support streaming QPen to QDebug");
1066  return dbg;
1067  Q_UNUSED(p);
1068 #endif
1069 }
1070 #endif
1071 
1084 
1085 #undef QT_COMPILING_QPEN
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:92
The QDebug class provides an output stream for debugging information.
Definition: qdebug.h:62
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition: qcolor.h:67
double d
Definition: qnumeric_p.h:62
static const Qt::PenCapStyle qpen_default_cap
Definition: qpen.cpp:246
double qreal
Definition: qglobal.h:1193
unsigned char c[8]
Definition: qnumeric_p.h:62
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
qreal dashOffset
Definition: qpen_p.h:71
void setBrush(const QBrush &brush)
Sets the brush used to fill strokes generated with this pen to the given brush.
Definition: qpen.cpp:808
qreal miterLimit
Definition: qpen_p.h:72
class QPenPrivate * d
Definition: qpen.h:128
void setCapStyle(Qt::PenCapStyle pcs)
Sets the pen&#39;s cap style to the given style.
Definition: qpen.cpp:723
Qt::PenStyle style() const
Returns the pen style.
Definition: qpen.cpp:428
QDebug & nospace()
Clears the stream&#39;s internal flag that records whether the last character was a space and returns a r...
Definition: qdebug.h:92
QDataStream & operator<<(QDataStream &s, const QPen &p)
Definition: qpen.cpp:936
QAtomicInt ref
Definition: qpen_p.h:64
void detach()
Detaches from shared pen data to make sure that this pen is the only one referring the data...
Definition: qpen.cpp:370
QColor color() const
Returns the color of this pen&#39;s brush.
Definition: qpen.cpp:771
void setCosmetic(bool cosmetic)
Sets this pen to cosmetic or non-cosmetic, depending on the value of cosmetic.
Definition: qpen.cpp:854
Qt::PenCapStyle capStyle
Definition: qpen_p.h:68
static Q_DECL_CONSTEXPR bool qFuzzyCompare(double p1, double p2)
Definition: qglobal.h:2030
bool destroyed
Definition: qglobal.h:1943
unsigned char quint8
Definition: qglobal.h:934
Q_DECL_CONSTEXPR T qAbs(const T &t)
Definition: qglobal.h:1201
The QPen class defines how a QPainter should draw lines and outlines of shapes.
Definition: qpen.h:64
QVector< qreal > dashPattern() const
Returns the dash pattern of this pen.
Definition: qpen.cpp:466
void setDashPattern(const QVector< qreal > &pattern)
Sets the dash pattern for this pen to the given pattern.
Definition: qpen.cpp:525
PenStyle
Definition: qnamespace.h:1134
uint cosmetic
Definition: qpen_p.h:73
PenCapStyle
Definition: qnamespace.h:1147
~QPen()
Destroys the pen.
Definition: qpen.cpp:351
Q_GLOBAL_STATIC_WITH_ARGS(QPenData, defaultPenInstance,(Qt::black, 0, Qt::SolidLine, qpen_default_cap, qpen_default_join)) Q_GLOBAL_STATIC_WITH_ARGS(QPenData
void setColor(const QColor &color)
Sets the color of this pen&#39;s brush to the given color.
Definition: qpen.cpp:787
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
Qt::PenJoinStyle joinStyle
Definition: qpen_p.h:69
void clear()
Removes all the elements from the vector and releases the memory used by the vector.
Definition: qvector.h:347
bool isCosmetic() const
Returns true if the pen is cosmetic; otherwise returns false.
Definition: qpen.cpp:840
nullPenInstance
Definition: qpen.cpp:272
Qt::PenJoinStyle joinStyle() const
Returns the pen&#39;s join style.
Definition: qpen.cpp:736
void setDashOffset(qreal doffset)
Sets the dash offset (the starting point on the dash pattern) for this pen to the offset specified...
Definition: qpen.cpp:570
bool deref()
Atomically decrements the value of this QAtomicInt.
QBasicAtomicPointer< T > pointer
Definition: qglobal.h:1942
unsigned short quint16
Definition: qglobal.h:936
Q_CORE_EXPORT void qWarning(const char *,...)
void setJoinStyle(Qt::PenJoinStyle pcs)
Sets the pen&#39;s join style to the given style.
Definition: qpen.cpp:753
PenJoinStyle
Definition: qnamespace.h:1154
QBrush brush() const
Returns the brush used to fill strokes generated with this pen.
Definition: qpen.cpp:797
bool isDetached()
Definition: qpen.cpp:913
QGlobalStaticDeleter(QGlobalStatic< QPenPrivate > &_globalStatic)
Definition: qpen.cpp:256
bool operator==(const QPen &p) const
Returns true if the pen is equal to the given pen; otherwise false.
Definition: qpen.cpp:889
QPenPrivate QPenData
Definition: qpen.cpp:51
const T & at(int i) const
Returns the item at index position i in the vector.
Definition: qvector.h:350
int version() const
Returns the version number of the data serialization format.
Definition: qdatastream.h:212
int width() const
Returns the pen width with integer precision.
Definition: qpen.cpp:630
The QBrush class defines the fill pattern of shapes drawn by QPainter.
Definition: qbrush.h:76
QVector< qreal > dashPattern
Definition: qpen_p.h:70
QPen & operator=(const QPen &pen)
Assigns the given pen to this pen and returns a reference to this pen.
Definition: qpen.cpp:393
QPen()
Constructs a default black solid line pen with 0 width.
Definition: qpen.cpp:279
void setWidthF(qreal width)
Sets the pen width to the given width in pixels with floating point precision.
Definition: qpen.cpp:690
qreal miterLimit() const
Returns the miter limit of the pen.
Definition: qpen.cpp:589
static const Qt::PenJoinStyle qpen_default_join
Definition: qpen.cpp:247
unsigned int quint32
Definition: qglobal.h:938
qreal widthF() const
Returns the pen width with floating point precision.
Definition: qpen.cpp:645
Definition: qnamespace.h:54
void qAtomicAssign(T *&d, T *x)
This is a helper for the assignment operators of implicitly shared classes.
Definition: qatomic.h:195
qreal width
Definition: qpen_p.h:65
qreal dashOffset() const
Returns the dash offset for the pen.
Definition: qpen.cpp:547
bool isEmpty() const
Returns true if the vector has size 0; otherwise returns false.
Definition: qvector.h:139
The QDataStream class provides serialization of binary data to a QIODevice.
Definition: qdatastream.h:71
QPenPrivate(const QBrush &brush, qreal width, Qt::PenStyle, Qt::PenCapStyle, Qt::PenJoinStyle _joinStyle)
Definition: qpen.cpp:233
Qt::PenCapStyle capStyle() const
Returns the pen&#39;s cap style.
Definition: qpen.cpp:706
QDebug & space()
Writes a space character to the debug stream and returns a reference to the stream.
Definition: qdebug.h:91
Qt::PenStyle style
Definition: qpen_p.h:67
static qreal dot(const QPointF &a, const QPointF &b)
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
int size() const
Returns the number of items in the vector.
Definition: qvector.h:137
QDataStream & operator>>(QDataStream &s, QPen &p)
Definition: qpen.cpp:985
Q_DECL_CONSTEXPR int qRound(qreal d)
Definition: qglobal.h:1203
void setStyle(Qt::PenStyle)
Sets the pen style to the given style.
Definition: qpen.cpp:450
void setMiterLimit(qreal limit)
Sets the miter limit of this pen to the given limit.
Definition: qpen.cpp:611
void setWidth(int width)
Sets the pen width to the given width in pixels with integer precision.
Definition: qpen.cpp:667
bool isSolid() const
Returns true if the pen has a solid fill, otherwise false.
Definition: qpen.cpp:820
QBrush brush
Definition: qpen_p.h:66
QGlobalStatic< QPenPrivate > & globalStatic
Definition: qpen.cpp:255