Changeset 267 for trunk/src/gui/image/qpixmap_pm.cpp
- Timestamp:
- Oct 29, 2009, 10:11:44 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/gui/image/qpixmap_pm.cpp
r264 r267 102 102 icons and pointers (\sa toPmHPOINTER()). 103 103 104 Note that if the pixmap does neither have a maks nor the alpha channel but 104 if \a embedRealAlpha is \c true, the real alpha chennel (not the 1bpp mask) 105 will be embedded in the high 8 bits of the 32-bit pixel value for each pixel 106 in the created bitmap (which always has 1 plane and the 32-bit depth). This 107 extra information isn't touched by PM/GPI but may be used by custom drawing 108 routines to do real alpha blending. 109 110 Note that if the pixmap does neither have a mask nor the alpha channel but 105 111 \a mask is not NULL, a NULLHANDLE value will be stored there. 106 112 … … 110 116 \warning This function is only available on OS/2. 111 117 */ 112 HBITMAP QPixmap::toPmHBITMAP(HBITMAP *mask ) const118 HBITMAP QPixmap::toPmHBITMAP(HBITMAP *mask) const 113 119 { 114 120 if (data->classId() != QPixmapData::RasterClass) { … … 130 136 HBITMAP hbmMask = NULLHANDLE; 131 137 132 QImage image = d->image.convertToFormat(QImage::Format_ARGB32).mirrored(); 138 // Note that we always use ARGB32 even if embedRealAlpha is false because 139 // in this case we will use the alpha channel to dither the 1bpp mask 140 QImage image = d->image.convertToFormat(QImage::Format_ARGB32); 141 // flip the bitmap top to bottom for PM 142 image = image.mirrored(); 133 143 134 144 // bitmap header + 2 palette entries (for the mask) … … 148 158 149 159 if (mask && hasAlpha()) { 150 // get the mask. We prefer QImage::createAlphaMask() over QPixmap::mask() 151 // since the former will dither while the latter will convert any 152 // non-zero alpha value to an opaque pixel 153 #if 1 154 QImage mask = image.createAlphaMask().convertToFormat(QImage::Format_Mono); 155 156 // note: for some strange reason, createAlphaMask() (as opposed to 157 // mask().toImage()) returns an image already flipped top to bottom, 158 // so take it into account 159 160 // create the AND mask 161 mask.invertPixels(); 162 // add the XOR mask (and leave it zeroed) 163 mask = mask.copy(0, -h, w, h * 2); 164 165 #else 166 QImage mask = this->mask().toImage().convertToFormat(QImage::Format_Mono); 167 168 // create the AND mask 169 mask.invertPixels(); 170 // add the XOR mask (and leave it zeroed) 171 mask = mask.copy(0, 0, w, h * 2); 172 // flip the bitmap top to bottom for PM 173 mask = mask.mirrored(false, true); 174 #endif 160 // get the mask 161 QImage mask; 162 if (!embedRealAlpha) { 163 // We prefer QImage::createAlphaMask() over QPixmap::mask() 164 // since the former will dither while the latter will convert any 165 // non-zero alpha value to an opaque pixel 166 mask = image.createAlphaMask().convertToFormat(QImage::Format_Mono); 167 168 // note: for some strange reason, createAlphaMask() (as opposed to 169 // mask().toImage()) returns an image already flipped top to bottom, 170 // so take it into account 171 172 // create the AND mask 173 mask.invertPixels(); 174 // add the XOR mask (and leave it zeroed) 175 mask = mask.copy(0, -h, w, h * 2); 176 } else { 177 // if we embedded real alpha, we still need a mask if we are going 178 // to create a pointer out of this pixmap (WinCreatePointerIndirect() 179 // requirement), but we will use QPixmap::mask() because it won't be 180 // able to destroy the alpha channel of non-fully transparent pixels 181 // when preparing the color bitmap for masking later. We could also 182 // skip this prepare step, but well, let's go this way, it won't hurt. 183 mask = this->mask().toImage().convertToFormat(QImage::Format_Mono); 184 185 // create the AND mask 186 mask.invertPixels(); 187 // add the XOR mask (and leave it zeroed) 188 mask = mask.copy(0, 0, w, h * 2); 189 // flip the bitmap top to bottom for PM 190 mask = mask.mirrored(false, true); 191 } 175 192 176 193 // create the mask bitmap … … 192 209 POINTL ptls[] = { 193 210 { 0, 0 }, { w - 1, h - 1 }, // dst: inclusive-inclusive 194 { 0, h }, { w, h * 2 }, 211 { 0, h }, { w, h * 2 }, // src: inclusive-exclusive 195 212 }; 196 213 ptls[0].y -= h; … … 217 234 If \a isPointer is \c true, an icon size closest to the system pointer size 218 235 is chosen, otherwise to the system icon size. \a hotX and \a hotY define the 219 hot spot. 236 hot spot. Note is that the size of the resulting pointer will exactly match 237 the system size no matter what size the matched icon is. Smaller icons will 238 be centered in a box corresponding to the system size, larger icons will 239 be scaled down. 240 241 If \a embedRealAlpha is \c true, the color bitmap in the pointer will have 242 the alpha channel embedded in it (see toPmHBITMAP() for details). 243 244 Note that due to the bug in WinCreatePointerIndirect(), hbmMiniPointer and 245 hbmMiniColor field of the POINTERINFO structure are always ignored. For this 246 reason, the caller must choose what icon size (normal or half-size) he wants 247 to get using the \a isMini argument. A bitmap of the respective size will be 248 created and assigned to the hbmColor field. 220 249 221 250 It is the caller's responsibility to free the \c HPOINTER data … … 226 255 // static 227 256 HPOINTER QPixmap::toPmHPOINTER(const QIcon &icon, bool isPointer, 228 int hotX, int hotY) 257 int hotX, int hotY, bool embedRealAlpha, 258 bool isMini) 229 259 { 230 260 if (icon.isNull()) … … 234 264 int w = WinQuerySysValue(HWND_DESKTOP, isPointer ? SV_CXPOINTER : SV_CXICON); 235 265 int h = WinQuerySysValue(HWND_DESKTOP, isPointer ? SV_CYPOINTER : SV_CYICON); 236 int w2 = w / 2; 237 int h2 = h / 2; 238 239 // obtain the closest (but never larger) icon sizes we have 266 if (isMini) { 267 w = w / 2; 268 h = h / 2; 269 } 270 271 // obtain the closest (but never larger) icon size we have 240 272 QSize size = icon.actualSize(QSize(w, h)); 241 QSize sizeMini = icon.actualSize(QSize(w2, h2));242 273 243 274 QPixmap pm = icon.pixmap(size); 244 QPixmap pmMini = icon.pixmap(sizeMini); 245 if (pm.isNull() && pmMini.isNull()) 246 return NULLHANDLE; 247 248 // if we got smaller pixmaps then center them inside the system sized rect 249 // instead of letting WinCreatePointerIndirect() scale them (this covers a 250 // usual case when we got 32 and 16 px pixmaps on a 120 DPI system where the 251 // icon size is 40 and 20 px respectively): scaling such small images looks 252 // really ugly. 275 if (pm.isNull()) 276 return NULLHANDLE; 277 278 // if we got a smaller pixmap then center it inside the box matching the 279 // system size instead of letting WinCreatePointerIndirect() scale (this 280 // covers a usual case when we get 32/16 px pixmaps on a 120 DPI system 281 // where the icon size is 40/20 px respectively): scaling such small images 282 // looks really ugly. 253 283 if (!pm.isNull() && (pm.width() < w || pm.height() < h)) { 254 284 Q_ASSERT(pm.width() <= w && pm.height() <= h); … … 259 289 pm = pmNew; 260 290 } 261 if (!pmMini.isNull() && (pmMini.width() < w2 || pmMini.height() < h2)) {262 Q_ASSERT(pmMini.width() <= w2 && pmMini.height() <= h2);263 QPixmap pmNew(w2, h2);264 pmNew.fill(Qt::transparent);265 QPainter painter(&pmNew);266 painter.drawPixmap((w2 - pmMini.width()) / 2, (h2 - pmMini.height()) / 2, pmMini);267 pmMini = pmNew;268 }269 270 if (pm.isNull()) {271 // if we only have the mini icon, use it as a normal one;272 // WinCreatePointerIndirect() will figure that and not scale it273 pm = pmMini;274 pmMini = QPixmap();275 }276 291 277 292 POINTERINFO info; … … 279 294 info.xHotspot = hotX; 280 295 info.yHotspot = hotY; 281 info.hbmColor = pm.toPmHBITMAP(&info.hbmPointer); 282 if (!pmMini.isNull()) { 283 info.hbmMiniColor = pmMini.toPmHBITMAP(&info.hbmMiniPointer); 284 } else { 285 info.hbmMiniPointer = NULLHANDLE; 286 info.hbmMiniColor = NULLHANDLE; 287 } 296 info.hbmColor = pm.toPmHBITMAP(&info.hbmPointer, embedRealAlpha); 297 info.hbmMiniPointer = NULLHANDLE; 298 info.hbmMiniColor = NULLHANDLE; 288 299 289 300 HPOINTER hIcon = WinCreatePointerIndirect(HWND_DESKTOP, &info); … … 291 302 GpiDeleteBitmap(info.hbmPointer); 292 303 GpiDeleteBitmap(info.hbmColor); 293 GpiDeleteBitmap(info.hbmMiniPointer);294 GpiDeleteBitmap(info.hbmMiniColor);295 304 296 305 return hIcon;
Note:
See TracChangeset
for help on using the changeset viewer.