/** * _cairo_beos_bitmap_to_surface: * * Returns an addrefed image surface for a BBitmap. The bitmap need not outlive * the surface. **/ static cairo_image_surface_t* _cairo_beos_bitmap_to_surface (BBitmap* bitmap) { color_space format = bitmap->ColorSpace(); if (format != B_RGB32 && format != B_RGBA32) { BBitmap bmp(bitmap->Bounds(), B_RGB32, true); BView view(bitmap->Bounds(), "Cairo bitmap drawing view", B_FOLLOW_ALL_SIDES, 0); bmp.AddChild(&view); view.LockLooper(); view.DrawBitmap(bitmap, BPoint(0.0, 0.0)); view.Sync(); cairo_image_surface_t* imgsurf = _cairo_beos_bitmap_to_surface(&bmp); view.UnlockLooper(); bmp.RemoveChild(&view); return imgsurf; } cairo_format_t cformat = format == B_RGB32 ? CAIRO_FORMAT_RGB24 : CAIRO_FORMAT_ARGB32; BRect bounds(bitmap->Bounds()); unsigned char* bits = reinterpret_cast<unsigned char*>(bitmap->Bits()); int width = bounds.IntegerWidth() + 1; int height = bounds.IntegerHeight() + 1; unsigned char* premultiplied; if (cformat == CAIRO_FORMAT_ARGB32) { premultiplied = premultiply_rgba(bits, width, height, bitmap->BytesPerRow()); } else { premultiplied = reinterpret_cast<unsigned char*>( _cairo_malloc_ab(bitmap->BytesPerRow(), height)); if (premultiplied) memcpy(premultiplied, bits, bitmap->BytesPerRow() * height); } if (!premultiplied) return NULL; cairo_image_surface_t* surf = reinterpret_cast<cairo_image_surface_t*> (cairo_image_surface_create_for_data(premultiplied, cformat, width, height, bitmap->BytesPerRow())); if (surf->base.status) free(premultiplied); else _cairo_image_surface_assume_ownership_of_data(surf); return surf; }
static cairo_status_t _get_image_surface (cairo_xcb_surface_t *surface, cairo_rectangle_int16_t *interest_rect, cairo_image_surface_t **image_out, cairo_rectangle_int16_t *image_rect) { cairo_image_surface_t *image; XCBGetImageRep *imagerep; int bpp, bytes_per_line; int x1, y1, x2, y2; unsigned char *data; cairo_format_t format; cairo_format_masks_t masks; x1 = 0; y1 = 0; x2 = surface->width; y2 = surface->height; if (interest_rect) { cairo_rectangle_int16_t rect; rect.x = interest_rect->x; rect.y = interest_rect->y; rect.width = interest_rect->width; rect.height = interest_rect->height; if (rect.x > x1) x1 = rect.x; if (rect.y > y1) y1 = rect.y; if (rect.x + rect.width < x2) x2 = rect.x + rect.width; if (rect.y + rect.height < y2) y2 = rect.y + rect.height; if (x1 >= x2 || y1 >= y2) { *image_out = NULL; return CAIRO_STATUS_SUCCESS; } } if (image_rect) { image_rect->x = x1; image_rect->y = y1; image_rect->width = x2 - x1; image_rect->height = y2 - y1; } /* XXX: This should try to use the XShm extension if available */ if (surface->use_pixmap == 0) { XCBGenericError *error; imagerep = XCBGetImageReply(surface->dpy, XCBGetImage(surface->dpy, XCBImageFormatZPixmap, surface->drawable, x1, y1, x2 - x1, y2 - y1, AllPlanes), &error); /* If we get an error, the surface must have been a window, * so retry with the safe code path. */ if (error) surface->use_pixmap = CAIRO_ASSUME_PIXMAP; } else { surface->use_pixmap--; imagerep = NULL; } if (!imagerep) { /* XCBGetImage from a window is dangerous because it can * produce errors if the window is unmapped or partially * outside the screen. We could check for errors and * retry, but to keep things simple, we just create a * temporary pixmap */ XCBDRAWABLE drawable; drawable.pixmap = XCBPIXMAPNew (surface->dpy); XCBCreatePixmap (surface->dpy, surface->depth, drawable.pixmap, surface->drawable, x2 - x1, y2 - y1); _cairo_xcb_surface_ensure_gc (surface); XCBCopyArea (surface->dpy, surface->drawable, drawable, surface->gc, x1, y1, 0, 0, x2 - x1, y2 - y1); imagerep = XCBGetImageReply(surface->dpy, XCBGetImage(surface->dpy, XCBImageFormatZPixmap, drawable, x1, y1, x2 - x1, y2 - y1, AllPlanes), 0); XCBFreePixmap (surface->dpy, drawable.pixmap); } if (!imagerep) return CAIRO_STATUS_NO_MEMORY; bpp = _bits_per_pixel(surface->dpy, imagerep->depth); bytes_per_line = _bytes_per_line(surface->dpy, surface->width, bpp); data = malloc (bytes_per_line * surface->height); if (data == NULL) { free (imagerep); return CAIRO_STATUS_NO_MEMORY; } memcpy (data, XCBGetImageData (imagerep), bytes_per_line * surface->height); free (imagerep); /* * Compute the pixel format masks from either an XCBVISUALTYPE or * a XCBRenderPCTFORMINFO, failing we assume the drawable is an * alpha-only pixmap as it could only have been created that way * through the cairo_xlib_surface_create_for_bitmap function. */ if (surface->visual) { masks.bpp = bpp; masks.alpha_mask = 0; masks.red_mask = surface->visual->red_mask; masks.green_mask = surface->visual->green_mask; masks.blue_mask = surface->visual->blue_mask; } else if (surface->has_format) { masks.bpp = bpp; masks.red_mask = (unsigned long)surface->format.direct.red_mask << surface->format.direct.red_shift; masks.green_mask = (unsigned long)surface->format.direct.green_mask << surface->format.direct.green_shift; masks.blue_mask = (unsigned long)surface->format.direct.blue_mask << surface->format.direct.blue_shift; masks.alpha_mask = (unsigned long)surface->format.direct.alpha_mask << surface->format.direct.alpha_shift; } else { masks.bpp = bpp; masks.red_mask = 0; masks.green_mask = 0; masks.blue_mask = 0; if (surface->depth < 32) masks.alpha_mask = (1 << surface->depth) - 1; else masks.alpha_mask = 0xffffffff; } /* * Prefer to use a standard pixman format instead of the * general masks case. */ if (_CAIRO_MASK_FORMAT (&masks, &format)) { image = (cairo_image_surface_t *) cairo_image_surface_create_for_data (data, format, x2 - x1, y2 - y1, bytes_per_line); if (image->base.status) goto FAIL; } else { /* * XXX This can't work. We must convert the data to one of the * supported pixman formats. Pixman needs another function * which takes data in an arbitrary format and converts it * to something supported by that library. */ image = (cairo_image_surface_t *) _cairo_image_surface_create_with_masks (data, &masks, x2 - x1, y2 - y1, bytes_per_line); if (image->base.status) goto FAIL; } /* Let the surface take ownership of the data */ _cairo_image_surface_assume_ownership_of_data (image); *image_out = image; return CAIRO_STATUS_SUCCESS; FAIL: free (data); return CAIRO_STATUS_NO_MEMORY; }