Qt 4.8
qregion_mac.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 
42 #include <private/qt_mac_p.h>
43 #include "qcoreapplication.h"
44 #include <qlibrary.h>
45 
47 
49 
50 #if defined(Q_WS_MAC32) && !defined(QT_MAC_USE_COCOA)
51 #define RGN_CACHE_SIZE 200
52 #ifdef RGN_CACHE_SIZE
53 static bool rgncache_init = false;
54 static int rgncache_used;
55 static RgnHandle rgncache[RGN_CACHE_SIZE];
56 static void qt_mac_cleanup_rgncache()
57 {
58  rgncache_init = false;
59  for(int i = 0; i < RGN_CACHE_SIZE; ++i) {
60  if(rgncache[i]) {
61  --rgncache_used;
62  DisposeRgn(rgncache[i]);
63  rgncache[i] = 0;
64  }
65  }
66 }
67 #endif
68 
70 {
71 #ifdef RGN_CACHE_SIZE
72  if(!rgncache_init) {
73  rgncache_used = 0;
74  rgncache_init = true;
75  for(int i = 0; i < RGN_CACHE_SIZE; ++i)
76  rgncache[i] = 0;
77  qAddPostRoutine(qt_mac_cleanup_rgncache);
78  } else if(rgncache_used) {
79  for(int i = 0; i < RGN_CACHE_SIZE; ++i) {
80  if(rgncache[i]) {
81  RgnHandle ret = rgncache[i];
82  SetEmptyRgn(ret);
83  rgncache[i] = 0;
84  --rgncache_used;
85  return ret;
86  }
87  }
88  }
89 #endif
90  return NewRgn();
91 }
92 
94 {
95 #ifdef RGN_CACHE_SIZE
96  if(rgncache_init && rgncache_used < RGN_CACHE_SIZE) {
97  for(int i = 0; i < RGN_CACHE_SIZE; ++i) {
98  if(!rgncache[i]) {
99  ++rgncache_used;
100  rgncache[i] = r;
101  return;
102  }
103  }
104  }
105 #endif
106  DisposeRgn(r);
107 }
108 
109 static OSStatus qt_mac_get_rgn_rect(UInt16 msg, RgnHandle, const Rect *rect, void *reg)
110 {
111  if(msg == kQDRegionToRectsMsgParse) {
112  QRect rct(rect->left, rect->top, (rect->right - rect->left), (rect->bottom - rect->top));
113  if(!rct.isEmpty())
114  *((QRegion *)reg) += rct;
115  }
116  return noErr;
117 }
118 
120 {
121  return QRegion::fromQDRgn(rgn);
122 }
123 
124 QRegion QRegion::fromQDRgn(RgnHandle rgn)
125 {
126  QRegion ret;
127  ret.detach();
128  OSStatus oss = QDRegionToRects(rgn, kQDParseRegionFromTopLeft, qt_mac_get_rgn_rect, (void *)&ret);
129  if(oss != noErr)
130  return QRegion();
131  return ret;
132 }
133 
141 RgnHandle QRegion::toQDRgn() const
142 {
143  RgnHandle rgnHandle = qt_mac_get_rgn();
144  if(d->qt_rgn && d->qt_rgn->numRects) {
145  RgnHandle tmp_rgn = qt_mac_get_rgn();
146  int n = d->qt_rgn->numRects;
147  const QRect *qt_r = (n == 1) ? &d->qt_rgn->extents : d->qt_rgn->rects.constData();
148  while (n--) {
149  SetRectRgn(tmp_rgn,
150  qMax(SHRT_MIN, qt_r->x()),
151  qMax(SHRT_MIN, qt_r->y()),
152  qMin(SHRT_MAX, qt_r->right() + 1),
153  qMin(SHRT_MAX, qt_r->bottom() + 1));
154  UnionRgn(rgnHandle, tmp_rgn, rgnHandle);
155  ++qt_r;
156  }
157  qt_mac_dispose_rgn(tmp_rgn);
158  }
159  return rgnHandle;
160 }
161 
170 RgnHandle QRegion::toQDRgnForUpdate_sys() const
171 {
172  RgnHandle rgnHandle = qt_mac_get_rgn();
173  if(d->qt_rgn && d->qt_rgn->numRects) {
174  RgnHandle tmp_rgn = qt_mac_get_rgn();
175  int n = d->qt_rgn->numRects;
176  const QRect *qt_r = (n == 1) ? &d->qt_rgn->extents : d->qt_rgn->rects.constData();
177  while (n--) {
178 
179  // detect overflow. Tested for use with HIViewSetNeedsDisplayInRegion
180  // in QWidgetPrivate::update_sys().
181  enum { HIViewSetNeedsDisplayInRegionOverflow = 10000 }; // empirically determined conservative value
182  if (qt_r->right() > HIViewSetNeedsDisplayInRegionOverflow || qt_r->bottom() > HIViewSetNeedsDisplayInRegionOverflow) {
183  qt_mac_dispose_rgn(tmp_rgn);
184  qt_mac_dispose_rgn(rgnHandle);
185  return 0;
186  }
187 
188  SetRectRgn(tmp_rgn,
189  qMax(SHRT_MIN, qt_r->x()),
190  qMax(SHRT_MIN, qt_r->y()),
191  qMin(SHRT_MAX, qt_r->right() + 1),
192  qMin(SHRT_MAX, qt_r->bottom() + 1));
193  UnionRgn(rgnHandle, tmp_rgn, rgnHandle);
194  ++qt_r;
195  }
196  qt_mac_dispose_rgn(tmp_rgn);
197  }
198  return rgnHandle;
199 }
200 
201 #endif
202 
203 #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
204 OSStatus QRegion::shape2QRegionHelper(int inMessage, HIShapeRef,
205  const CGRect *inRect, void *inRefcon)
206 {
207  QRegion *region = static_cast<QRegion *>(inRefcon);
208  if (!region)
209  return paramErr;
210 
211  switch (inMessage) {
212  case kHIShapeEnumerateRect:
213  *region += QRect(inRect->origin.x, inRect->origin.y,
214  inRect->size.width, inRect->size.height);
215  break;
216  case kHIShapeEnumerateInit:
217  // Assume the region is already setup correctly
218  case kHIShapeEnumerateTerminate:
219  default:
220  break;
221  }
222  return noErr;
223 }
224 #endif
225 
234 HIMutableShapeRef QRegion::toHIMutableShape() const
235 {
236  HIMutableShapeRef shape = HIShapeCreateMutable();
237 #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
239  if (d->qt_rgn && d->qt_rgn->numRects) {
240  int n = d->qt_rgn->numRects;
241  const QRect *qt_r = (n == 1) ? &d->qt_rgn->extents : d->qt_rgn->rects.constData();
242  while (n--) {
243  CGRect cgRect = CGRectMake(qt_r->x(), qt_r->y(), qt_r->width(), qt_r->height());
244  HIShapeUnionWithRect(shape, &cgRect);
245  ++qt_r;
246  }
247  }
248  } else
249 #endif
250  {
251 #ifndef QT_MAC_USE_COCOA
252  QCFType<HIShapeRef> qdShape = HIShapeCreateWithQDRgn(QMacSmartQuickDrawRegion(toQDRgn()));
253  HIShapeUnion(qdShape, shape, shape);
254 #endif
255  }
256  return shape;
257 }
258 
259 #if !defined(Q_WS_MAC64) && !defined(QT_MAC_USE_COCOA)
262 #endif
263 
264 
265 QRegion QRegion::fromHIShapeRef(HIShapeRef shape)
266 {
267  QRegion returnRegion;
268  returnRegion.detach();
269  // Begin gratuitous #if-defery
270 #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
271 # ifndef Q_WS_MAC64
273 # endif
274  HIShapeEnumerate(shape, kHIShapeParseFromTopLeft, shape2QRegionHelper, &returnRegion);
275 # ifndef Q_WS_MAC64
276  } else
277 # endif
278 #endif
279  {
280 #if !defined(Q_WS_MAC64) && !defined(QT_MAC_USE_COCOA)
281  if (ptrHIShapeGetAsQDRgn == 0) {
282  QLibrary library(QLatin1String("/System/Library/Frameworks/Carbon.framework/Carbon"));
284  ptrHIShapeGetAsQDRgn = reinterpret_cast<PtrHIShapeGetAsQDRgn>(library.resolve("HIShapeGetAsQDRgn"));
285  }
286  RgnHandle rgn = qt_mac_get_rgn();
287  ptrHIShapeGetAsQDRgn(shape, rgn);
288  returnRegion = QRegion::fromQDRgn(rgn);
289  qt_mac_dispose_rgn(rgn);
290 #endif
291  }
292  return returnRegion;
293 }
294 
void detach()
Definition: qregion.cpp:300
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
#define Q_GUI_EXPORT
Definition: qglobal.h:1450
int width() const
Returns the width of the rectangle.
Definition: qrect.h:303
QRegion qt_mac_convert_mac_region(RgnHandle rgn)
struct __HIShape * HIMutableShapeRef
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
QRegionPrivate * qt_rgn
Definition: qregion.h:211
const struct __HIShape * HIShapeRef
void * resolve(const char *symbol)
Returns the address of the exported symbol symbol.
Definition: qlibrary.cpp:1155
int height() const
Returns the height of the rectangle.
Definition: qrect.h:306
int bottom() const
Returns the y-coordinate of the rectangle&#39;s bottom edge.
Definition: qrect.h:249
QRegion()
Constructs an empty region.
Definition: qregion.cpp:3961
#define Q_BASIC_ATOMIC_INITIALIZER(a)
Definition: qbasicatomic.h:218
static struct QRegionData shared_empty
Definition: qregion.h:218
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
Definition: qglobal.h:1217
RgnHandle qt_mac_get_rgn()
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
static PtrHIShapeGetAsQDRgn ptrHIShapeGetAsQDRgn
OSStatus(* PtrHIShapeGetAsQDRgn)(HIShapeRef, RgnHandle)
The QRegion class specifies a clip region for a painter.
Definition: qregion.h:68
signed long OSStatus
struct OpaqueRgnHandle * RgnHandle
QVector< QRect > rects
Definition: qregion.cpp:1227
struct CGRect CGRect
int right() const
Returns the x-coordinate of the rectangle&#39;s right edge.
Definition: qrect.h:246
int y() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:255
int x() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:252
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:58
void setLoadHints(LoadHints hints)
Definition: qlibrary.cpp:1304
static const MacVersion MacintoshVersion
the version of the Macintosh operating system on which the application is run (Mac only)...
Definition: qglobal.h:1646
const T * constData() const
Returns a const pointer to the data stored in the vector.
Definition: qvector.h:154
struct QRegionData * d
Definition: qregion.h:217
void qAddPostRoutine(QtCleanUpFunction ptr)
Adds a global routine that will be called from the QApplication destructor.
The QLibrary class loads shared libraries at runtime.
Definition: qlibrary.h:62
void qt_mac_dispose_rgn(RgnHandle r)