gfxWindowsSurface::gfxWindowsSurface(const gfxIntSize& size, gfxImageFormat imageFormat) : mOwnsDC(PR_FALSE), mForPrinting(PR_FALSE), mWnd(nsnull) { if (!CheckSurfaceSize(size)) return; cairo_surface_t *surf = cairo_win32_surface_create_with_dib((cairo_format_t)imageFormat, size.width, size.height); Init(surf); RecordMemoryUsed(size.width * size.height * 4 + sizeof(gfxWindowsSurface)); if (CairoStatus() == 0) mDC = cairo_win32_surface_get_dc(CairoSurface()); else mDC = nsnull; }
PassRefPtr<BitmapImage> BitmapImage::create(HBITMAP hBitmap) { DIBSECTION dibSection; if (!GetObject(hBitmap, sizeof(DIBSECTION), &dibSection)) return 0; ASSERT(dibSection.dsBm.bmBitsPixel == 32); if (dibSection.dsBm.bmBitsPixel != 32) return 0; ASSERT(dibSection.dsBm.bmBits); if (!dibSection.dsBm.bmBits) return 0; RefPtr<cairo_surface_t> surface = adoptRef(cairo_win32_surface_create_with_dib(CAIRO_FORMAT_ARGB32, dibSection.dsBm.bmWidth, dibSection.dsBm.bmHeight)); return BitmapImage::create(surface.release()); }
PassRefPtr<BitmapImage> BitmapImage::create(HBITMAP hBitmap) { DIBSECTION dibSection; if (!GetObject(hBitmap, sizeof(DIBSECTION), &dibSection)) return 0; ASSERT(dibSection.dsBm.bmBitsPixel == 32); if (dibSection.dsBm.bmBitsPixel != 32) return 0; ASSERT(dibSection.dsBm.bmBits); if (!dibSection.dsBm.bmBits) return 0; cairo_surface_t* image = cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32, dibSection.dsBm.bmWidth, dibSection.dsBm.bmHeight); // The BitmapImage object takes over ownership of the cairo_surface_t*, so no need to destroy here. return adoptRef(new BitmapImage(image)); }
gfxWindowsSurface::gfxWindowsSurface(const gfxIntSize& realSize, gfxImageFormat imageFormat) : mOwnsDC(false), mForPrinting(false), mWnd(nullptr) { gfxIntSize size(realSize); if (!CheckSurfaceSize(size)) MakeInvalid(size); cairo_surface_t *surf = cairo_win32_surface_create_with_dib((cairo_format_t)(int)imageFormat, size.width, size.height); Init(surf); if (CairoStatus() == CAIRO_STATUS_SUCCESS) { mDC = cairo_win32_surface_get_dc(CairoSurface()); RecordMemoryUsed(size.width * size.height * 4 + sizeof(gfxWindowsSurface)); } else { mDC = nullptr; } }
// Method: SetDragImage // Not part of Win32 API. // Notes in http://msdn.microsoft.com/en-us/library/windows/desktop/bb762034(v=vs.85).aspx say: // The drag-and-drop helper object calls IDataObject::SetData to load private formats—used for // cross-process support—into the data object. It later retrieves these formats by calling // IDataObject::GetData. To support the drag-and-drop helper object, the data object's SetData // and GetData implementations must be able to accept and return arbitrary private formats. // Because we don't know how the drag-and-drop helper is going to call SetData and GetData, // and we don't need to support drag and drop across processes, we'll just manage this ourselves. void WinCE_SetDragImage(SHDRAGIMAGE * dragImage) { memcpy(¤tDragImage, dragImage, sizeof(SHDRAGIMAGE)); BITMAP info; if (GetObject(currentDragImage.hbmpDragImage, sizeof(info), &info) == 0) return; unsigned char * bits = (unsigned char *) info.bmBits; // Windows flips bitmaps. Flip it back. // See Top-Down vs. Bottom-Up DIBs // http://msdn.microsoft.com/en-us/library/windows/desktop/dd407212(v=vs.85).aspx if (info.bmHeight > 0) { LONG bmSize = info.bmWidthBytes * info.bmHeight; bits = (unsigned char *)fastMalloc(bmSize); for (int y = 0; y < info.bmHeight; y++) { unsigned char * dst = bits + (info.bmHeight - y - 1) * info.bmWidthBytes; unsigned char * src = (unsigned char *)info.bmBits + y * info.bmWidthBytes; memcpy(dst, src, info.bmWidthBytes); } } cairo_surface_t* imageSurface = cairo_image_surface_create_for_data((unsigned char*)bits, info.bmBitsPixel == 32 ? CAIRO_FORMAT_ARGB32 : info.bmBitsPixel == 24 ? CAIRO_FORMAT_RGB24 : info.bmBitsPixel == 16 ? CAIRO_FORMAT_RGB16_565 : CAIRO_FORMAT_INVALID, info.bmWidth, info.bmHeight > 0 ? info.bmHeight : -info.bmHeight, info.bmWidthBytes); dragImageCairo = cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32, dragImage->sizeDragImage.cx, dragImage->sizeDragImage.cy); cairo_t *cr = cairo_create(dragImageCairo); cairo_set_source_surface(cr, imageSurface, 0, 0); cairo_paint_with_alpha(cr, 0.5); cairo_destroy(cr); cairo_surface_destroy(imageSurface); if (bits != info.bmBits) fastFree(bits); }
gfxWindowsSurface::gfxWindowsSurface(const mozilla::gfx::IntSize& realSize, gfxImageFormat imageFormat) : mOwnsDC(false), mWnd(nullptr) { mozilla::gfx::IntSize size(realSize); if (!mozilla::gfx::Factory::CheckSurfaceSize(size)) MakeInvalid(size); cairo_format_t cformat = GfxFormatToCairoFormat(imageFormat); cairo_surface_t *surf = cairo_win32_surface_create_with_dib(cformat, size.width, size.height); Init(surf); if (CairoStatus() == CAIRO_STATUS_SUCCESS) { mDC = cairo_win32_surface_get_dc(CairoSurface()); RecordMemoryUsed(size.width * size.height * 4 + sizeof(gfxWindowsSurface)); } else { mDC = nullptr; } }
already_AddRefed<gfxASurface> gfxWindowsSurface::CreateSimilarSurface(gfxContentType aContent, const gfxIntSize& aSize) { if (!mSurface || !mSurfaceValid) { return nullptr; } cairo_surface_t *surface; if (!mForPrinting && GetContentType() == gfxContentType::COLOR_ALPHA) { // When creating a similar surface to a transparent surface, ensure // the new surface uses a DIB. cairo_surface_create_similar won't // use a DIB for a gfxContentType::COLOR surface if this surface doesn't // have a DIB (e.g. if we're a transparent window surface). But // we need a DIB to perform well if the new surface is composited into // a surface that's the result of create_similar(gfxContentType::COLOR_ALPHA) // (e.g. a backbuffer for the window) --- that new surface *would* // have a DIB. surface = cairo_win32_surface_create_with_dib((cairo_format_t)(int)gfxPlatform::GetPlatform()->OptimalFormatForContent(aContent), aSize.width, aSize.height); } else { surface = cairo_surface_create_similar(mSurface, (cairo_content_t)(int)aContent, aSize.width, aSize.height); } if (cairo_surface_status(surface)) { cairo_surface_destroy(surface); return nullptr; } nsRefPtr<gfxASurface> result = Wrap(surface); if (mForPrinting) { MOZ_ASSERT(result->GetType() == gfxSurfaceType::Recording); gfxUnknownSurface *unknown = static_cast<gfxUnknownSurface*>(result.get()); unknown->SetSize(aSize); } cairo_surface_destroy(surface); return result.forget(); }
already_AddRefed<gfxASurface> gfxWindowsSurface::CreateSimilarSurface(gfxContentType aContent, const mozilla::gfx::IntSize& aSize) { if (!mSurface || !mSurfaceValid) { return nullptr; } cairo_surface_t *surface; if (!mForPrinting && GetContentType() == gfxContentType::COLOR_ALPHA) { // When creating a similar surface to a transparent surface, ensure // the new surface uses a DIB. cairo_surface_create_similar won't // use a DIB for a gfxContentType::COLOR surface if this surface doesn't // have a DIB (e.g. if we're a transparent window surface). But // we need a DIB to perform well if the new surface is composited into // a surface that's the result of create_similar(gfxContentType::COLOR_ALPHA) // (e.g. a backbuffer for the window) --- that new surface *would* // have a DIB. gfxImageFormat gformat = gfxPlatform::GetPlatform()->OptimalFormatForContent(aContent); cairo_format_t cformat = gfxImageFormatToCairoFormat(gformat); surface = cairo_win32_surface_create_with_dib(cformat, aSize.width, aSize.height); } else { surface = cairo_surface_create_similar(mSurface, (cairo_content_t)(int)aContent, aSize.width, aSize.height); } if (cairo_surface_status(surface)) { cairo_surface_destroy(surface); return nullptr; } RefPtr<gfxASurface> result = Wrap(surface, aSize); cairo_surface_destroy(surface); return result.forget(); }
HDC GraphicsContext::getWindowsContext(const IntRect& dstRect, bool supportAlphaBlend, bool mayCreateBitmap) { if (dstRect.isEmpty()) return 0; if(!m_data->hdc_refcount++) { m_data->hdc_surface = cairo_win32_surface_create_with_dib(CAIRO_FORMAT_RGB24, dstRect.width(), dstRect.height()); // see http://cairographics.org/FAQ/#paint_from_a_surface cairo_surface_t* source = cairo_get_target( m_data->cr ); cairo_t *cr = cairo_create ( m_data->hdc_surface ); cairo_set_source_surface (cr, source, -dstRect.x(), -dstRect.y() ); cairo_paint(cr); cairo_destroy(cr); m_data->m_hdc = cairo_win32_surface_get_dc(m_data->hdc_surface); SaveDC(m_data->m_hdc); } HDC hdc = m_data->m_hdc; return hdc; }
already_AddRefed<gfxASurface> gfxWindowsSurface::CreateSimilarSurface(gfxContentType aContent, const gfxIntSize& aSize) { if (!mSurface || !mSurfaceValid) { return nsnull; } cairo_surface_t *surface; if (GetContentType() == CONTENT_COLOR_ALPHA) { // When creating a similar surface to a transparent surface, ensure // the new surface uses a DIB. cairo_surface_create_similar won't // use a DIB for a CONTENT_COLOR surface if this surface doesn't // have a DIB (e.g. if we're a transparent window surface). But // we need a DIB to perform well if the new surface is composited into // a surface that's the result of create_similar(CONTENT_COLOR_ALPHA) // (e.g. a backbuffer for the window) --- that new surface *would* // have a DIB. surface = cairo_win32_surface_create_with_dib(cairo_format_t(gfxASurface::FormatFromContent(aContent)), aSize.width, aSize.height); } else { surface = cairo_surface_create_similar(mSurface, cairo_content_t(aContent), aSize.width, aSize.height); } if (cairo_surface_status(surface)) { cairo_surface_destroy(surface); return nsnull; } nsRefPtr<gfxASurface> result = Wrap(surface); cairo_surface_destroy(surface); return result.forget(); }
static VALUE cr_win32_surface_initialize (int argc, VALUE *argv, VALUE self) { cairo_surface_t *surface = NULL; VALUE arg1, arg2, arg3, arg4; VALUE hdc, format, width, height; rb_scan_args (argc, argv, "13", &arg1, &arg2, &arg3, &arg4); switch (argc) { case 1: hdc = arg1; surface = cairo_win32_surface_create (NUM2PTR (hdc)); break; case 2: width = arg1; height = arg2; surface = cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32, NUM2INT (width), NUM2INT (height)); break; case 3: if (NIL_P (arg1) || (rb_cairo__is_kind_of (arg1, rb_cNumeric) && NUM2INT (arg1) != CAIRO_FORMAT_RGB24)) { # if CAIRO_CHECK_VERSION(1, 4, 0) HDC win32_hdc; hdc = arg1; width = arg2; height = arg3; win32_hdc = NIL_P (hdc) ? NULL : NUM2PTR (hdc); surface = cairo_win32_surface_create_with_ddb (win32_hdc, CAIRO_FORMAT_RGB24, NUM2INT (width), NUM2INT (height)); # else rb_raise (rb_eArgError, "Cairo::Win32Surface.new(hdc, width, height) " "is available since cairo >= 1.4.0"); # endif } else { format = arg1; width = arg2; height = arg3; surface = cairo_win32_surface_create_with_dib (RVAL2CRFORMAT (format), NUM2INT (width), NUM2INT (height)); } break; case 4: { # if CAIRO_CHECK_VERSION(1, 4, 0) HDC win32_hdc; hdc = arg1; format = arg2; width = arg3; height = arg4; win32_hdc = NIL_P (hdc) ? NULL : (HDC) NUM2UINT (hdc); surface = cairo_win32_surface_create_with_ddb (win32_hdc, RVAL2CRFORMAT (format), NUM2INT (width), NUM2INT (height)); # else rb_raise (rb_eArgError, "Cairo::Win32Surface.new(hdc, format, width, height) " "is available since cairo >= 1.4.0"); # endif } break; } if (!surface) rb_cairo_check_status (CAIRO_STATUS_INVALID_FORMAT); cr_surface_check_status (surface); DATA_PTR (self) = surface; if (rb_block_given_p ()) yield_and_finish (self); return Qnil; }
static void drawDragImage(cairo_t *crScreen, POINT dest, POINT * prevLoc, IWebViewPrivate * webView, HWND targetWindow, bool drawDragImage, RECT * dirty) { int width = currentDragImage.sizeDragImage.cx; int height = currentDragImage.sizeDragImage.cy; // If we are dragging over a webview we know how to get its // backing store and therefore how to draw over it. //1. Determine the union of where the drag image was and where it now is. SIZE unionImageSize = {width, height}; POINT unionPoint = {dest.x, dest.y}; if (prevLoc) { unionImageSize.cx += prevLoc->x > dest.x ? prevLoc->x - dest.x : dest.x - prevLoc->x; unionImageSize.cy += prevLoc->y > dest.y ? prevLoc->y - dest.y : dest.y - prevLoc->y; if (prevLoc->x < dest.x) unionPoint.x = prevLoc->x; if (prevLoc->y < dest.y) unionPoint.y = prevLoc->y; } RECT unionRect = {unionPoint.x, unionPoint.y, unionPoint.x + unionImageSize.cx, unionPoint.y + unionImageSize.cy}; if (dirty) { // if there is a dirty rect, we may not need to paint at all. if (IntersectRect(&unionRect, dirty, &unionRect) == 0) return; } //2. Get the webview backing store, put it in a cairo surface. HBITMAP backingStore; HRESULT hr = webView->backingStore((OLE_HANDLE*) &backingStore); if (FAILED(hr)) return; BITMAP info; if (GetObject(backingStore, sizeof(info), &info) == 0) return; ASSERT(info.bmBitsPixel == 32); cairo_surface_t* webviewImage = cairo_image_surface_create_for_data((unsigned char*)info.bmBits, CAIRO_FORMAT_ARGB32, info.bmWidth, info.bmHeight, info.bmWidthBytes); //3. Create a bitmap the size of the union. cairo_surface_t * unionImage = cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32, unionImageSize.cx, unionImageSize.cy); //4. Copy the webview backing store into the bitmap. POINT webViewPoint = unionPoint; if (targetWindow) ::ScreenToClient(targetWindow, &webViewPoint); cairo_t *crUnionImage = cairo_create(unionImage); cairo_set_source_surface(crUnionImage, webviewImage, -webViewPoint.x, -webViewPoint.y); cairo_rectangle(crUnionImage, 0, 0, unionImageSize.cx, unionImageSize.cy); cairo_fill(crUnionImage); cairo_surface_destroy(webviewImage); //5. Alpha blend the drag image into the bitmap. if (drawDragImage) { POINT imgPosition = {dest.x - unionPoint.x, dest.y - unionPoint.y}; cairo_set_source_surface(crUnionImage, dragImageCairo, imgPosition.x, imgPosition.y); cairo_rectangle(crUnionImage, imgPosition.x, imgPosition.y, width, height); cairo_fill(crUnionImage); } cairo_destroy(crUnionImage); //6. Draw the blended drag image onto the screen. cairo_set_source_surface(crScreen, unionImage, unionPoint.x, unionPoint.y); if (unionRect.left != unionPoint.x || unionRect.top != unionPoint.y || unionRect.right - unionRect.left != unionImageSize.cx || unionRect.bottom - unionRect.top != unionImageSize.cy) { cairo_rectangle(crScreen, unionRect.left, unionRect.top, unionRect.right - unionRect.left, unionRect.bottom - unionRect.top); cairo_clip(crScreen); } cairo_rectangle(crScreen, unionPoint.x, unionPoint.y, unionImageSize.cx, unionImageSize.cy); cairo_fill(crScreen); cairo_surface_destroy(unionImage); }
already_AddRefed<DrawTarget> PrintTarget::GetReferenceDrawTarget(DrawEventRecorder* aRecorder) { if (!mRefDT) { const IntSize size(1, 1); cairo_surface_t* similar; switch (cairo_surface_get_type(mCairoSurface)) { #ifdef CAIRO_HAS_WIN32_SURFACE case CAIRO_SURFACE_TYPE_WIN32: similar = cairo_win32_surface_create_with_dib( CairoContentToCairoFormat(cairo_surface_get_content(mCairoSurface)), size.width, size.height); break; #endif #ifdef CAIRO_HAS_QUARTZ_SURFACE case CAIRO_SURFACE_TYPE_QUARTZ: similar = cairo_quartz_surface_create_cg_layer( mCairoSurface, cairo_surface_get_content(mCairoSurface), size.width, size.height); break; #endif default: similar = cairo_surface_create_similar( mCairoSurface, cairo_surface_get_content(mCairoSurface), size.width, size.height); break; } if (cairo_surface_status(similar)) { return nullptr; } RefPtr<DrawTarget> dt = Factory::CreateDrawTargetForCairoSurface(similar, size); // The DT addrefs the surface, so we need drop our own reference to it: cairo_surface_destroy(similar); if (!dt || !dt->IsValid()) { return nullptr; } mRefDT = dt.forget(); } if (aRecorder) { if (!mRecordingRefDT) { RefPtr<DrawTarget> dt = CreateRecordingDrawTarget(aRecorder, mRefDT); if (!dt || !dt->IsValid()) { return nullptr; } mRecordingRefDT = dt.forget(); #ifdef DEBUG mRecorder = aRecorder; #endif } #ifdef DEBUG else { MOZ_ASSERT(aRecorder == mRecorder, "Caching mRecordingRefDT assumes the aRecorder is an invariant"); } #endif return do_AddRef(mRecordingRefDT); } return do_AddRef(mRefDT); }