Commit c78dabc55943b76479f7a84bae146f52cbc7bbbf

  • avatar
  • Jani Hautakangas <ext-jani.hautakangas @no…a.com>
  • Fri Sep 18 13:33:10 CEST 2009
Introduce native Symbian bitmap support to QPixmap

This is done to reduce heap consumption and to give
a possibility to share bitmaps across process. QPixmap
maps to Symbian CFbsBitmap which is stored in Symbian
font and bitmap server.

Reviewed-by: Jason Barron
  
23892389#ifdef SYMBIAN_GRAPHICS_USE_GCE
23902390//RWsPointerCursor is fixed, so don't use low performance sprites
23912391#define Q_SYMBIAN_FIXED_POINTER_CURSORS
2392#define Q_SYMBIAN_HAS_EXTENDED_BITMAP_TYPE
23922393#endif
23932394
23942395//Symbian does not support data imports from a DLL
  
7070 SOURCES += image/qpixmap_mac.cpp
7171}
7272symbian {
73 HEADERS += image/qpixmap_s60_p.h
7374 SOURCES += image/qpixmap_s60.cpp
7475}
7576
  
15571557 premultiplied alpha format. If the image has an alpha channel, and
15581558 if the system allows, the preferred format is premultiplied alpha.
15591559 Note also that QPixmap, unlike QImage, may be hardware dependent.
1560 On X11 and Mac, a QPixmap is stored on the server side while a
1561 QImage is stored on the client side (on Windows, these two classes
1560 On X11, Mac and Symbian, a QPixmap is stored on the server side while
1561 a QImage is stored on the client side (on Windows, these two classes
15621562 have an equivalent internal representation, i.e. both QImage and
15631563 QPixmap are stored on the client side and don't use any GDI
15641564 resources).
15771577 screen. Alternatively, if no manipulation is desired, the image
15781578 file can be loaded directly into a QPixmap. On Windows, the
15791579 QPixmap class also supports conversion between \c HBITMAP and
1580 QPixmap.
1580 QPixmap. On Symbian, the QPixmap class also supports conversion
1581 between CFbsBitmap and QPixmap.
15811582
15821583 QPixmap provides a collection of functions that can be used to
15831584 obtain a variety of information about the pixmap. In addition,
16831683 returns the HBITMAP handle. The fromWinHBITMAP() function returns
16841684 a QPixmap that is equivalent to the given bitmap which has the
16851685 specified format.
1686
1687 In addition, on Symbian, the QPixmap class supports conversion to
1688 and from CFbsBitmap: the toSymbianCFbsBitmap() function creates
1689 CFbsBitmap equivalent to the QPixmap, based on given mode and returns
1690 a CFbsBitmap object. The fromSymbianCFbsBitmap() function returns a
1691 QPixmap that is equivalent to the given bitmap and given mode.
16861692
16871693 \section1 Pixmap Transformations
16881694
  
157157#endif
158158
159159#if defined(Q_OS_SYMBIAN)
160 CFbsBitmap *toSymbianCFbsBitmap() const;
161 static QPixmap fromSymbianCFbsBitmap(CFbsBitmap *bitmap);
160 enum ConversionMode { CopyData, DuplicateHandle };
161
162 CFbsBitmap *toSymbianCFbsBitmap(ConversionMode mode = DuplicateHandle) const;
163 static QPixmap fromSymbianCFbsBitmap(CFbsBitmap *bitmap, ConversionMode mode = DuplicateHandle);
162164#endif
163165
164166 inline QPixmap copy(int x, int y, int width, int height) const;
256256 friend class QPixmapData;
257257 friend class QX11PixmapData;
258258 friend class QMacPixmapData;
259 friend class QS60PixmapData;
259260 friend class QBitmap;
260261 friend class QPaintDevice;
261262 friend class QPainter;
  
8383
8484protected:
8585 int metric(QPaintDevice::PaintDeviceMetric metric) const;
86 QImage image;
8687
8788private:
8889 friend class QPixmap;
8990 friend class QBitmap;
9091 friend class QDetachedPixmap;
9192 friend class QRasterPaintEngine;
92 QImage image;
9393};
9494
9595QT_END_NAMESPACE
  
4343#include <fbs.h>
4444
4545#include <private/qt_s60_p.h>
46#include <private/qpaintengine_s60_p.h>
47
4648#include "qpixmap.h"
4749#include "qpixmap_raster_p.h"
4850#include <qwidget.h>
51#include "qpixmap_s60_p.h"
52#include "qnativeimage_p.h"
53#include "qbitmap.h"
54#include "qimage.h"
55#include "qimage_p.h"
4956
57#include <fbs.h>
58
5059QT_BEGIN_NAMESPACE
5160
52QPixmap QPixmap::grabWindow(WId winId, int x, int y, int w, int h )
61const uchar qt_pixmap_bit_mask[] = { 0x01, 0x02, 0x04, 0x08,
62 0x10, 0x20, 0x40, 0x80 };
63
64
65
66/*!
67 \since 4.6
68
69 Symbian Font And Bitmap server client that is
70 used to lock the global bitmap heap. Only used in
71 S60 v3.1 and S60 v3.2.
72*/
73class QSymbianFbsClient
5374{
75public:
76
77 QSymbianFbsClient() : heapLock(0), heapLocked(false)
78 {
79 QT_TRAP_THROWING(heapLock = new(ELeave) CFbsBitmap);
80 heapLock->Create(TSize(0,0), S60->screenDevice()->DisplayMode());
81 }
82
83 ~QSymbianFbsClient()
84 {
85 delete heapLock;
86 }
87
88 bool lockHeap()
89 {
90 bool wasLocked = heapLocked;
91
92 if (heapLock && !heapLocked) {
93 heapLock->LockHeap(ETrue);
94 heapLocked = true;
95 }
96
97 return wasLocked;
98 }
99
100 bool unlockHeap()
101 {
102 bool wasLocked = heapLocked;
103
104 if (heapLock && heapLocked) {
105 heapLock->UnlockHeap(ETrue);
106 heapLocked = false;
107 }
108
109 return wasLocked;
110 }
111
112
113private:
114
115 CFbsBitmap *heapLock;
116 bool heapLocked;
117};
118
119Q_GLOBAL_STATIC(QSymbianFbsClient, qt_symbianFbsClient);
120
121
122
123// QSymbianFbsHeapLock
124
125QSymbianFbsHeapLock::QSymbianFbsHeapLock(LockAction a)
126: action(a), wasLocked(false)
127{
128 QSysInfo::SymbianVersion symbianVersion = QSysInfo::symbianVersion();
129 if (symbianVersion == QSysInfo::SV_9_2 || symbianVersion == QSysInfo::SV_9_3)
130 wasLocked = qt_symbianFbsClient()->unlockHeap();
131}
132
133QSymbianFbsHeapLock::~QSymbianFbsHeapLock()
134{
135 // Do nothing
136}
137
138void QSymbianFbsHeapLock::relock()
139{
140 QSysInfo::SymbianVersion symbianVersion = QSysInfo::symbianVersion();
141 if (wasLocked && (symbianVersion == QSysInfo::SV_9_2 || symbianVersion == QSysInfo::SV_9_3))
142 qt_symbianFbsClient()->lockHeap();
143}
144
145/*!
146 \since 4.6
147
148 Data access class that is used to locks/unlocks pixel data
149 when drawing or modifying CFbsBitmap pixel data.
150*/
151class QSymbianBitmapDataAccess
152{
153public:
154
155 bool heapWasLocked;
156 QSysInfo::SymbianVersion symbianVersion;
157
158 explicit QSymbianBitmapDataAccess() : heapWasLocked(false)
159 {
160 symbianVersion = QSysInfo::symbianVersion();
161 };
162
163 ~QSymbianBitmapDataAccess() {};
164
165 inline void beginDataAccess(CFbsBitmap *bitmap)
166 {
167 if (symbianVersion == QSysInfo::SV_9_2 || symbianVersion == QSysInfo::SV_9_3)
168 heapWasLocked = qt_symbianFbsClient()->lockHeap();
169 else
170 bitmap->LockHeap(ETrue);
171 }
172
173 inline void endDataAccess(CFbsBitmap *bitmap)
174 {
175 if (symbianVersion == QSysInfo::SV_9_2 || symbianVersion == QSysInfo::SV_9_3) {
176 if (!heapWasLocked)
177 qt_symbianFbsClient()->unlockHeap();
178 } else {
179 bitmap->UnlockHeap(ETrue);
180 }
181 }
182};
183
184
185#define UPDATE_BUFFER() \
186 { \
187 beginDataAccess(); \
188 endDataAccess(); \
189}
190
191
192static CFbsBitmap* createSymbianCFbsBitmap(const TSize& size, TDisplayMode mode)
193{
194 QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock);
195
196 CFbsBitmap* bitmap = 0;
197 QT_TRAP_THROWING(bitmap = new (ELeave) CFbsBitmap);
198
199 if (bitmap->Create(size, mode) != KErrNone) {
200 delete bitmap;
201 bitmap = 0;
202 }
203
204 lock.relock();
205
206 return bitmap;
207}
208
209static CFbsBitmap* uncompress(CFbsBitmap* bitmap)
210{
211 if(bitmap->IsCompressedInRAM()) {
212 QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock);
213
214 CFbsBitmap *uncompressed = 0;
215 QT_TRAP_THROWING(uncompressed = new (ELeave) CFbsBitmap);
216
217 if (uncompressed->Create(bitmap->SizeInPixels(), bitmap->DisplayMode()) != KErrNone) {
218 delete bitmap;
219 bitmap = 0;
220 lock.relock();
221
222 return bitmap;
223 }
224
225 lock.relock();
226
227 CBitmapContext *bitmapContext = 0;
228 CFbsBitmapDevice* bitmapDevice = 0;
229 QT_TRAP_THROWING(bitmapDevice = CFbsBitmapDevice::NewL(uncompressed));
230 TInt err = bitmapDevice->CreateBitmapContext(bitmapContext);
231 if (err != KErrNone) {
232 delete bitmap;
233 delete bitmapDevice;
234 bitmap = 0;
235 bitmapDevice = 0;
236
237 lock.relock();
238
239 return bitmap;
240 }
241
242 bitmapContext->DrawBitmap(TPoint(), bitmap);
243
244 delete bitmapContext;
245 delete bitmapDevice;
246
247 return uncompressed;
248 } else {
249 return bitmap;
250 }
251}
252
253QPixmap QPixmap::grabWindow(WId winId, int x, int y, int w, int h)
254{
54255 CWsScreenDevice* screenDevice = S60->screenDevice();
55256 TSize screenSize = screenDevice->SizeInPixels();
56
257
57258 TSize srcSize;
58259 // Find out if this is one of our windows.
59260 QSymbianControl *sControl;
268268 y += relativePos.iY;
269269 srcSize = winId->Size();
270270 }
271
271
272272 TRect srcRect(TPoint(x, y), srcSize);
273273 // Clip to the screen
274274 srcRect.Intersection(TRect(screenSize));
275
275
276276 if (w > 0 && h > 0) {
277277 TRect subRect(TPoint(x, y), TSize(w, h));
278278 // Clip to the subRect
279279 srcRect.Intersection(subRect);
280280 }
281
281
282282 if (srcRect.IsEmpty())
283283 return QPixmap();
284
285 TDisplayMode displayMode = screenDevice->DisplayMode();
286 CFbsBitmap* temporary = q_check_ptr(new CFbsBitmap()); // CBase derived object needs check on new
287 TInt error = temporary->Create(srcRect.Size(), displayMode);
288 if (error == KErrNone)
289 error = screenDevice->CopyScreenToBitmap(temporary, srcRect);
290
291 if (error != KErrNone) {
292 CBase::Delete(temporary);
293 return QPixmap();
284
285 CFbsBitmap* temporary = createSymbianCFbsBitmap(srcRect.Size(), screenDevice->DisplayMode());
286
287 QPixmap pix;
288
289 if (temporary && screenDevice->CopyScreenToBitmap(temporary, srcRect) == KErrNone) {
290 pix = QPixmap::fromSymbianCFbsBitmap(temporary);
294291 }
295
296 QPixmap pixmap = QPixmap::fromSymbianCFbsBitmap(temporary);
297 CBase::Delete(temporary);
298 return pixmap;
292
293 delete temporary;
294 return pix;
299295}
300296
301297/*!
302\since 4.6
298 \enum QPixmap::ConversionMode
303299
304Returns a \c CFbsBitmap that is equivalent to the QPixmap by copying the data.
300 \bold{Symbian only:} This enum defines how the conversion between \c
301 CFbsBitmap and QPixmap is performed.
305302
306It is the caller's responsibility to delete the \c CFbsBitmap after use.
303 \warning This enum is only available on Symbian.
307304
308\warning This function is only available on Symbian OS.
305 \value CopyData Copied CFbsBitmap data.
309306
310\sa fromSymbianCFbsBitmap()
307 \value DuplicateHandle Duplicates CFbsBitmap handle. This also means
308 that pixmap data will be explicitly shared.
309
310 \sa fromSymbianCFbsBitmap(), toSymbianCFbsBitmap()
311311*/
312312
313CFbsBitmap *QPixmap::toSymbianCFbsBitmap() const
313
314/*!
315 \fn CFbsBitmap *QPixmap::toSymbianCFbsBitmap(ConversionMode mode)
316 \since 4.6
317
318 Creates \c CFbsBitmap that is equivalent to the QPixmap, based on
319 the given \a mode. If the creation then this function returns 0.
320
321 It is the caller's responsibility to release the \c CFbsBitmap data
322 after use either by deleting the bitmap or calling \c Reset().
323
324 \warning On S60 3.1 and S60 3.2 conversion mode will always be CopyData
325 if QPixmap pixels have alpha values.
326 \warning This function is only available on Symbian OS.
327
328 \sa fromSymbianCFbsBitmap()
329*/
330CFbsBitmap *QPixmap::toSymbianCFbsBitmap(ConversionMode mode) const
314331{
315 if (isNull())
332 QS60PixmapData *s60data = static_cast<QS60PixmapData *>(data.data());
333
334 if (isNull() || !s60data->cfbsBitmap)
316335 return 0;
336
337 bool convertToArgb32 = false;
338
339 QSysInfo::SymbianVersion symbianVersion = QSysInfo::symbianVersion();
340 if (symbianVersion == QSysInfo::SV_9_2 || symbianVersion == QSysInfo::SV_9_3) {
341 // Convert argb32_premultiplied to argb32 since Symbian 9.2 and Symbian 9.3 do
342 // not support premultipied format.
343
344 if (s60data->image.format() == QImage::Format_ARGB32_Premultiplied) {
345 mode = CopyData;
346 convertToArgb32 = true;
347 }
348 }
349
350 CFbsBitmap *bitmap = 0;
351
352 TDisplayMode displayMode = s60data->cfbsBitmap->DisplayMode();
353
354 if(displayMode == EGray2) {
355 //Symbian thinks set pixels are white/transparent, Qt thinks they are foreground/solid
356 //So invert mono bitmaps so that masks work correctly.
357 s60data->image.invertPixels();
358 mode = CopyData;
359 }
360
361 if (mode == CopyData) {
362 QImage source;
363
364 if (convertToArgb32) {
365 source = s60data->image.convertToFormat(QImage::Format_ARGB32);
366 displayMode = EColor16MA;
367 } else {
368 source = s60data->image;
369 }
370
371 CFbsBitmap *newBitmap = createSymbianCFbsBitmap(TSize(source.width(), source.height()), displayMode);
372 const uchar *sptr = source.bits();
373 s60data->symbianBitmapDataAccess->beginDataAccess(newBitmap);
374
375 uchar *dptr = (uchar*)newBitmap->DataAddress();
376 Mem::Copy(dptr, sptr, source.numBytes());
377
378 s60data->symbianBitmapDataAccess->endDataAccess(newBitmap);
379
380 bitmap = newBitmap;
381 } else {
382
383 QT_TRAP_THROWING(bitmap = new (ELeave) CFbsBitmap);
384
385 TInt err = bitmap->Duplicate(s60data->cfbsBitmap->Handle());
386 if (err != KErrNone) {
387 qWarning("Could not duplicate CFbsBitmap");
388 delete bitmap;
389 bitmap = 0;
390 }
391 }
392
393 if(displayMode == EGray2) {
394 // restore pixels
395 s60data->image.invertPixels();
396 }
397
398 return bitmap;
399}
317400
401/*!
402 \fn QPixmap QPixmap::fromSymbianCFbsBitmap(CFbsBitmap *bitmap, ConversionMode mode)
403 \since 4.6
404
405 Creates a QPixmap from native \c CFbsBitmap \a bitmap. The conversion
406 is based on the specified \a mode. Conversion mode is always QPixmap::CopyData
407 if given \a bitmap does not have display mode of TDisplayMode::EGray2,
408 \c TDisplayMode::EColor16MU or \c TDisplayMode::EColor16MAP.
409
410 If the CFbsBitmap is not valid this function will return a null QPixmap.
411
412 \warning This function is only available on Symbian OS.
413
414 \sa toSymbianCFbsBitmap(), {QPixmap#Pixmap Conversion}{Pixmap Conversion}
415*/
416QPixmap QPixmap::fromSymbianCFbsBitmap(CFbsBitmap *bitmap, ConversionMode mode)
417{
418 if (bitmap) {
419
420 bool deleteSourceBitmap = false;
421
422#if Q_SYMBIAN_HAS_EXTENDED_BITMAP_TYPE
423
424 // Rasterize extended bitmaps
425
426 TUid extendedBitmapType = = bitmap->ExtendedBitmapType();
427 if (extendedBitmapType != KNullUid) {
428 CFbsBitmap *rasterBitmap = createSymbianCFbsBitmap(bitmap->SizeInPixels(), EColor16MA);
429
430 CFbsBitmapDevice *rasterBitmapDev = 0;
431 QT_TRAP_THROWING(rasterBitmapDev = CFbsBitmapDevice::NewL(rasterBitmap));
432
433 CFbsBitGc *rasterBitmapGc = 0;
434 TInt err = rasterBitmapDev->CreateContext(rasterBitmapGc);
435 if (err != KErrNone) {
436 delete rasterBitmap;
437 delete rasterBitmapDev;
438 rasterBitmapDev = 0;
439 return QPixmap();
440 }
441
442 rasterBitmapGc->BitBlt(TPoint( 0, 0), bitmap);
443
444 bitmap = rasterBitmap;
445
446 delete rasterBitmapDev;
447 delete rasterBitmapGc;
448
449 rasterBitmapDev = 0;
450 rasterBitmapGc = 0;
451
452 deleteSourceBitmap = true;
453 }
454#endif
455
456
457 deleteSourceBitmap = bitmap->IsCompressedInRAM();
458 CFbsBitmap *sourceBitmap = uncompress(bitmap);
459
460 TDisplayMode displayMode = sourceBitmap->DisplayMode();
461 QImage::Format format = qt_TDisplayMode2Format(displayMode);
462
463 QImage::Format opaqueFormat = QNativeImage::systemFormat();
464 QImage::Format alphaFormat = QImage::Format_ARGB32_Premultiplied;
465
466 if (format != opaqueFormat && format != alphaFormat && format != QImage::Format_MonoLSB)
467 mode = CopyData;
468
469
470 QPixmapData::PixelType type = (format!=QImage::Format_MonoLSB)
471 ? QPixmapData::PixmapType
472 : QPixmapData::BitmapType;
473
474 QS60PixmapData *pixmapData = 0;
475
476 if (mode == CopyData) {
477
478 TSize size = sourceBitmap->SizeInPixels();
479
480 QSymbianBitmapDataAccess da;
481 da.beginDataAccess(sourceBitmap);
482 uchar *bytes = (uchar*)sourceBitmap->DataAddress();
483 QImage img = QImage(bytes, size.iWidth, size.iHeight, format);
484 da.endDataAccess(sourceBitmap);
485
486 pixmapData = new QS60PixmapData(type);
487 pixmapData->fromImage(img, Qt::AutoColor);
488
489 if(deleteSourceBitmap)
490 delete sourceBitmap;
491
492 if(displayMode == EGray2) {
493 //Symbian thinks set pixels are white/transparent, Qt thinks they are foreground/solid
494 //So invert mono bitmaps so that masks work correctly.
495 pixmapData->image.invertPixels();
496 }
497 } else {
498 CFbsBitmap* duplicate = 0;
499 QT_TRAP_THROWING(duplicate = new (ELeave) CFbsBitmap);
500
501 TInt err = duplicate->Duplicate(sourceBitmap->Handle());
502 if (err != KErrNone) {
503 qWarning("Could not duplicate CFbsBitmap");
504
505 if(deleteSourceBitmap)
506 delete sourceBitmap;
507
508 delete duplicate;
509 return QPixmap();
510 }
511
512 pixmapData = new QS60PixmapData(type);
513 pixmapData->fromSymbianBitmap(duplicate);
514
515 if(deleteSourceBitmap)
516 delete sourceBitmap;
517 }
518
519 return QPixmap(pixmapData);
520 }
521
522 return QPixmap();
523}
524
525QS60PixmapData::QS60PixmapData(PixelType type) : QRasterPixmapData(type),
526 symbianBitmapDataAccess(new QSymbianBitmapDataAccess),
527 cfbsBitmap(0),
528 bitmapDevice(0),
529 bitmapContext(0),
530 pengine(0),
531 bytes(0)
532{
533
534}
535
536QS60PixmapData::~QS60PixmapData()
537{
538 release();
539}
540
541void QS60PixmapData::resize(int width, int height)
542{
543 if (width <= 0 || height <= 0) {
544 w = width;
545 h = height;
546 is_null = true;
547
548 release();
549 return;
550 } else if (!cfbsBitmap) {
551 TDisplayMode mode;
552 if (pixelType() == BitmapType)
553 mode = EGray2;
554 else
555 mode = EColor16MU;
556
557 CFbsBitmap* bitmap = createSymbianCFbsBitmap(TSize(width, height), mode);
558 fromSymbianBitmap(bitmap);
559 } else {
560
561 TSize newSize(width, height);
562
563 if(cfbsBitmap->SizeInPixels() != newSize) {
564 cfbsBitmap->Resize(TSize(width, height));
565 if(pengine) {
566 delete pengine;
567 pengine = 0;
568 }
569 }
570
571 UPDATE_BUFFER();
572 }
573}
574
575bool QS60PixmapData::initSymbianBitmapContext()
576{
577 QT_TRAP_THROWING(bitmapDevice = CFbsBitmapDevice::NewL(cfbsBitmap));
578 TInt err = bitmapDevice->CreateBitmapContext(bitmapContext);
579 if (err != KErrNone) {
580 delete bitmapDevice;
581 bitmapDevice = 0;
582 return false;
583 }
584 return true;
585}
586
587void QS60PixmapData::release()
588{
589 if (cfbsBitmap) {
590 QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock);
591 delete bitmapContext;
592 delete bitmapDevice;
593 delete cfbsBitmap;
594 lock.relock();
595 }
596
597 delete pengine;
598 image = QImage();
599 cfbsBitmap = 0;
600 bitmapContext = 0;
601 bitmapDevice = 0;
602 pengine = 0;
603 bytes = 0;
604}
605
606/*!
607 * Takes ownership of bitmap
608 */
609void QS60PixmapData::fromSymbianBitmap(CFbsBitmap* bitmap)
610{
611 cfbsBitmap = bitmap;
612
613 if(!initSymbianBitmapContext()) {
614 qWarning("Could not create CBitmapContext");
615 release();
616 return;
617 }
618
619 setSerialNumber(cfbsBitmap->Handle());
620
621 UPDATE_BUFFER();
622
623 // Create default palette if needed
624 if (cfbsBitmap->DisplayMode() == EGray2) {
625 image.setNumColors(2);
626 image.setColor(0, QColor(Qt::color0).rgba());
627 image.setColor(1, QColor(Qt::color1).rgba());
628
629 //Symbian thinks set pixels are white/transparent, Qt thinks they are foreground/solid
630 //So invert mono bitmaps so that masks work correctly.
631 image.invertPixels();
632 } else if (cfbsBitmap->DisplayMode() == EGray256) {
633 for (int i=0; i < 256; ++i)
634 image.setColor(i, qRgb(i, i, i));
635 }else if (cfbsBitmap->DisplayMode() == EColor256) {
636 const TColor256Util *palette = TColor256Util::Default();
637 for (int i=0; i < 256; ++i)
638 image.setColor(i, (QRgb)(palette->Color256(i).Value()));
639 }
640}
641
642void QS60PixmapData::fromImage(const QImage &img, Qt::ImageConversionFlags flags)
643{
644 QImage sourceImage;
645
646 if (pixelType() == BitmapType) {
647 sourceImage = img.convertToFormat(QImage::Format_MonoLSB);
648 } else {
649 if (img.depth() == 1) {
650 image = img.hasAlphaChannel()
651 ? img.convertToFormat(QImage::Format_ARGB32_Premultiplied)
652 : img.convertToFormat(QImage::Format_RGB32);
653 } else {
654
655 QImage::Format opaqueFormat = QNativeImage::systemFormat();
656 QImage::Format alphaFormat = QImage::Format_ARGB32_Premultiplied;
657
658 if (!img.hasAlphaChannel()
659 || ((flags & Qt::NoOpaqueDetection) == 0
660 && !const_cast<QImage &>(img).data_ptr()->checkForAlphaPixels())) {
661 sourceImage = img.convertToFormat(opaqueFormat);
662 } else {
663 sourceImage = img.convertToFormat(alphaFormat);
664 }
665 }
666 }
667
668
669 QImage::Format destFormat = sourceImage.format();
318670 TDisplayMode mode;
319 const QImage img = toImage();
320 QImage::Format destFormat = img.format();
321 switch (img.format()) {
322 case QImage::Format_Mono:
323 destFormat = QImage::Format_MonoLSB;
324 // Fall through intended
671 switch (destFormat) {
325672 case QImage::Format_MonoLSB:
326673 mode = EGray2;
327674 break;
328 case QImage::Format_Indexed8:
329 if (img.isGrayscale())
330 mode = EGray256;
331 else
332 mode = EColor256;
333 break;
334675 case QImage::Format_RGB32:
335676 mode = EColor16MU;
336677 break;
337 case QImage::Format_ARGB6666_Premultiplied:
338 case QImage::Format_ARGB8565_Premultiplied:
339 case QImage::Format_ARGB8555_Premultiplied:
340 destFormat = QImage::Format_ARGB32_Premultiplied;
341 // Fall through intended
342678 case QImage::Format_ARGB32_Premultiplied:
343679#if !defined(__SERIES60_31__) && !defined(__S60_32__)
344 // ### TODO: Add runtime detection as well?
345680 mode = EColor16MAP;
346 break;
681 break;
347682#endif
348683 destFormat = QImage::Format_ARGB32;
349684 // Fall through intended
350685 case QImage::Format_ARGB32:
351686 mode = EColor16MA;
352687 break;
353 case QImage::Format_RGB555:
354 destFormat = QImage::Format_RGB16;
355 // Fall through intended
356 case QImage::Format_RGB16:
357 mode = EColor64K;
358 break;
359 case QImage::Format_RGB666:
360 destFormat = QImage::Format_RGB888;
361 // Fall through intended
362 case QImage::Format_RGB888:
363 mode = EColor16M;
364 break;
365 case QImage::Format_RGB444:
366 mode = EColor4K;
367 break;
368688 case QImage::Format_Invalid:
369 return 0;
689 return;
370690 default:
371 qWarning("Image format not supported: %d", img.format());
372 return 0;
691 qWarning("Image format not supported: %d", image.format());
692 return;
373693 }
694
695 cfbsBitmap = createSymbianCFbsBitmap(TSize(sourceImage.width(), sourceImage.height()), mode);
696 if (!(cfbsBitmap && initSymbianBitmapContext())) {
697 qWarning("Could not create CFbsBitmap and/or CBitmapContext");
698 release();
699 return;
700 }
701
702 setSerialNumber(cfbsBitmap->Handle());
703
704 const uchar *sptr = const_cast<const QImage &>(sourceImage).bits();
705 symbianBitmapDataAccess->beginDataAccess(cfbsBitmap);
706 uchar *dptr = (uchar*)cfbsBitmap->DataAddress();
707 Mem::Copy(dptr, sptr, sourceImage.numBytes());
708 symbianBitmapDataAccess->endDataAccess(cfbsBitmap);
709
710 UPDATE_BUFFER();
711
712 if (destFormat == QImage::Format_MonoLSB) {
713 image.setNumColors(2);
714 image.setColor(0, QColor(Qt::color0).rgba());
715 image.setColor(1, QColor(Qt::color1).rgba());
716 } else {
717 image.setColorTable(sourceImage.colorTable());
718 }
719}
374720
375 CFbsBitmap* bitmap = q_check_ptr(new CFbsBitmap()); // CBase derived object needs check on new
376 TSize size(width(), height());
377 if (bitmap->Create(size, mode) != KErrNone) {
378 CBase::Delete(bitmap);
379 return 0;
721void QS60PixmapData::copy(const QPixmapData *data, const QRect &rect)
722{
723 if (data->pixelType() == BitmapType) {
724 QBitmap::fromImage(data->toImage().copy(rect));
725 return;
380726 }
727
728 const QS60PixmapData *s60Data = static_cast<const QS60PixmapData*>(data);
729
730 resize(rect.width(), rect.height());
731 cfbsBitmap->SetDisplayMode(s60Data->cfbsBitmap->DisplayMode());
732
733 bitmapContext->BitBlt(TPoint(0, 0), s60Data->cfbsBitmap, qt_QRect2TRect(rect));
734}
381735
382 QImage converted = img.convertToFormat(destFormat);
383
384 //Symbian thinks set pixels are white/transparent, Qt thinks they are foreground/solid
385 //So invert mono bitmaps so that masks work correctly.
386 if (mode == EGray2)
387 converted.invertPixels();
388
389 bitmap->LockHeap();
390 const uchar *sptr = converted.bits();
391 uchar *dptr = (uchar*)bitmap->DataAddress();
392 Mem::Copy(dptr, sptr, converted.numBytes());
393 bitmap->UnlockHeap();
394 return bitmap;
736bool QS60PixmapData::scroll(int dx, int dy, const QRect &rect)
737{
738 bitmapContext->CopyRect(TPoint(dx, dy), qt_QRect2TRect(rect));
739 return true;
395740}
396741
397/*!
398 \since 4.6
742int QS60PixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const
743{
744 if (!cfbsBitmap)
745 return 0;
399746
400 Returns a QPixmap that is equivalent to the \c CFbsBitmap \a bitmap
401 by copying the data. If the CFbsBitmap is not valid or is compressed
402 in memory, this function will return a null QPixmap.
747 switch (metric) {
748 case QPaintDevice::PdmWidth:
749 return cfbsBitmap->SizeInPixels().iWidth;
750 case QPaintDevice::PdmHeight:
751 return cfbsBitmap->SizeInPixels().iHeight;
752 case QPaintDevice::PdmWidthMM: {
753 TInt twips = cfbsBitmap->SizeInTwips().iWidth;
754 return (int)(twips * (25.4/KTwipsPerInch));
755 }
756 case QPaintDevice::PdmHeightMM: {
757 TInt twips = cfbsBitmap->SizeInTwips().iHeight;
758 return (int)(twips * (25.4/KTwipsPerInch));
759 }
760 case QPaintDevice::PdmNumColors:
761 return TDisplayModeUtils::NumDisplayModeColors(cfbsBitmap->DisplayMode());
762 case QPaintDevice::PdmDpiX:
763 case QPaintDevice::PdmPhysicalDpiX: {
764 TReal inches = cfbsBitmap->SizeInTwips().iWidth / (TReal)KTwipsPerInch;
765 TInt pixels = cfbsBitmap->SizeInPixels().iWidth;
766 return pixels / inches;
767 }
768 case QPaintDevice::PdmDpiY:
769 case QPaintDevice::PdmPhysicalDpiY: {
770 TReal inches = cfbsBitmap->SizeInTwips().iHeight / (TReal)KTwipsPerInch;
771 TInt pixels = cfbsBitmap->SizeInPixels().iHeight;
772 return pixels / inches;
773 }
774 case QPaintDevice::PdmDepth:
775 return TDisplayModeUtils::NumDisplayModeBitsPerPixel(cfbsBitmap->DisplayMode());
776 default:
777 qWarning("QPixmap::metric: Invalid metric command");
778 }
779 return 0;
403780
404 \warning This function is only available on Symbian OS.
781}
405782
406 \sa toSymbianCFbsBitmap(), {QPixmap#Pixmap Conversion}{Pixmap Conversion}
407*/
783void QS60PixmapData::fill(const QColor &color)
784{
785 if (color.alpha() != 255) {
786 QImage im(width(), height(), QImage::Format_ARGB32_Premultiplied);
787 im.fill(PREMUL(color.rgba()));
788 release();
789 fromImage(im, Qt::AutoColor | Qt::OrderedAlphaDither);
790 } else {
791 beginDataAccess();
792 QRasterPixmapData::fill(color);
793 endDataAccess();
794 }
795}
408796
409QPixmap QPixmap::fromSymbianCFbsBitmap(CFbsBitmap *bitmap)
797void QS60PixmapData::setMask(const QBitmap &mask)
410798{
411 if (!bitmap)
412 return QPixmap();
799 if (mask.size().isEmpty()) {
800 if (image.depth() != 1) {
801 QImage newImage = image.convertToFormat(QImage::Format_RGB32);
802 release();
803 fromImage(newImage, Qt::AutoColor | Qt::OrderedAlphaDither);
804 }
805 } else if (image.depth() == 1) {
806 beginDataAccess();
807 QRasterPixmapData::setMask(mask);
808 endDataAccess();
809 } else {
810 const int w = image.width();
811 const int h = image.height();
812
813 const QImage imageMask = mask.toImage().convertToFormat(QImage::Format_MonoLSB);
814 QImage newImage = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
815 for (int y = 0; y < h; ++y) {
816 const uchar *mscan = imageMask.scanLine(y);
817 QRgb *tscan = (QRgb *)newImage.scanLine(y);
818 for (int x = 0; x < w; ++x) {
819 if (!(mscan[x>>3] & qt_pixmap_bit_mask[x&7]))
820 tscan[x] = 0;
821 }
822 }
823 release();
824 fromImage(newImage, Qt::AutoColor | Qt::OrderedAlphaDither);
825 }
826}
413827
414 int width = bitmap->SizeInPixels().iWidth;
415 int height = bitmap->SizeInPixels().iHeight;
828void QS60PixmapData::setAlphaChannel(const QPixmap &alphaChannel)
829{
830 QImage img(toImage());
831 img.setAlphaChannel(alphaChannel.toImage());
832 release();
833 fromImage(img, Qt::OrderedDither | Qt::OrderedAlphaDither);
834}
416835
417 if (width <= 0 || height <= 0 || bitmap->IsCompressedInRAM())
418 return QPixmap();
836QImage QS60PixmapData::toImage() const
837{
838 return image;
839}
419840
420 TDisplayMode displayMode = bitmap->DisplayMode();
421 QImage::Format format = qt_TDisplayMode2Format(displayMode);
422 int bytesPerLine = CFbsBitmap::ScanLineLength(width, displayMode);
423 bitmap->LockHeap();
424 QImage image = QImage((const uchar*)bitmap->DataAddress(), width, height, bytesPerLine, format);
425 if (displayMode == EGray2) {
426 image.setNumColors(2);
427 image.setColor(0, QColor(Qt::color0).rgba());
428 image.setColor(1, QColor(Qt::color1).rgba());
429 //Symbian thinks set pixels are white/transparent, Qt thinks they are foreground/solid
430 //So invert mono bitmaps so that masks work correctly.
431 image.invertPixels();
432 } else if (displayMode == EGray256) {
433 for (int i=0; i < 256; ++i)
434 image.setColor(i, qRgb(i, i, i));
435 }else if (displayMode == EColor256) {
436 const TColor256Util *palette = TColor256Util::Default();
437 for (int i=0; i < 256; ++i)
438 image.setColor(i, (QRgb)(palette->Color256(i).Value()));
841QPaintEngine* QS60PixmapData::paintEngine() const
842{
843 if (!pengine) {
844 QS60PixmapData *that = const_cast<QS60PixmapData*>(this);
845 that->pengine = new QS60PaintEngine(&that->image, that);
439846 }
440 QPixmap pixmap = QPixmap::fromImage(image.copy());
441 bitmap->UnlockHeap();
442 return pixmap;
847 return pengine;
443848}
849
850void QS60PixmapData::beginDataAccess()
851{
852 if(!cfbsBitmap)
853 return;
854
855 symbianBitmapDataAccess->beginDataAccess(cfbsBitmap);
856
857 uchar* newBytes = (uchar*)cfbsBitmap->DataAddress();
858
859 if (newBytes == bytes)
860 return;
861
862
863 bytes = newBytes;
864 TDisplayMode mode = cfbsBitmap->DisplayMode();
865 QImage::Format format = qt_TDisplayMode2Format(mode);
866 TSize size = cfbsBitmap->SizeInPixels();
867
868 QVector<QRgb> savedColorTable;
869 if (!image.isNull())
870 savedColorTable = image.colorTable();
871
872 image = QImage(bytes, size.iWidth, size.iHeight, format);
873
874 // Restore the palette or create a default
875 if (!savedColorTable.isEmpty()) {
876 image.setColorTable(savedColorTable);
877 }
878
879 w = size.iWidth;
880 h = size.iHeight;
881 d = image.depth();
882 is_null = (w <= 0 || h <= 0);
883
884 if (pengine) {
885 QS60PaintEngine *engine = static_cast<QS60PaintEngine *>(pengine);
886 engine->prepare(&image);
887 }
888}
889
890void QS60PixmapData::endDataAccess(bool readOnly) const
891{
892 if(!cfbsBitmap)
893 return;
894
895 symbianBitmapDataAccess->endDataAccess(cfbsBitmap);
896}
897
444898
445899QT_END_NAMESPACE
  
1/****************************************************************************
2**
3** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information (qt-info@nokia.com)
5**
6** This file is part of the $MODULE$ of the Qt Toolkit.
7**
8** $TROLLTECH_DUAL_LICENSE$
9**
10****************************************************************************/
11
12#ifndef QPIXMAPDATA_S60_P_H
13#define QPIXMAPDATA_S60_P_H
14
15//
16// W A R N I N G
17// -------------
18//
19// This file is not part of the Qt API. It exists purely as an
20// implementation detail. This header file may change from version to
21// version without notice, or even be removed.
22//
23// We mean it.
24//
25
26#include <QtGui/private/qpixmap_raster_p.h>
27
28QT_BEGIN_NAMESPACE
29
30class CFbsBitmap;
31class CFbsBitmapDevice;
32class CBitmapContext;
33
34class QSymbianBitmapDataAccess;
35
36class QSymbianFbsHeapLock
37{
38public:
39
40 enum LockAction {
41 Unlock
42 };
43
44 explicit QSymbianFbsHeapLock(LockAction a);
45 ~QSymbianFbsHeapLock();
46 void relock();
47
48private:
49
50 LockAction action;
51 bool wasLocked;
52};
53
54class QS60PixmapData : public QRasterPixmapData
55{
56public:
57 QS60PixmapData(PixelType type);
58 ~QS60PixmapData();
59
60 void resize(int width, int height);
61 void fromImage(const QImage &image, Qt::ImageConversionFlags flags);
62 void copy(const QPixmapData *data, const QRect &rect);
63 bool scroll(int dx, int dy, const QRect &rect);
64
65 int metric(QPaintDevice::PaintDeviceMetric metric) const;
66 void fill(const QColor &color);
67 void setMask(const QBitmap &mask);
68 void setAlphaChannel(const QPixmap &alphaChannel);
69 QImage toImage() const;
70 QPaintEngine* paintEngine() const;
71
72 void beginDataAccess();
73 void endDataAccess(bool readOnly=false) const;
74
75private:
76 void release();
77 void fromSymbianBitmap(CFbsBitmap* bitmap);
78 bool initSymbianBitmapContext();
79
80 QSymbianBitmapDataAccess *symbianBitmapDataAccess;
81
82 CFbsBitmap *cfbsBitmap;
83 CFbsBitmapDevice *bitmapDevice;
84 CBitmapContext *bitmapContext;
85 QPaintEngine *pengine;
86 uchar* bytes;
87
88 friend class QPixmap;
89 friend class QS60WindowSurface;
90 friend class QS60PaintEngine;
91 friend class QS60Data;
92};
93
94QT_END_NAMESPACE
95
96#endif // QPIXMAPDATA_S60_P_H
  
4747#ifdef Q_WS_X11
4848# include <private/qpixmap_x11_p.h>
4949#endif
50#if defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN)
50#if defined(Q_WS_WIN)
5151# include <private/qpixmap_raster_p.h>
5252#endif
5353#ifdef Q_WS_MAC
5454# include <private/qpixmap_mac_p.h>
5555#endif
56#ifdef Q_WS_S60
57# include <private/qpixmap_s60_p.h>
58#endif
5659
5760#include "private/qapplication_p.h"
5861#include "private/qgraphicssystem_p.h"
7878
7979#if defined(Q_WS_X11)
8080 return new QX11PixmapData(type);
81#elif defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN)
81#elif defined(Q_WS_WIN)
8282 return new QRasterPixmapData(type);
8383#elif defined(Q_WS_MAC)
8484 return new QMacPixmapData(type);
85#elif defined(Q_WS_S60)
86 return new QS60PixmapData(type);
8587#else
8688#error QSimplePixmapDataFactory::create() not implemented
8789#endif
  
108108 bool virtualMouseRequired;
109109 int qtOwnsS60Environment : 1;
110110 static inline void updateScreenSize();
111 static inline RWsSession& wsSession();
111 static inline RWsSession& wsSession();
112112 static inline RWindowGroup& windowGroup();
113113 static inline CWsScreenDevice* screenDevice();
114114 static inline CCoeAppUi* appUi();
284284 format = QImage::Format_RGB16;
285285 break;
286286 case EColor16M:
287 format = QImage::Format_RGB666;
287 format = QImage::Format_RGB888;
288288 break;
289289 case EColor16MU:
290290 format = QImage::Format_RGB32;
  
1414 painting/qoutlinemapper_p.h \
1515 painting/qpaintdevice.h \
1616 painting/qpaintengine.h \
17 painting/qpaintengine_p.h \
17 painting/qpaintengine_p.h \
1818 painting/qpaintengine_alpha_p.h \
1919 painting/qpaintengine_preview_p.h \
2020 painting/qpaintengineex_p.h \
179179
180180symbian {
181181 SOURCES += \
182 painting/qpaintengine_s60.cpp \
182183 painting/qregion_s60.cpp \
183184 painting/qcolormap_s60.cpp
185
186 HEADERS += \
187 painting/qpaintengine_s60_p.h
184188}
185189
186190x11|embedded {
  
4444#ifdef Q_WS_X11
4545# include <private/qpixmap_x11_p.h>
4646#endif
47#if defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN)
47#if defined(Q_WS_WIN)
4848# include <private/qpixmap_raster_p.h>
4949#endif
5050#ifdef Q_WS_MAC
5151# include <private/qpixmap_mac_p.h>
5252#endif
53#ifdef Q_WS_S60
54# include <private/qpixmap_s60_p.h>
55#endif
5356
5457QT_BEGIN_NAMESPACE
5558
6767#endif
6868#if defined(Q_WS_X11)
6969 return new QX11PixmapData(type);
70#elif defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN)
70#elif defined(Q_WS_WIN)
7171 return new QRasterPixmapData(type);
7272#elif defined(Q_WS_MAC)
7373 return new QMacPixmapData(type);
74#elif defined(Q_WS_S60)
75 return new QS60PixmapData(type);
7476#elif !defined(Q_WS_QWS)
7577#error QGraphicsSystem::createDefaultPixmapData() not implemented
7678#endif
  
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information (qt-info@nokia.com)
5**
6** This file is part of the $MODULE$ of the Qt Toolkit.
7**
8** $TROLLTECH_DUAL_LICENSE$
9**
10****************************************************************************/
11
12#include <private/qpaintengine_s60_p.h>
13#include <private/qpixmap_s60_p.h>
14#include <private/qt_s60_p.h>
15
16QT_BEGIN_NAMESPACE
17
18class QS60PaintEnginePrivate : public QRasterPaintEnginePrivate
19{
20public:
21 QS60PaintEnginePrivate(QS60PaintEngine *engine) { }
22};
23
24QS60PaintEngine::QS60PaintEngine(QPaintDevice *device, QS60PixmapData *data)
25 : QRasterPaintEngine(*(new QS60PaintEnginePrivate(this)), device), pixmapData(data)
26{
27}
28
29bool QS60PaintEngine::begin(QPaintDevice *device)
30{
31 pixmapData->beginDataAccess();
32 return QRasterPaintEngine::begin(device);
33}
34
35bool QS60PaintEngine::end()
36{
37 bool ret = QRasterPaintEngine::end();
38 pixmapData->endDataAccess();
39 return ret;
40}
41
42void QS60PaintEngine::drawPixmap(const QPointF &p, const QPixmap &pm)
43{
44 QS60PixmapData *srcData = static_cast<QS60PixmapData *>(pm.pixmapData());
45 srcData->beginDataAccess();
46 QRasterPaintEngine::drawPixmap(p, pm);
47 srcData->endDataAccess();
48}
49
50void QS60PaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
51{
52 QS60PixmapData *srcData = static_cast<QS60PixmapData *>(pm.pixmapData());
53 srcData->beginDataAccess();
54 QRasterPaintEngine::drawPixmap(r, pm, sr);
55 srcData->endDataAccess();
56}
57
58void QS60PaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pm, const QPointF &sr)
59{
60 QS60PixmapData *srcData = static_cast<QS60PixmapData *>(pm.pixmapData());
61 srcData->beginDataAccess();
62 QRasterPaintEngine::drawTiledPixmap(r, pm, sr);
63 srcData->endDataAccess();
64}
65
66void QS60PaintEngine::prepare(QImage *image)
67{
68 QRasterBuffer *buffer = d_func()->rasterBuffer.data();
69 if (buffer)
70 buffer->prepare(image);
71}
72
73QT_END_NAMESPACE
  
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information (qt-info@nokia.com)
5**
6** This file is part of the $MODULE$ of the Qt Toolkit.
7**
8** $TROLLTECH_DUAL_LICENSE$
9**
10****************************************************************************/
11
12#ifndef QPAINTENGINE_S60_P_H
13#define QPAINTENGINE_S60_P_H
14
15//
16// W A R N I N G
17// -------------
18//
19// This file is not part of the Qt API. It exists for the convenience
20// of other Qt classes. This header file may change from version to
21// version without notice, or even be removed.
22//
23// We mean it.
24//
25
26#include "private/qpaintengine_raster_p.h"
27
28QT_BEGIN_NAMESPACE
29
30class QS60PaintEnginePrivate;
31class QS60PixmapData;
32
33class QS60PaintEngine : public QRasterPaintEngine
34{
35 Q_DECLARE_PRIVATE(QS60PaintEngine)
36
37public:
38 QS60PaintEngine(QPaintDevice *device, QS60PixmapData* data);
39 bool begin(QPaintDevice *device);
40 bool end();
41
42 void drawPixmap(const QPointF &p, const QPixmap &pm);
43 void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr);
44 void drawTiledPixmap(const QRectF &r, const QPixmap &pm, const QPointF &sr);
45
46 void prepare(QImage* image);
47
48private:
49 QS60PixmapData *pixmapData;
50};
51
52QT_END_NAMESPACE
53
54#endif // QPAINTENGINE_S60_P_H
  
4444#include <QtGui/qpaintdevice.h>
4545#include <private/qwidget_p.h>
4646#include "qwindowsurface_s60_p.h"
47#include "qpixmap_s60_p.h"
4748#include "qt_s60_p.h"
4849#include "private/qdrawhelper_p.h"
4950
5252
5353struct QS60WindowSurfacePrivate
5454{
55 QImage device;
56 CFbsBitmap *bitmap;
57 uchar* bytes;
58
59 // Since only one CFbsBitmap is allowed to be locked at a time, this is static.
60 static QS60WindowSurface* lockedSurface;
55 QPixmap device;
56 QList<QImage*> bufferImages;
6157};
62QS60WindowSurface* QS60WindowSurfacePrivate::lockedSurface = NULL;
6358
6459QS60WindowSurface::QS60WindowSurface(QWidget* widget)
6560 : QWindowSurface(widget), d_ptr(new QS60WindowSurfacePrivate)
6661{
67 d_ptr->bytes = 0;
68 d_ptr->bitmap = 0;
6962
7063 TDisplayMode mode = S60->screenDevice()->DisplayMode();
7164 bool isOpaque = qt_widget_private(widget)->isOpaque;
6767 else if (mode == EColor16MU && !isOpaque)
6868 mode = EColor16MA; // Try for transparency anyway
6969
70
7170 // We create empty CFbsBitmap here -> it will be resized in setGeometry
72 d_ptr->bitmap = q_check_ptr(new CFbsBitmap); // CBase derived object needs check on new
73 qt_symbian_throwIfError( d_ptr->bitmap->Create(TSize(0, 0), mode ) );
74
75 updatePaintDeviceOnBitmap();
76
71 CFbsBitmap *bitmap = q_check_ptr(new CFbsBitmap); // CBase derived object needs check on new
72 qt_symbian_throwIfError( bitmap->Create( TSize(0, 0), mode ) );
73
74 QS60PixmapData *data = new QS60PixmapData(QPixmapData::PixmapType);
75 data->fromSymbianBitmap(bitmap);
76 d_ptr->device = QPixmap(data);
77
7778 setStaticContentsSupport(true);
7879}
79
8080QS60WindowSurface::~QS60WindowSurface()
8181{
82 if (QS60WindowSurfacePrivate::lockedSurface == this)
83 unlockBitmapHeap();
84
85 delete d_ptr->bitmap;
8682 delete d_ptr;
8783}
8884
8985void QS60WindowSurface::beginPaint(const QRegion &rgn)
9086{
91 if(!d_ptr->bitmap)
92 return;
93
94 if (QS60WindowSurfacePrivate::lockedSurface)
95 unlockBitmapHeap();
96
97 QS60WindowSurfacePrivate::lockedSurface = this;
98 lockBitmapHeap();
99
10087 if (!qt_widget_private(window())->isOpaque) {
101 QRgb *data = reinterpret_cast<QRgb *>(d_ptr->device.bits());
102 const int row_stride = d_ptr->device.bytesPerLine() / 4;
88 QImage image = static_cast<QS60PixmapData *>(d_ptr->device.data_ptr().data())->image;
89 QRgb *data = reinterpret_cast<QRgb *>(image.bits());
90 const int row_stride = image.bytesPerLine() / 4;
10391
10492 const QVector<QRect> rects = rgn.rects();
10593 for (QVector<QRect>::const_iterator it = rects.begin(); it != rects.end(); ++it) {
106106 }
107107}
108108
109void QS60WindowSurface::endPaint(const QRegion &)
110{
111 qDeleteAll(d_ptr->bufferImages);
112 d_ptr->bufferImages.clear();
113}
114
115QImage* QS60WindowSurface::buffer(const QWidget *widget)
116{
117 if (widget->window() != window())
118 return 0;
119
120 QPaintDevice *pdev = paintDevice();
121 if (!pdev)
122 return 0;
123
124 const QPoint off = offset(widget);
125 QImage *img = &(static_cast<QS60PixmapData *>(d_ptr->device.data_ptr().data())->image);
126
127 QRect rect(off, widget->size());
128 rect &= QRect(QPoint(), img->size());
129
130 if (rect.isEmpty())
131 return 0;
132
133 img = new QImage(img->scanLine(rect.y()) + rect.x() * img->depth() / 8,
134 rect.width(), rect.height(),
135 img->bytesPerLine(), img->format());
136 d_ptr->bufferImages.append(img);
137
138 return img;
139}
140
109141void QS60WindowSurface::flush(QWidget *widget, const QRegion &region, const QPoint &)
110142{
111143 const QVector<QRect> subRects = region.rects();
157157 if (d_ptr->device.isNull())
158158 return false;
159159
160 CFbsBitmapDevice *bitmapDevice = 0;
161 QT_TRAP_THROWING(bitmapDevice = CFbsBitmapDevice::NewL(d_ptr->bitmap));
162 CBitmapContext *bitmapContext;
163 TInt err = bitmapDevice->CreateBitmapContext(bitmapContext);
164 if (err != KErrNone) {
165 CBase::Delete(bitmapDevice);
166 return false;
167 }
168 bitmapContext->CopyRect(TPoint(dx, dy), qt_QRect2TRect(rect));
169 CBase::Delete(bitmapContext);
170 CBase::Delete(bitmapDevice);
160 QS60PixmapData *data = static_cast<QS60PixmapData*>(d_ptr->device.data_ptr().data());
161 data->scroll(dx, dy, rect);
162
171163 return true;
172164}
173165
174void QS60WindowSurface::endPaint(const QRegion & /* rgn */)
175{
176 if(!d_ptr->bitmap)
177 return;
178
179 Q_ASSERT(QS60WindowSurfacePrivate::lockedSurface);
180 unlockBitmapHeap();
181 QS60WindowSurfacePrivate::lockedSurface = NULL;
182}
183
184166QPaintDevice* QS60WindowSurface::paintDevice()
185167{
186168 return &d_ptr->device;
173173 if (rect == geometry())
174174 return;
175175
176 QWindowSurface::setGeometry(rect);
176 QS60PixmapData *data = static_cast<QS60PixmapData*>(d_ptr->device.data_ptr().data());
177 data->resize(rect.width(), rect.height());
177178
178 TRect nativeRect(qt_QRect2TRect(rect));
179 qt_symbian_throwIfError(d_ptr->bitmap->Resize(nativeRect.Size()));
180
181 if (!rect.isNull())
182 updatePaintDeviceOnBitmap();
179 QWindowSurface::setGeometry(rect);
183180}
184181
185void QS60WindowSurface::lockBitmapHeap()
182CFbsBitmap* QS60WindowSurface::symbianBitmap() const
186183{
187 if (!QS60WindowSurfacePrivate::lockedSurface)
188 return;
189
190 // Get some local variables to make later code lines more clear to read
191 CFbsBitmap*& bitmap = QS60WindowSurfacePrivate::lockedSurface->d_ptr->bitmap;
192 QImage& device = QS60WindowSurfacePrivate::lockedSurface->d_ptr->device;
193 uchar*& bytes = QS60WindowSurfacePrivate::lockedSurface->d_ptr->bytes;
194
195 bitmap->LockHeap();
196 uchar *newBytes = (uchar*)bitmap->DataAddress();
197 if (newBytes != bytes) {
198 bytes = newBytes;
199
200 // Get some values for QImage creation
201 TDisplayMode mode = bitmap->DisplayMode();
202 if (mode == EColor16MA
203 && qt_widget_private(QS60WindowSurfacePrivate::lockedSurface->window())->isOpaque)
204 mode = EColor16MU;
205 QImage::Format format = qt_TDisplayMode2Format( mode );
206 TSize bitmapSize = bitmap->SizeInPixels();
207 int bytesPerLine = CFbsBitmap::ScanLineLength( bitmapSize.iWidth, mode);
208
209 device = QImage( bytes, bitmapSize.iWidth, bitmapSize.iHeight, bytesPerLine, format );
210 }
211}
212
213void QS60WindowSurface::unlockBitmapHeap()
214{
215 if (!QS60WindowSurfacePrivate::lockedSurface)
216 return;
217
218 QS60WindowSurfacePrivate::lockedSurface->d_ptr->bitmap->UnlockHeap();
219}
220
221void QS60WindowSurface::updatePaintDeviceOnBitmap()
222{
223 // This forces the actual device to be updated based on CFbsBitmap
224 beginPaint(QRegion());
225 endPaint(QRegion());
226}
227
228CFbsBitmap *QS60WindowSurface::symbianBitmap() const
229{
230 return d_ptr->bitmap;
184 QS60PixmapData *data = static_cast<QS60PixmapData*>(d_ptr->device.data_ptr().data());
185 return data->cfbsBitmap;
231186}
232187
233188QT_END_NAMESPACE
  
7575 void beginPaint(const QRegion &);
7676 void endPaint(const QRegion &);
7777
78 QImage* buffer(const QWidget *widget);
79
7880 void setGeometry(const QRect &rect);
7981
80 static void lockBitmapHeap();
81 static void unlockBitmapHeap();
82
8382 CFbsBitmap *symbianBitmap() const;
84
85private:
86 void updatePaintDeviceOnBitmap();
8783
8884private:
8985 QS60WindowSurfacePrivate* d_ptr;
  
4444#include "qpainter.h"
4545#include "qstyleoption.h"
4646#include "qstyle.h"
47#include "private/qwindowsurface_s60_p.h"
4847#include "private/qt_s60_p.h"
48#include "private/qpixmap_s60_p.h"
4949#include "private/qcore_symbian_p.h"
5050#include "qapplication.h"
5151
11361136QPixmap QS60StylePrivate::part(QS60StyleEnums::SkinParts part,
11371137 const QSize &size, SkinElementFlags flags)
11381138{
1139 QS60WindowSurface::unlockBitmapHeap();
1139 QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock);
1140
11401141 QPixmap result = (flags & SF_ColorSkinned)?
11411142 QS60StyleModeSpecifics::colorSkinnedGraphics(part, size, flags)
11421143 : QS60StyleModeSpecifics::skinnedGraphics(part, size, flags);
1143 QS60WindowSurface::lockBitmapHeap();
1144
1145 lock.relock();
11441146
11451147 if (flags & SF_StateDisabled && !QS60StyleModeSpecifics::disabledPartGraphic(part)) {
11461148 QStyleOption opt;
11601160
11611161QPixmap QS60StylePrivate::frame(SkinFrameElements frame, const QSize &size, SkinElementFlags flags)
11621162{
1163 QS60WindowSurface::unlockBitmapHeap();
1163 QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock);
11641164 QPixmap result = QS60StyleModeSpecifics::skinnedGraphics(frame, size, flags);
1165 QS60WindowSurface::lockBitmapHeap();
1165 lock.relock();
11661166
11671167 if (flags & SF_StateDisabled && !QS60StyleModeSpecifics::disabledFrameGraphic(frame)) {
11681168 QStyleOption opt;
  
4141
4242#include "qfont.h"
4343#include "qt_s60_p.h"
44#include <private/qwindowsurface_s60_p.h>
44#include "qpixmap_s60_p.h"
4545#include "qmutex.h"
4646
4747QT_BEGIN_NAMESPACE
5757 QMutexLocker locker(lastResortFamilyMutex());
5858 static QString family;
5959 if (family.isEmpty()) {
60 QS60WindowSurface::unlockBitmapHeap();
60
61 QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock);
62
6163 CFont *font;
6264 const TInt err = S60->screenDevice()->GetNearestFontInTwips(font, TFontSpec());
6365 Q_ASSERT(err == KErrNone);
6466 const TFontSpec spec = font->FontSpecInTwips();
6567 family = QString((const QChar *)spec.iTypeface.iName.Ptr(), spec.iTypeface.iName.Length());
6668 S60->screenDevice()->ReleaseFont(font);
67 QS60WindowSurface::lockBitmapHeap();
69
70 lock.relock();
6871 }
6972 return family;
7073#else
  
4545#include "qfontengine_s60_p.h"
4646#include "qabstractfileengine.h"
4747#include "qdesktopservices.h"
48#include "qpixmap_s60_p.h"
4849#include "qt_s60_p.h"
4950#include "qendian.h"
50#include <private/qwindowsurface_s60_p.h>
5151#include <private/qcore_symbian_p.h>
5252#if defined(QT_NO_FREETYPE)
5353#include <OPENFONT.H>
217217 if (!db->s60Store)
218218 db->s60Store = new QFontDatabaseS60StoreImplementation;
219219
220 QS60WindowSurface::unlockBitmapHeap();
220 QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock);
221
221222 const int numTypeFaces = QS60Data::screenDevice()->NumTypefaces();
222223 const QFontDatabaseS60StoreImplementation *store = dynamic_cast<const QFontDatabaseS60StoreImplementation*>(db->s60Store);
223224 Q_ASSERT(store);
272272 }
273273 QS60Data::screenDevice()->ReleaseFont(font);
274274 }
275
275276 Q_ASSERT(fontAdded);
276 QS60WindowSurface::lockBitmapHeap();
277
278 lock.relock();
279
277280#else // defined(QT_NO_FREETYPE)
278281 QDir dir(QDesktopServices::storageLocation(QDesktopServices::FontsLocation));
279282 dir.setNameFilters(QStringList() << QLatin1String("*.ttf")
  
4343#include "qtextengine_p.h"
4444#include "qglobal.h"
4545#include <private/qapplication_p.h>
46#include <private/qwindowsurface_s60_p.h>
4746#include "qimage.h"
4847#include "qt_s60_p.h"
48#include "qpixmap_s60_p.h"
4949
5050#include <e32base.h>
5151#include <e32std.h>
136136 QFontEngine::fontDef = request;
137137 m_fontSizeInPixels = (request.pixelSize >= 0)?
138138 request.pixelSize:pointsToPixels(request.pointSize);
139 QS60WindowSurface::unlockBitmapHeap();
139
140 QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock);
141
140142 m_textRenderBitmap = q_check_ptr(new CFbsBitmap()); // CBase derived object needs check on new
141143 const TSize bitmapSize(1, 1); // It is just a dummy bitmap that I need to keep the font alive (or maybe not)
142144 qt_symbian_throwIfError(m_textRenderBitmap->Create(bitmapSize, EGray256));
153153 const TInt errorCode = m_textRenderBitmapDevice->GetNearestFontInPixels(m_font, fontSpec);
154154 Q_ASSERT(errorCode == 0);
155155 m_textRenderBitmapGc->UseFont(m_font);
156 QS60WindowSurface::lockBitmapHeap();
156
157 lock.relock();
157158}
158159
159160QFontEngineS60::~QFontEngineS60()
160161{
161 QS60WindowSurface::unlockBitmapHeap();
162 QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock);
163
162164 m_textRenderBitmapGc->DiscardFont();
163165 delete m_textRenderBitmapGc;
164166 m_textRenderBitmapGc = NULL;
169169 m_textRenderBitmapDevice = NULL;
170170 delete m_textRenderBitmap;
171171 m_textRenderBitmap = NULL;
172 QS60WindowSurface::lockBitmapHeap();
172
173 lock.relock();
173174}
174175
175176bool QFontEngineS60::stringToCMap(const QChar *characters, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const