// FIXME: Is it possible to merge getWindowsContext and createWindowsBitmap into a single API // suitable for all clients? void GraphicsContext::releaseWindowsContext(HDC hdc, const IntRect& dstRect, bool supportAlphaBlend, bool mayCreateBitmap) { bool createdBitmap = mayCreateBitmap && (!m_data->m_hdc || isInTransparencyLayer()); if (!createdBitmap) { m_data->restore(); return; } if (dstRect.isEmpty()) return; OwnPtr<HBITMAP> bitmap = adoptPtr(static_cast<HBITMAP>(GetCurrentObject(hdc, OBJ_BITMAP))); DIBPixelData pixelData(bitmap.get()); ASSERT(pixelData.bitsPerPixel() == 32); CGContextRef bitmapContext = CGBitmapContextCreate(pixelData.buffer(), pixelData.size().width(), pixelData.size().height(), 8, pixelData.bytesPerRow(), deviceRGBColorSpaceRef(), kCGBitmapByteOrder32Little | (supportAlphaBlend ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst)); CGImageRef image = CGBitmapContextCreateImage(bitmapContext); CGContextDrawImage(m_data->m_cgContext.get(), dstRect, image); // Delete all our junk. CGImageRelease(image); CGContextRelease(bitmapContext); ::DeleteDC(hdc); }
void GraphicsContext::releaseWindowsContext(HDC hdc, const IntRect& dstRect, bool supportAlphaBlend, bool mayCreateBitmap) { bool createdBitmap = mayCreateBitmap && (!m_data->m_hdc || isInTransparencyLayer()); if (!hdc || !createdBitmap) { m_data->restore(); return; } if (dstRect.isEmpty()) return; OwnPtr<HBITMAP> bitmap = adoptPtr(static_cast<HBITMAP>(GetCurrentObject(hdc, OBJ_BITMAP))); DIBPixelData pixelData(bitmap.get()); ASSERT(pixelData.bitsPerPixel() == 32); // If this context does not support alpha blending, then it may have // been drawn with GDI functions which always set the alpha channel // to zero. We need to manually set the bitmap to be fully opaque. unsigned char* bytes = reinterpret_cast<unsigned char*>(pixelData.buffer()); if (!supportAlphaBlend) setRGBABitmapAlpha(bytes, pixelData.size().height() * pixelData.bytesPerRow(), 255); drawBitmapToContext(m_data, platformContext()->cr(), pixelData, IntSize(dstRect.x(), dstRect.height() + dstRect.y())); ::DeleteDC(hdc); }
HDC GraphicsContext::getWindowsContext(const IntRect& dstRect, bool supportAlphaBlend, bool mayCreateBitmap) { // FIXME: Should a bitmap be created also when a shadow is set? if (mayCreateBitmap && (!m_data->m_hdc || isInTransparencyLayer())) { if (dstRect.isEmpty()) return 0; // Create a bitmap DC in which to draw. BitmapInfo bitmapInfo = BitmapInfo::create(dstRect.size()); void* pixels = 0; HBITMAP bitmap = ::CreateDIBSection(NULL, &bitmapInfo, DIB_RGB_COLORS, &pixels, 0, 0); if (!bitmap) return 0; auto bitmapDC = adoptGDIObject(::CreateCompatibleDC(m_data->m_hdc)); ::SelectObject(bitmapDC.get(), bitmap); // Fill our buffer with clear if we're going to alpha blend. if (supportAlphaBlend) fillWithClearColor(bitmap); // Make sure we can do world transforms. ::SetGraphicsMode(bitmapDC.get(), GM_ADVANCED); // Apply a translation to our context so that the drawing done will be at (0,0) of the bitmap. XFORM xform = TransformationMatrix().translate(-dstRect.x(), -dstRect.y()); ::SetWorldTransform(bitmapDC.get(), &xform); return bitmapDC.leak(); } m_data->flush(); m_data->save(); return m_data->m_hdc; }