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());
}
Beispiel #3
0
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));
}
Beispiel #4
0
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;
    }
}
Beispiel #5
0
// 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(&currentDragImage, 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;
    }
}
Beispiel #7
0
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;
}
Beispiel #12
0
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);
}
Beispiel #13
0
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);
}