Warning: That file was not part of the compilation database. It may have many parsing errors.

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 "qpixmap.h"
43#include "qimage.h"
44#include "qapplication.h"
45#include "qbitmap.h"
46#include "qmatrix.h"
47#include "qtransform.h"
48#include "qlibrary.h"
49#include "qvarlengtharray.h"
50#include "qdebug.h"
51#include <private/qdrawhelper_p.h>
52#include <private/qpixmap_mac_p.h>
53#include <private/qpixmap_raster_p.h>
54#include <private/qpaintengine_mac_p.h>
55#include <private/qt_mac_p.h>
56#include <private/qt_cocoa_helpers_mac_p.h>
57#include <private/qapplication_p.h>
58
59#include <limits.h>
60#include <string.h>
61
62QT_BEGIN_NAMESPACE
63
64/*****************************************************************************
65 Externals
66 *****************************************************************************/
67extern const uchar *qt_get_bitflip_array(); //qimage.cpp
68extern CGContextRef qt_mac_cg_context(const QPaintDevice *pdev); //qpaintdevice_mac.cpp
69extern RgnHandle qt_mac_get_rgn(); //qregion_mac.cpp
70extern void qt_mac_dispose_rgn(RgnHandle r); //qregion_mac.cpp
71extern QRegion qt_mac_convert_mac_region(RgnHandle rgn); //qregion_mac.cpp
72
73static int qt_pixmap_serial = 0;
74
75Q_GUI_EXPORT quint32 *qt_mac_pixmap_get_base(const QPixmap *pix)
76{
77 if (QApplicationPrivate::graphics_system_name == QLatin1String("raster"))
78 return reinterpret_cast<quint32 *>(static_cast<QRasterPixmapData*>(pix->data.data())->buffer()->bits());
79 else
80 return static_cast<QMacPixmapData*>(pix->data.data())->pixels;
81}
82
83Q_GUI_EXPORT int qt_mac_pixmap_get_bytes_per_line(const QPixmap *pix)
84{
85 if (QApplicationPrivate::graphics_system_name == QLatin1String("raster"))
86 return static_cast<QRasterPixmapData*>(pix->data.data())->buffer()->bytesPerLine();
87 else
88 return static_cast<QMacPixmapData*>(pix->data.data())->bytesPerRow;
89}
90
91void qt_mac_cgimage_data_free(void *info, const void *memoryToFree, size_t)
92{
93 QMacPixmapData *pmdata = static_cast<QMacPixmapData *>(info);
94 if (!pmdata) {
95 free(const_cast<void *>(memoryToFree));
96 } else {
97 if (QMacPixmapData::validDataPointers.contains(pmdata) == false) {
98 free(const_cast<void *>(memoryToFree));
99 // mark data as freed
100 if (pmdata->pixels == memoryToFree)
101 pmdata->pixels = 0;
102 if (pmdata->pixelsToFree == memoryToFree)
103 pmdata->pixelsToFree = 0;
104 return;
105 }
106 if (pmdata->pixels == pmdata->pixelsToFree) {
107 // something we aren't expecting, just free it.
108 Q_ASSERT(memoryToFree != pmdata->pixelsToFree);
109 free(const_cast<void *>(memoryToFree));
110 } else {
111 free(pmdata->pixelsToFree);
112 pmdata->pixelsToFree = static_cast<quint32 *>(const_cast<void *>(memoryToFree));
113 }
114 pmdata->cg_dataBeingReleased = 0;
115 }
116}
117
118CGImageRef qt_mac_image_to_cgimage(const QImage &image)
119{
120 int bitsPerColor = 8;
121 int bitsPerPixel = 32;
122 if (image.depth() == 1) {
123 bitsPerColor = 1;
124 bitsPerPixel = 1;
125 }
126 QCFType<CGDataProviderRef> provider =
127 CGDataProviderCreateWithData(0, image.bits(), image.bytesPerLine() * image.height(),
128 0);
129
130 uint cgflags = kCGImageAlphaPremultipliedFirst;
131#ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version
132 cgflags |= kCGBitmapByteOrder32Host;
133#endif
134
135 CGImageRef cgImage = CGImageCreate(image.width(), image.height(), bitsPerColor, bitsPerPixel,
136 image.bytesPerLine(),
137 QCoreGraphicsPaintEngine::macGenericColorSpace(),
138 cgflags, provider,
139 0,
140 0,
141 kCGRenderingIntentDefault);
142
143 return cgImage;
144}
145
146/*****************************************************************************
147 QPixmap member functions
148 *****************************************************************************/
149
150static inline QRgb qt_conv16ToRgb(ushort c) {
151 static const int qt_rbits = (565/100);
152 static const int qt_gbits = (565/10%10);
153 static const int qt_bbits = (565%10);
154 static const int qt_red_shift = qt_bbits+qt_gbits-(8-qt_rbits);
155 static const int qt_green_shift = qt_bbits-(8-qt_gbits);
156 static const int qt_neg_blue_shift = 8-qt_bbits;
157 static const int qt_blue_mask = (1<<qt_bbits)-1;
158 static const int qt_green_mask = (1<<(qt_gbits+qt_bbits))-((1<<qt_bbits)-1);
159 static const int qt_red_mask = (1<<(qt_rbits+qt_gbits+qt_bbits))-(1<<(qt_gbits+qt_bbits));
160
161 const int r=(c & qt_red_mask);
162 const int g=(c & qt_green_mask);
163 const int b=(c & qt_blue_mask);
164 const int tr = r >> qt_red_shift;
165 const int tg = g >> qt_green_shift;
166 const int tb = b << qt_neg_blue_shift;
167
168 return qRgb(tr,tg,tb);
169}
170
171QSet<QMacPixmapData*> QMacPixmapData::validDataPointers;
172
173QMacPixmapData::QMacPixmapData(PixelType type)
174 : QPixmapData(type, MacClass), has_alpha(0), has_mask(0),
175 uninit(true), pixels(0), pixelsSize(0), pixelsToFree(0),
176 bytesPerRow(0), cg_data(0), cg_dataBeingReleased(0), cg_mask(0),
177 pengine(0)
178{
179}
180
181QPixmapData *QMacPixmapData::createCompatiblePixmapData() const
182{
183 return new QMacPixmapData(pixelType());
184}
185
186#define BEST_BYTE_ALIGNMENT 16
187#define COMPTUE_BEST_BYTES_PER_ROW(bpr) \
188 (((bpr) + (BEST_BYTE_ALIGNMENT - 1)) & ~(BEST_BYTE_ALIGNMENT - 1))
189
190void QMacPixmapData::resize(int width, int height)
191{
192 setSerialNumber(++qt_pixmap_serial);
193
194 w = width;
195 h = height;
196 is_null = (w <= 0 || h <= 0);
197 d = (pixelType() == BitmapType ? 1 : 32);
198 bool make_null = w <= 0 || h <= 0; // create null pixmap
199 if (make_null || d == 0) {
200 w = 0;
201 h = 0;
202 is_null = true;
203 d = 0;
204 if (!make_null)
205 qWarning("Qt: QPixmap: Invalid pixmap parameters");
206 return;
207 }
208
209 if (w < 1 || h < 1)
210 return;
211
212 //create the pixels
213 bytesPerRow = w * sizeof(quint32); // Minimum bytes per row.
214
215 // Quartz2D likes things as a multple of 16 (for now).
216 bytesPerRow = COMPTUE_BEST_BYTES_PER_ROW(bytesPerRow);
217 macCreatePixels();
218}
219
220#undef COMPUTE_BEST_BYTES_PER_ROW
221
222void QMacPixmapData::fromImage(const QImage &img,
223 Qt::ImageConversionFlags flags)
224{
225 setSerialNumber(++qt_pixmap_serial);
226
227 // the conversion code only handles format >=
228 // Format_ARGB32_Premultiplied at the moment..
229 if (img.format() > QImage::Format_ARGB32_Premultiplied) {
230 QImage image;
231 if (img.hasAlphaChannel())
232 image = img.convertToFormat(QImage::Format_ARGB32_Premultiplied);
233 else
234 image = img.convertToFormat(QImage::Format_RGB32);
235 fromImage(image, flags);
236 return;
237 }
238
239 w = img.width();
240 h = img.height();
241 is_null = (w <= 0 || h <= 0);
242 d = (pixelType() == BitmapType ? 1 : img.depth());
243
244 QImage image = img;
245 int dd = QPixmap::defaultDepth();
246 bool force_mono = (dd == 1 ||
247 (flags & Qt::ColorMode_Mask)==Qt::MonoOnly);
248 if (force_mono) { // must be monochrome
249 if (d != 1) {
250 image = image.convertToFormat(QImage::Format_MonoLSB, flags); // dither
251 d = 1;
252 }
253 } else { // can be both
254 bool conv8 = false;
255 if(d > 8 && dd <= 8) { // convert to 8 bit
256 if ((flags & Qt::DitherMode_Mask) == Qt::AutoDither)
257 flags = (flags & ~Qt::DitherMode_Mask)
258 | Qt::PreferDither;
259 conv8 = true;
260 } else if ((flags & Qt::ColorMode_Mask) == Qt::ColorOnly) {
261 conv8 = d == 1; // native depth wanted
262 } else if (d == 1) {
263 if (image.colorCount() == 2) {
264 QRgb c0 = image.color(0); // Auto: convert to best
265 QRgb c1 = image.color(1);
266 conv8 = qMin(c0,c1) != qRgb(0,0,0) || qMax(c0,c1) != qRgb(255,255,255);
267 } else {
268 // eg. 1-color monochrome images (they do exist).
269 conv8 = true;
270 }
271 }
272 if (conv8) {
273 image = image.convertToFormat(QImage::Format_Indexed8, flags);
274 d = 8;
275 }
276 }
277
278 if (image.depth()==1) {
279 image.setColor(0, QColor(Qt::color0).rgba());
280 image.setColor(1, QColor(Qt::color1).rgba());
281 }
282
283 if (d == 16 || d == 24) {
284 image = image.convertToFormat(QImage::Format_RGB32, flags);
285 fromImage(image, flags);
286 return;
287 }
288
289 // different size or depth, make a new pixmap
290 resize(w, h);
291
292 // exit if resize failed
293 if (is_null)
294 return;
295
296 quint32 *dptr = pixels, *drow;
297 const uint dbpr = bytesPerRow;
298
299 const QImage::Format sfmt = image.format();
300 const unsigned short sbpr = image.bytesPerLine();
301
302 // use const_cast to prevent a detach
303 const uchar *sptr = const_cast<const QImage &>(image).bits(), *srow;
304
305 for (int y = 0; y < h; ++y) {
306 drow = dptr + (y * (dbpr / 4));
307 srow = sptr + (y * sbpr);
308 switch(sfmt) {
309 case QImage::Format_MonoLSB:
310 case QImage::Format_Mono:{
311 for (int x = 0; x < w; ++x) {
312 char one_bit = *(srow + (x / 8));
313 if (sfmt == QImage::Format_Mono)
314 one_bit = one_bit >> (7 - (x % 8));
315 else
316 one_bit = one_bit >> (x % 8);
317 if ((one_bit & 0x01))
318 *(drow+x) = 0xFF000000;
319 else
320 *(drow+x) = 0xFFFFFFFF;
321 }
322 break;
323 }
324 case QImage::Format_Indexed8: {
325 int numColors = image.numColors();
326 if (numColors > 0) {
327 for (int x = 0; x < w; ++x) {
328 int index = *(srow + x);
329 *(drow+x) = PREMUL(image.color(qMin(index, numColors)));
330 }
331 }
332 } break;
333 case QImage::Format_RGB32:
334 for (int x = 0; x < w; ++x)
335 *(drow+x) = *(((quint32*)srow) + x) | 0xFF000000;
336 break;
337 case QImage::Format_ARGB32:
338 case QImage::Format_ARGB32_Premultiplied:
339 for (int x = 0; x < w; ++x) {
340 if(sfmt == QImage::Format_RGB32)
341 *(drow+x) = 0xFF000000 | (*(((quint32*)srow) + x) & 0x00FFFFFF);
342 else if(sfmt == QImage::Format_ARGB32_Premultiplied)
343 *(drow+x) = *(((quint32*)srow) + x);
344 else
345 *(drow+x) = PREMUL(*(((quint32*)srow) + x));
346 }
347 break;
348 default:
349 qWarning("Qt: internal: Oops: Forgot a format [%d] %s:%d", sfmt,
350 __FILE__, __LINE__);
351 break;
352 }
353 }
354 if (sfmt != QImage::Format_RGB32) { //setup the alpha
355 bool alphamap = image.depth() == 32;
356 if (sfmt == QImage::Format_Indexed8) {
357 const QVector<QRgb> rgb = image.colorTable();
358 for (int i = 0, count = image.colorCount(); i < count; ++i) {
359 const int alpha = qAlpha(rgb[i]);
360 if (alpha != 0xff) {
361 alphamap = true;
362 break;
363 }
364 }
365 }
366 macSetHasAlpha(alphamap);
367 }
368 uninit = false;
369}
370
371int get_index(QImage * qi,QRgb mycol)
372{
373 int loopc;
374 for(loopc=0;loopc<qi->colorCount();loopc++) {
375 if(qi->color(loopc)==mycol)
376 return loopc;
377 }
378 qi->setColorCount(qi->colorCount()+1);
379 qi->setColor(qi->colorCount(),mycol);
380 return qi->colorCount();
381}
382
383QImage QMacPixmapData::toImage() const
384{
385 QImage::Format format = QImage::Format_MonoLSB;
386 if (d != 1) //Doesn't support index color modes
387 format = (has_alpha ? QImage::Format_ARGB32_Premultiplied :
388 QImage::Format_RGB32);
389
390 QImage image(w, h, format);
391 // exit if image was not created (out of memory)
392 if (image.isNull())
393 return image;
394 quint32 *sptr = pixels, *srow;
395 const uint sbpr = bytesPerRow;
396 if (format == QImage::Format_MonoLSB) {
397 image.fill(0);
398 image.setColorCount(2);
399 image.setColor(0, QColor(Qt::color0).rgba());
400 image.setColor(1, QColor(Qt::color1).rgba());
401 for (int y = 0; y < h; ++y) {
402 uchar *scanLine = image.scanLine(y);
403 srow = sptr + (y * (sbpr/4));
404 for (int x = 0; x < w; ++x) {
405 if (!(*(srow + x) & RGB_MASK))
406 scanLine[x >> 3] |= (1 << (x & 7));
407 }
408 }
409 } else {
410 for (int y = 0; y < h; ++y) {
411 srow = sptr + (y * (sbpr / 4));
412 memcpy(image.scanLine(y), srow, w * 4);
413 }
414
415 }
416
417 return image;
418}
419
420void QMacPixmapData::fill(const QColor &fillColor)
421
422{
423 { //we don't know what backend to use so we cannot paint here
424 quint32 *dptr = pixels;
425 Q_ASSERT_X(dptr, "QPixmap::fill", "No dptr");
426 const quint32 colr = PREMUL(fillColor.rgba());
427 const int nbytes = bytesPerRow * h;
428 if (!colr) {
429 memset(dptr, 0, nbytes);
430 } else {
431 for (uint i = 0; i < nbytes / sizeof(quint32); ++i)
432 *(dptr + i) = colr;
433 }
434 }
435
436 // If we had an alpha channel from before, don't
437 // switch it off. Only go from no alpha to alpha:
438 if (fillColor.alpha() != 255)
439 macSetHasAlpha(true);
440}
441
442QPixmap QMacPixmapData::alphaChannel() const
443{
444 if (!has_alpha)
445 return QPixmap();
446
447 QMacPixmapData *alpha = new QMacPixmapData(PixmapType);
448 alpha->resize(w, h);
449 macGetAlphaChannel(alpha, false);
450 return QPixmap(alpha);
451}
452
453void QMacPixmapData::setAlphaChannel(const QPixmap &alpha)
454{
455 has_mask = true;
456 QMacPixmapData *alphaData = static_cast<QMacPixmapData*>(alpha.data.data());
457 macSetAlphaChannel(alphaData, false);
458}
459
460QBitmap QMacPixmapData::mask() const
461{
462 if (!has_mask && !has_alpha)
463 return QBitmap();
464
465 QMacPixmapData *mask = new QMacPixmapData(BitmapType);
466 mask->resize(w, h);
467 macGetAlphaChannel(mask, true);
468 return QPixmap(mask);
469}
470
471void QMacPixmapData::setMask(const QBitmap &mask)
472{
473 if (mask.isNull()) {
474 QMacPixmapData opaque(PixmapType);
475 opaque.resize(w, h);
476 opaque.fill(QColor(255, 255, 255, 255));
477 macSetAlphaChannel(&opaque, true);
478 has_alpha = has_mask = false;
479 return;
480 }
481
482 has_alpha = false;
483 has_mask = true;
484 QMacPixmapData *maskData = static_cast<QMacPixmapData*>(mask.data.data());
485 macSetAlphaChannel(maskData, true);
486}
487
488int QMacPixmapData::metric(QPaintDevice::PaintDeviceMetric theMetric) const
489{
490 switch (theMetric) {
491 case QPaintDevice::PdmWidth:
492 return w;
493 case QPaintDevice::PdmHeight:
494 return h;
495 case QPaintDevice::PdmWidthMM:
496 return qRound(metric(QPaintDevice::PdmWidth) * 25.4 / qreal(metric(QPaintDevice::PdmDpiX)));
497 case QPaintDevice::PdmHeightMM:
498 return qRound(metric(QPaintDevice::PdmHeight) * 25.4 / qreal(metric(QPaintDevice::PdmDpiY)));
499 case QPaintDevice::PdmNumColors:
500 return 1 << d;
501 case QPaintDevice::PdmDpiX:
502 case QPaintDevice::PdmPhysicalDpiX: {
503 extern float qt_mac_defaultDpi_x(); //qpaintdevice_mac.cpp
504 return int(qt_mac_defaultDpi_x());
505 }
506 case QPaintDevice::PdmDpiY:
507 case QPaintDevice::PdmPhysicalDpiY: {
508 extern float qt_mac_defaultDpi_y(); //qpaintdevice_mac.cpp
509 return int(qt_mac_defaultDpi_y());
510 }
511 case QPaintDevice::PdmDepth:
512 return d;
513 default:
514 qWarning("QPixmap::metric: Invalid metric command");
515 }
516 return 0;
517}
518
519QMacPixmapData::~QMacPixmapData()
520{
521 validDataPointers.remove(this);
522 if (cg_mask) {
523 CGImageRelease(cg_mask);
524 cg_mask = 0;
525 }
526
527 delete pengine; // Make sure we aren't drawing on the context anymore.
528 if (cg_data) {
529 CGImageRelease(cg_data);
530 }
531 else if (pixels && (pixels != pixelsToFree))
532 free(pixels);
533 if (pixelsToFree)
534 free(pixelsToFree);
535}
536
537void QMacPixmapData::macSetAlphaChannel(const QMacPixmapData *pix, bool asMask)
538{
539 if (!pixels || !h || !w || pix->w != w || pix->h != h)
540 return;
541
542 quint32 *dptr = pixels, *drow;
543 const uint dbpr = bytesPerRow;
544 const unsigned short sbpr = pix->bytesPerRow;
545 quint32 *sptr = pix->pixels, *srow;
546 for (int y=0; y < h; ++y) {
547 drow = dptr + (y * (dbpr/4));
548 srow = sptr + (y * (sbpr/4));
549 if(d == 1) {
550 for (int x=0; x < w; ++x) {
551 if((*(srow+x) & RGB_MASK))
552 *(drow+x) = 0xFFFFFFFF;
553 }
554 } else if(d == 8) {
555 for (int x=0; x < w; ++x)
556 *(drow+x) = (*(drow+x) & RGB_MASK) | (*(srow+x) << 24);
557 } else if(asMask) {
558 for (int x=0; x < w; ++x) {
559 if(*(srow+x) & RGB_MASK)
560 *(drow+x) = (*(drow+x) & RGB_MASK);
561 else
562 *(drow+x) = (*(drow+x) & RGB_MASK) | 0xFF000000;
563 *(drow+x) = PREMUL(*(drow+x));
564 }
565 } else {
566 for (int x=0; x < w; ++x) {
567 const uchar alpha = qGray(qRed(*(srow+x)), qGreen(*(srow+x)), qBlue(*(srow+x)));
568 const uchar destAlpha = qt_div_255(alpha * qAlpha(*(drow+x)));
569#if 1
570 *(drow+x) = (*(drow+x) & RGB_MASK) | (destAlpha << 24);
571#else
572 *(drow+x) = qRgba(qt_div_255(qRed(*(drow+x) * alpha)),
573 qt_div_255(qGreen(*(drow+x) * alpha)),
574 qt_div_255(qBlue(*(drow+x) * alpha)), destAlpha);
575#endif
576 *(drow+x) = PREMUL(*(drow+x));
577 }
578 }
579 }
580 macSetHasAlpha(true);
581}
582
583void QMacPixmapData::macGetAlphaChannel(QMacPixmapData *pix, bool asMask) const
584{
585 quint32 *dptr = pix->pixels, *drow;
586 const uint dbpr = pix->bytesPerRow;
587 const unsigned short sbpr = bytesPerRow;
588 quint32 *sptr = pixels, *srow;
589 for(int y=0; y < h; ++y) {
590 drow = dptr + (y * (dbpr/4));
591 srow = sptr + (y * (sbpr/4));
592 if(asMask) {
593 for (int x = 0; x < w; ++x) {
594 if (*(srow + x) & qRgba(0, 0, 0, 255))
595 *(drow + x) = 0x00000000;
596 else
597 *(drow + x) = 0xFFFFFFFF;
598 }
599 } else {
600 for (int x = 0; x < w; ++x) {
601 const int alpha = qAlpha(*(srow + x));
602 *(drow + x) = qRgb(alpha, alpha, alpha);
603 }
604 }
605 }
606}
607
608void QMacPixmapData::macSetHasAlpha(bool b)
609{
610 has_alpha = b;
611 macReleaseCGImageRef();
612}
613
614void QMacPixmapData::macCreateCGImageRef()
615{
616 Q_ASSERT(cg_data == 0);
617 //create the cg data
618 CGColorSpaceRef colorspace = QCoreGraphicsPaintEngine::macDisplayColorSpace();
619 QCFType<CGDataProviderRef> provider = CGDataProviderCreateWithData(this,
620 pixels, bytesPerRow * h,
621 qt_mac_cgimage_data_free);
622 validDataPointers.insert(this);
623 uint cgflags = kCGImageAlphaPremultipliedFirst;
624#ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version
625 cgflags |= kCGBitmapByteOrder32Host;
626#endif
627 cg_data = CGImageCreate(w, h, 8, 32, bytesPerRow, colorspace,
628 cgflags, provider, 0, 0, kCGRenderingIntentDefault);
629}
630
631void QMacPixmapData::macReleaseCGImageRef()
632{
633 if (!cg_data)
634 return; // There's nothing we need to do
635
636 cg_dataBeingReleased = cg_data;
637 CGImageRelease(cg_data);
638 cg_data = 0;
639
640 if (pixels != pixelsToFree) {
641 macCreatePixels();
642 } else {
643 pixelsToFree = 0;
644 }
645}
646
647
648// We create our space in memory to paint on here. If we already have existing pixels
649// copy them over. This is to preserve the fact that CGImageRef's are immutable.
650void QMacPixmapData::macCreatePixels()
651{
652 int numBytes = bytesPerRow * h;
653 quint32 *base_pixels;
654 if (pixelsToFree && pixelsToFree != pixels) {
655 // Reuse unused block of memory lying around from a previous callback.
656 base_pixels = pixelsToFree;
657 pixelsToFree = 0;
658 } else {
659 // We need a block of memory to do stuff with.
660 base_pixels = static_cast<quint32 *>(malloc(numBytes));
661 if (!base_pixels) {
662 qWarning("Failed to allocate memory for pixmap data, setting to NULL");
663 numBytes = 0;
664 w = 0;
665 h = 0;
666 is_null = 0;
667 bytesPerRow=0;
668 }
669 }
670
671 // only copy when both buffers exist
672 if (pixels && base_pixels)
673 memcpy(base_pixels, pixels, qMin(pixelsSize, (uint) numBytes));
674
675 // free pixels before assigning new memory
676 if (pixels)
677 free(pixels);
678
679 pixels = base_pixels;
680 pixelsSize = numBytes;
681}
682
683#if 0
684QPixmap QMacPixmapData::transformed(const QTransform &transform,
685 Qt::TransformationMode mode) const
686{
687 int w, h; // size of target pixmap
688 const int ws = width();
689 const int hs = height();
690
691 QTransform mat(transform.m11(), transform.m12(),
692 transform.m21(), transform.m22(), 0., 0.);
693 if (transform.m12() == 0.0F && transform.m21() == 0.0F &&
694 transform.m11() >= 0.0F && transform.m22() >= 0.0F)
695 {
696 h = int(qAbs(mat.m22()) * hs + 0.9999);
697 w = int(qAbs(mat.m11()) * ws + 0.9999);
698 h = qAbs(h);
699 w = qAbs(w);
700 } else { // rotation or shearing
701 QPolygonF a(QRectF(0,0,ws+1,hs+1));
702 a = mat.map(a);
703 QRectF r = a.boundingRect().normalized();
704 w = int(r.width() + 0.9999);
705 h = int(r.height() + 0.9999);
706 }
707 mat = QPixmap::trueMatrix(mat, ws, hs);
708 if (!h || !w)
709 return QPixmap();
710
711 // create destination
712 QMacPixmapData *pm = new QMacPixmapData(pixelType(), w, h);
713 const quint32 *sptr = pixels;
714 quint32 *dptr = pm->pixels;
715 memset(dptr, 0, (pm->bytesPerRow * pm->h));
716
717 // do the transform
718 if (mode == Qt::SmoothTransformation) {
719#warning QMacPixmapData::transformed not properly implemented
720 qWarning("QMacPixmapData::transformed not properly implemented");
721#if 0
722 QPainter p(&pm);
723 p.setRenderHint(QPainter::Antialiasing);
724 p.setRenderHint(QPainter::SmoothPixmapTransform);
725 p.setTransform(mat);
726 p.drawPixmap(0, 0, *this);
727#endif
728 } else {
729 bool invertible;
730 mat = mat.inverted(&invertible);
731 if (!invertible)
732 return QPixmap();
733
734 const int bpp = 32;
735 const int xbpl = (w * bpp) / 8;
736 if (!qt_xForm_helper(mat, 0, QT_XFORM_TYPE_MSBFIRST, bpp,
737 (uchar*)dptr, xbpl, (pm->bytesPerRow) - xbpl,
738 h, (uchar*)sptr, (bytesPerRow), ws, hs)) {
739 qWarning("QMacPixmapData::transform(): failure");
740 return QPixmap();
741 }
742 }
743
744 // update the alpha
745 pm->macSetHasAlpha(true);
746 return QPixmap(pm);
747}
748#endif
749
750QT_BEGIN_INCLUDE_NAMESPACE
751#include <OpenGL/OpenGL.h>
752#include <OpenGL/gl.h>
753QT_END_INCLUDE_NAMESPACE
754
755// Load and resolve the symbols we need from OpenGL manually so QtGui doesn't have to link against the OpenGL framework.
756typedef CGLError (*PtrCGLChoosePixelFormat)(const CGLPixelFormatAttribute *, CGLPixelFormatObj *, long *);
757typedef CGLError (*PtrCGLClearDrawable)(CGLContextObj);
758typedef CGLError (*PtrCGLCreateContext)(CGLPixelFormatObj, CGLContextObj, CGLContextObj *);
759typedef CGLError (*PtrCGLDestroyContext)(CGLContextObj);
760typedef CGLError (*PtrCGLDestroyPixelFormat)(CGLPixelFormatObj);
761typedef CGLError (*PtrCGLSetCurrentContext)(CGLContextObj);
762typedef CGLError (*PtrCGLSetFullScreen)(CGLContextObj);
763typedef void (*PtrglFinish)();
764typedef void (*PtrglPixelStorei)(GLenum, GLint);
765typedef void (*PtrglReadBuffer)(GLenum);
766typedef void (*PtrglReadPixels)(GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoid *);
767
768static PtrCGLChoosePixelFormat ptrCGLChoosePixelFormat = 0;
769static PtrCGLClearDrawable ptrCGLClearDrawable = 0;
770static PtrCGLCreateContext ptrCGLCreateContext = 0;
771static PtrCGLDestroyContext ptrCGLDestroyContext = 0;
772static PtrCGLDestroyPixelFormat ptrCGLDestroyPixelFormat = 0;
773static PtrCGLSetCurrentContext ptrCGLSetCurrentContext = 0;
774static PtrCGLSetFullScreen ptrCGLSetFullScreen = 0;
775static PtrglFinish ptrglFinish = 0;
776static PtrglPixelStorei ptrglPixelStorei = 0;
777static PtrglReadBuffer ptrglReadBuffer = 0;
778static PtrglReadPixels ptrglReadPixels = 0;
779
780static bool resolveOpenGLSymbols()
781{
782 static bool triedResolve = false;
783 if (!triedResolve) {
784 QLibrary library(QLatin1String("/System/Library/Frameworks/OpenGL.framework/OpenGL"));
785 ptrCGLChoosePixelFormat = (PtrCGLChoosePixelFormat)(library.resolve("CGLChoosePixelFormat"));
786 ptrCGLClearDrawable = (PtrCGLClearDrawable)(library.resolve("CGLClearDrawable"));
787 ptrCGLCreateContext = (PtrCGLCreateContext)(library.resolve("CGLCreateContext"));
788 ptrCGLDestroyContext = (PtrCGLDestroyContext)(library.resolve("CGLDestroyContext"));
789 ptrCGLDestroyPixelFormat = (PtrCGLDestroyPixelFormat)(library.resolve("CGLDestroyPixelFormat"));
790 ptrCGLSetCurrentContext = (PtrCGLSetCurrentContext)(library.resolve("CGLSetCurrentContext"));
791 ptrCGLSetFullScreen = (PtrCGLSetFullScreen)(library.resolve("CGLSetFullScreen"));
792 ptrglFinish = (PtrglFinish)(library.resolve("glFinish"));
793 ptrglPixelStorei = (PtrglPixelStorei)(library.resolve("glPixelStorei"));
794 ptrglReadBuffer = (PtrglReadBuffer)(library.resolve("glReadBuffer"));
795 ptrglReadPixels = (PtrglReadPixels)(library.resolve("glReadPixels"));
796 triedResolve = true;
797 }
798 return ptrCGLChoosePixelFormat && ptrCGLClearDrawable && ptrCGLCreateContext
799 && ptrCGLDestroyContext && ptrCGLDestroyPixelFormat && ptrCGLSetCurrentContext
800 && ptrCGLSetFullScreen && ptrglFinish && ptrglPixelStorei
801 && ptrglReadBuffer && ptrglReadPixels;
802}
803
804// Inverts the given pixmap in the y direction.
805static void qt_mac_flipPixmap(void *data, int rowBytes, int height)
806{
807 int bottom = height - 1;
808 void *base = data;
809 void *buffer = malloc(rowBytes);
810
811 int top = 0;
812 while ( top < bottom )
813 {
814 void *topP = (void *)((top * rowBytes) + (intptr_t)base);
815 void *bottomP = (void *)((bottom * rowBytes) + (intptr_t)base);
816
817 bcopy( topP, buffer, rowBytes );
818 bcopy( bottomP, topP, rowBytes );
819 bcopy( buffer, bottomP, rowBytes );
820
821 ++top;
822 --bottom;
823 }
824 free(buffer);
825}
826
827// Grabs displayRect from display and places it into buffer.
828static void qt_mac_grabDisplayRect(CGDirectDisplayID display, const QRect &displayRect, void *buffer)
829{
830 if (display == kCGNullDirectDisplay)
831 return;
832
833 CGLPixelFormatAttribute attribs[] = {
834 kCGLPFAFullScreen,
835 kCGLPFADisplayMask,
836 (CGLPixelFormatAttribute)0, /* Display mask bit goes here */
837 (CGLPixelFormatAttribute)0
838 };
839
840 attribs[2] = (CGLPixelFormatAttribute)CGDisplayIDToOpenGLDisplayMask(display);
841
842 // Build a full-screen GL context
843 CGLPixelFormatObj pixelFormatObj;
844 long numPixelFormats;
845
846 ptrCGLChoosePixelFormat( attribs, &pixelFormatObj, &numPixelFormats );
847
848 if (!pixelFormatObj) // No full screen context support
849 return;
850
851 CGLContextObj glContextObj;
852 ptrCGLCreateContext(pixelFormatObj, 0, &glContextObj);
853 ptrCGLDestroyPixelFormat(pixelFormatObj) ;
854 if (!glContextObj)
855 return;
856
857 ptrCGLSetCurrentContext(glContextObj);
858 ptrCGLSetFullScreen(glContextObj) ;
859
860 ptrglReadBuffer(GL_FRONT);
861
862 ptrglFinish(); // Finish all OpenGL commands
863 ptrglPixelStorei(GL_PACK_ALIGNMENT, 4); // Force 4-byte alignment
864 ptrglPixelStorei(GL_PACK_ROW_LENGTH, 0);
865 ptrglPixelStorei(GL_PACK_SKIP_ROWS, 0);
866 ptrglPixelStorei(GL_PACK_SKIP_PIXELS, 0);
867
868 // Fetch the data in XRGB format, matching the bitmap context.
869 ptrglReadPixels(GLint(displayRect.x()), GLint(displayRect.y()),
870 GLint(displayRect.width()), GLint(displayRect.height()),
871#ifdef __BIG_ENDIAN__
872 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, buffer
873#else
874 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, buffer
875#endif
876 );
877
878 ptrCGLSetCurrentContext(0);
879 ptrCGLClearDrawable(glContextObj); // disassociate from full screen
880 ptrCGLDestroyContext(glContextObj); // and destroy the context
881}
882
883#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6)
884// Returns a pixmap containing the screen contents at rect.
885static QPixmap qt_mac_grabScreenRect_10_6(const QRect &rect)
886{
887 const int maxDisplays = 128; // 128 displays should be enough for everyone.
888 CGDirectDisplayID displays[maxDisplays];
889 CGDisplayCount displayCount;
890 const CGRect cgRect = CGRectMake(rect.x(), rect.y(), rect.width(), rect.height());
891 const CGDisplayErr err = CGGetDisplaysWithRect(cgRect, maxDisplays, displays, &displayCount);
892
893 extern CGFloat qt_mac_get_scalefactor();
894 QRect scaledRect = QRect(rect.topLeft(), rect.size() * qt_mac_get_scalefactor());
895
896 if (err && displayCount == 0)
897 return QPixmap();
898 QPixmap windowPixmap(scaledRect.size());
899 for (uint i = 0; i < displayCount; ++i) {
900 const CGRect bounds = CGDisplayBounds(displays[i]);
901 // Translate to display-local coordinates
902 QRect displayRect = rect.translated(qRound(-bounds.origin.x), qRound(-bounds.origin.y));
903 QCFType<CGImageRef> image = CGDisplayCreateImageForRect(displays[i],
904 CGRectMake(displayRect.x(), displayRect.y(), displayRect.width(), displayRect.height()));
905 QPixmap pix = QPixmap::fromMacCGImageRef(image);
906 QPainter painter(&windowPixmap);
907 painter.drawPixmap(-bounds.origin.x, -bounds.origin.y, pix);
908 }
909 return windowPixmap;
910}
911#endif
912
913static QPixmap qt_mac_grabScreenRect(const QRect &rect)
914{
915 if (!resolveOpenGLSymbols())
916 return QPixmap();
917
918 const int maxDisplays = 128; // 128 displays should be enough for everyone.
919 CGDirectDisplayID displays[maxDisplays];
920 CGDisplayCount displayCount;
921 const CGRect cgRect = CGRectMake(rect.x(), rect.y(), rect.width(), rect.height());
922 const CGDisplayErr err = CGGetDisplaysWithRect(cgRect, maxDisplays, displays, &displayCount);
923
924 if (err && displayCount == 0)
925 return QPixmap();
926
927 long bytewidth = rect.width() * 4; // Assume 4 bytes/pixel for now
928 bytewidth = (bytewidth + 3) & ~3; // Align to 4 bytes
929 QVarLengthArray<char> buffer(rect.height() * bytewidth);
930
931 for (uint i = 0; i < displayCount; ++i) {
932 const CGRect bounds = CGDisplayBounds(displays[i]);
933 // Translate to display-local coordinates
934 QRect displayRect = rect.translated(qRound(-bounds.origin.x), qRound(-bounds.origin.y));
935 // Adjust for inverted y axis.
936 displayRect.moveTop(qRound(bounds.size.height) - displayRect.y() - rect.height());
937 qt_mac_grabDisplayRect(displays[i], displayRect, buffer.data());
938 }
939
940 qt_mac_flipPixmap(buffer.data(), bytewidth, rect.height());
941 QCFType<CGContextRef> bitmap = CGBitmapContextCreate(buffer.data(), rect.width(),
942 rect.height(), 8, bytewidth,
943 QCoreGraphicsPaintEngine::macGenericColorSpace(),
944 kCGImageAlphaNoneSkipFirst);
945 QCFType<CGImageRef> image = CGBitmapContextCreateImage(bitmap);
946 return QPixmap::fromMacCGImageRef(image);
947}
948
949#ifndef QT_MAC_USE_COCOA // no QuickDraw in 64-bit mode
950static QPixmap qt_mac_grabScreenRect_10_3(int x, int y, int w, int h, QWidget *widget)
951{
952 QPixmap pm = QPixmap(w, h);
953 extern WindowPtr qt_mac_window_for(const QWidget *); // qwidget_mac.cpp
954 const BitMap *windowPort = 0;
955 if((widget->windowType() == Qt::Desktop)) {
956 GDHandle gdh;
957 if(!(gdh=GetMainDevice()))
958 qDebug("Qt: internal: Unexpected condition reached: %s:%d", __FILE__, __LINE__);
959 windowPort = (BitMap*)(*(*gdh)->gdPMap);
960 } else {
961 windowPort = GetPortBitMapForCopyBits(GetWindowPort(qt_mac_window_for(widget)));
962 }
963 const BitMap *pixmapPort = GetPortBitMapForCopyBits(static_cast<GWorldPtr>(pm.macQDHandle()));
964 Rect macSrcRect, macDstRect;
965 SetRect(&macSrcRect, x, y, x + w, y + h);
966 SetRect(&macDstRect, 0, 0, w, h);
967 CopyBits(windowPort, pixmapPort, &macSrcRect, &macDstRect, srcCopy, 0);
968 return pm;
969}
970#endif
971
972QPixmap QPixmap::grabWindow(WId window, int x, int y, int w, int h)
973{
974 QWidget *widget = QWidget::find(window);
975 if (widget == 0)
976 return QPixmap();
977
978 if(w == -1)
979 w = widget->width() - x;
980 if(h == -1)
981 h = widget->height() - y;
982
983 QPoint globalCoord(0, 0);
984 globalCoord = widget->mapToGlobal(globalCoord);
985 QRect rect(globalCoord.x() + x, globalCoord.y() + y, w, h);
986
987#ifdef QT_MAC_USE_COCOA
988#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6)
989 if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_6)
990 return qt_mac_grabScreenRect_10_6(rect);
991 else
992#endif
993 return qt_mac_grabScreenRect(rect);
994#else
995#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
996 if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) {
997 return qt_mac_grabScreenRect(rect);
998 } else
999#endif
1000 {
1001 return qt_mac_grabScreenRect_10_3(x, y, w, h, widget);
1002 }
1003#endif // ifdef Q_WS_MAC64
1004}
1005
1006/*! \internal
1007
1008 Returns the QuickDraw CGrafPtr of the pixmap. 0 is returned if it can't
1009 be obtained. Do not hold the pointer around for long as it can be
1010 relocated.
1011
1012 \warning This function is only available on Mac OS X.
1013 \warning As of Qt 4.6, this function \e{always} returns zero.
1014*/
1015
1016Qt::HANDLE QPixmap::macQDHandle() const
1017{
1018 return 0;
1019}
1020
1021/*! \internal
1022
1023 Returns the QuickDraw CGrafPtr of the pixmap's alpha channel. 0 is
1024 returned if it can't be obtained. Do not hold the pointer around for
1025 long as it can be relocated.
1026
1027 \warning This function is only available on Mac OS X.
1028 \warning As of Qt 4.6, this function \e{always} returns zero.
1029*/
1030
1031Qt::HANDLE QPixmap::macQDAlphaHandle() const
1032{
1033 return 0;
1034}
1035
1036/*! \internal
1037
1038 Returns the CoreGraphics CGContextRef of the pixmap. 0 is returned if
1039 it can't be obtained. It is the caller's responsiblity to
1040 CGContextRelease the context when finished using it.
1041
1042 \warning This function is only available on Mac OS X.
1043*/
1044
1045Qt::HANDLE QPixmap::macCGHandle() const
1046{
1047 if (isNull())
1048 return 0;
1049
1050 if (data->classId() == QPixmapData::MacClass) {
1051 QMacPixmapData *d = static_cast<QMacPixmapData *>(data.data());
1052 if (!d->cg_data)
1053 d->macCreateCGImageRef();
1054 CGImageRef ret = d->cg_data;
1055 CGImageRetain(ret);
1056 return ret;
1057 } else if (data->classId() == QPixmapData::RasterClass) {
1058 return qt_mac_image_to_cgimage(static_cast<QRasterPixmapData *>(data.data())->image);
1059 }
1060 return 0;
1061}
1062
1063bool QMacPixmapData::hasAlphaChannel() const
1064{
1065 return has_alpha;
1066}
1067
1068CGImageRef qt_mac_create_imagemask(const QPixmap &pixmap, const QRectF &sr)
1069{
1070 QMacPixmapData *px = static_cast<QMacPixmapData*>(pixmap.data.data());
1071 if (px->cg_mask) {
1072 if (px->cg_mask_rect == sr) {
1073 CGImageRetain(px->cg_mask); //reference for the caller
1074 return px->cg_mask;
1075 }
1076 CGImageRelease(px->cg_mask);
1077 px->cg_mask = 0;
1078 }
1079
1080 const int sx = qRound(sr.x()), sy = qRound(sr.y()), sw = qRound(sr.width()), sh = qRound(sr.height());
1081 const int sbpr = px->bytesPerRow;
1082 const uint nbytes = sw * sh;
1083 // alpha is always 255 for bitmaps, ignore it in this case.
1084 const quint32 mask = px->depth() == 1 ? 0x00ffffff : 0xffffffff;
1085 quint8 *dptr = static_cast<quint8 *>(malloc(nbytes));
1086 quint32 *sptr = px->pixels, *srow;
1087 for(int y = sy, offset=0; y < sh; ++y) {
1088 srow = sptr + (y * (sbpr / 4));
1089 for(int x = sx; x < sw; ++x)
1090 *(dptr+(offset++)) = (*(srow+x) & mask) ? 255 : 0;
1091 }
1092 QCFType<CGDataProviderRef> provider = CGDataProviderCreateWithData(0, dptr, nbytes, qt_mac_cgimage_data_free);
1093 px->cg_mask = CGImageMaskCreate(sw, sh, 8, 8, nbytes / sh, provider, 0, 0);
1094 px->cg_mask_rect = sr;
1095 CGImageRetain(px->cg_mask); //reference for the caller
1096 return px->cg_mask;
1097}
1098
1099#ifndef QT_MAC_USE_COCOA
1100IconRef qt_mac_create_iconref(const QPixmap &px)
1101{
1102 if (px.isNull())
1103 return 0;
1104
1105 //create icon
1106 IconFamilyHandle iconFamily = reinterpret_cast<IconFamilyHandle>(NewHandle(0));
1107 //create data
1108 {
1109 struct {
1110 OSType mac_type;
1111 int width, height, depth;
1112 bool mask;
1113 } images[] = {
1114 { kThumbnail32BitData, 128, 128, 32, false },
1115 { kThumbnail8BitMask, 128, 128, 8, true },
1116 { 0, 0, 0, 0, false } //end marker
1117 };
1118 for(int i = 0; images[i].mac_type; i++) {
1119 //get QPixmap data
1120 QImage scaled_px = px.toImage().scaled(images[i].width, images[i].height);
1121
1122 quint32 *sptr = (quint32 *) scaled_px.bits();
1123 quint32 *srow;
1124 uint sbpr = scaled_px.bytesPerLine();
1125
1126 //get Handle data
1127 const int dbpr = images[i].width * (images[i].depth/8);
1128 Handle hdl = NewHandle(dbpr*images[i].height);
1129 if(!sptr) { //handle null pixmap
1130 memset((*hdl), '\0', dbpr*images[i].height);
1131 } else if(images[i].mask) {
1132 if(images[i].mac_type == kThumbnail8BitMask) {
1133 for(int y = 0, hindex = 0; y < images[i].height; ++y) {
1134 srow = sptr + (y * (sbpr/4));
1135 for(int x = 0; x < images[i].width; ++x)
1136 *((*hdl)+(hindex++)) = qAlpha(*(srow+x));
1137 }
1138 }
1139 } else {
1140 char *dest = (*hdl);
1141#if defined(__i386__)
1142 if(images[i].depth == 32) {
1143 for(int y = 0; y < images[i].height; ++y) {
1144 uint *source = (uint*)((const uchar*)sptr+(sbpr*y));
1145 for(int x = 0; x < images[i].width; ++x, dest += 4)
1146 *((uint*)dest) = CFSwapInt32(*(source + x));
1147 }
1148 } else
1149#endif
1150 {
1151 for(int y = 0; y < images[i].height; ++y)
1152 memcpy(dest+(y*dbpr), ((const uchar*)sptr+(sbpr*y)), dbpr);
1153 }
1154 }
1155
1156 //set the family data to the Handle
1157 OSStatus set = SetIconFamilyData(iconFamily, images[i].mac_type, hdl);
1158 if(set != noErr)
1159 qWarning("%s: %d -- Unable to create icon data[%d]!! %ld",
1160 __FILE__, __LINE__, i, long(set));
1161 DisposeHandle(hdl);
1162 }
1163 }
1164
1165 //acquire and cleanup
1166 IconRef ret;
1167 static int counter = 0;
1168 const OSType kQtCreator = 'CUTE';
1169 RegisterIconRefFromIconFamily(kQtCreator, (OSType)counter, iconFamily, &ret);
1170 AcquireIconRef(ret);
1171 UnregisterIconRef(kQtCreator, (OSType)counter);
1172 DisposeHandle(reinterpret_cast<Handle>(iconFamily));
1173 counter++;
1174 return ret;
1175
1176}
1177#endif
1178
1179/*! \internal */
1180QPaintEngine* QMacPixmapData::paintEngine() const
1181{
1182 if (!pengine) {
1183 QMacPixmapData *that = const_cast<QMacPixmapData*>(this);
1184 that->pengine = new QCoreGraphicsPaintEngine();
1185 }
1186 return pengine;
1187}
1188
1189void QMacPixmapData::copy(const QPixmapData *data, const QRect &rect)
1190{
1191 if (data->pixelType() == BitmapType) {
1192 QBitmap::fromImage(toImage().copy(rect));
1193 return;
1194 }
1195
1196 const QMacPixmapData *macData = static_cast<const QMacPixmapData*>(data);
1197
1198 resize(rect.width(), rect.height());
1199
1200 has_alpha = macData->has_alpha;
1201 has_mask = macData->has_mask;
1202 uninit = false;
1203
1204 const int x = rect.x();
1205 const int y = rect.y();
1206 char *dest = reinterpret_cast<char*>(pixels);
1207
1208 // only copy data buffer if destination buffer exists (resize might have failed)
1209 if (dest) {
1210 const char *src = reinterpret_cast<const char*>(macData->pixels + x) + y * macData->bytesPerRow;
1211 for (int i = 0; i < h; ++i) {
1212 memcpy(dest, src, w * 4);
1213 dest += bytesPerRow;
1214 src += macData->bytesPerRow;
1215 }
1216
1217 has_alpha = macData->has_alpha;
1218 has_mask = macData->has_mask;
1219 }
1220}
1221
1222bool QMacPixmapData::scroll(int dx, int dy, const QRect &rect)
1223{
1224 Q_UNUSED(dx);
1225 Q_UNUSED(dy);
1226 Q_UNUSED(rect);
1227 return false;
1228}
1229
1230/*!
1231 \since 4.2
1232
1233 Creates a \c CGImageRef equivalent to the QPixmap. Returns the \c CGImageRef handle.
1234
1235 It is the caller's responsibility to release the \c CGImageRef data
1236 after use.
1237
1238 \warning This function is only available on Mac OS X.
1239
1240 \sa fromMacCGImageRef()
1241*/
1242CGImageRef QPixmap::toMacCGImageRef() const
1243{
1244 return (CGImageRef)macCGHandle();
1245}
1246
1247/*!
1248 \since 4.2
1249
1250 Returns a QPixmap that is equivalent to the given \a image.
1251
1252 \warning This function is only available on Mac OS X.
1253
1254 \sa toMacCGImageRef(), {QPixmap#Pixmap Conversion}{Pixmap Conversion}
1255*/
1256QPixmap QPixmap::fromMacCGImageRef(CGImageRef image)
1257{
1258 const size_t w = CGImageGetWidth(image),
1259 h = CGImageGetHeight(image);
1260 QPixmap ret(w, h);
1261 ret.fill(Qt::transparent);
1262 CGRect rect = CGRectMake(0, 0, w, h);
1263 CGContextRef ctx = qt_mac_cg_context(&ret);
1264 qt_mac_drawCGImage(ctx, &rect, image);
1265 CGContextRelease(ctx);
1266 return ret;
1267}
1268
1269QT_END_NAMESPACE
1270

Warning: That file was not part of the compilation database. It may have many parsing errors.