[cairo-commit] src/cairo-beos-surface.cpp

Christian Biesinger biesi at kemper.freedesktop.org
Sun Mar 26 16:58:48 PST 2006


 src/cairo-beos-surface.cpp |  204 +++++++++++++++++++++++++++++++++++----------
 1 files changed, 159 insertions(+), 45 deletions(-)

New commits:
diff-tree 8fbd0d448dbdf8f556315366b64abe2468588ea6 (from 3259efed7690670754d7c1e76176ff26464111c3)
Author: Christian Biesinger <cbiesinger at web.de>
Date:   Mon Mar 27 02:31:51 2006 +0200

    Implement create_similar for BeOS

diff --git a/src/cairo-beos-surface.cpp b/src/cairo-beos-surface.cpp
index 6347ba7..dfb0217 100644
--- a/src/cairo-beos-surface.cpp
+++ b/src/cairo-beos-surface.cpp
@@ -70,6 +70,9 @@ struct cairo_beos_surface_t {
     BBitmap* bitmap;
 
 
+    // If true, surface and view should be deleted when this surface is
+    // destroyed
+    bool owns_bitmap_view;
 };
 
 class AutoLockView {
@@ -92,6 +95,11 @@ class AutoLockView {
 	bool   mOK;
 };
 
+static cairo_surface_t *
+_cairo_beos_surface_create_internal (BView*   view,
+				     BBitmap* bmp,
+				     bool     owns_bitmap_view = false);
+
 static BRect
 _cairo_rect_to_brect (const cairo_rectangle_t* rect)
 {
@@ -414,10 +422,76 @@ _cairo_op_to_be_op (cairo_operator_t cai
     };
 }
 
+static cairo_surface_t *
+_cairo_beos_surface_create_similar (void            *abstract_surface,
+				    cairo_content_t  content,
+				    int              width,
+				    int              height)
+{
+    fprintf(stderr, "Creating similar\n");
+
+    cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
+							abstract_surface);
+
+    if (width <= 0)
+	width = 1;
+    if (height <= 0)
+	height = 1;
+
+    BRect rect(0.0, 0.0, width - 1, height - 1);
+    BBitmap* bmp;
+    switch (content) {
+	case CAIRO_CONTENT_ALPHA:
+	    // Can't support this natively
+	    return _cairo_image_surface_create_with_content(content, width,
+							    height);
+	case CAIRO_CONTENT_COLOR_ALPHA:
+	    bmp = new BBitmap(rect, B_RGBA32, true);
+	    break;
+	case CAIRO_CONTENT_COLOR:
+	    // Match the color depth
+	    if (surface->bitmap) {
+		color_space space = surface->bitmap->ColorSpace();
+		// No alpha was requested -> make sure not to return
+		// a surface with alpha
+		if (space == B_RGBA32)
+		    space = B_RGB32;
+		if (space == B_RGBA15)
+		    space = B_RGB15;
+		bmp = new BBitmap(rect, space, true);
+	    } else {
+		BScreen scr(surface->view->Window());
+		color_space space = B_RGB32;
+		if (scr.IsValid())
+		    space = scr.ColorSpace();
+		bmp = new BBitmap(rect, space, true);
+	    }
+	    break;
+	default:
+	    assert(0);
+	    return NULL;
+	    
+    };
+    BView* view = new BView(rect, "Cairo bitmap view", B_FOLLOW_ALL_SIDES, 0);
+    bmp->AddChild(view);
+    return _cairo_beos_surface_create_internal(view, bmp, true);
+}
+
 static cairo_status_t
 _cairo_beos_surface_finish (void *abstract_surface)
 {
-    // Nothing to do
+    cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
+							abstract_surface);
+    if (surface->owns_bitmap_view) {
+	if (surface->bitmap)
+	    surface->bitmap->RemoveChild(surface->view);
+
+	delete surface->view;
+	delete surface->bitmap;
+
+	surface->view = NULL;
+	surface->bitmap = NULL;
+    }
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -549,13 +623,12 @@ _cairo_beos_surface_release_dest_image (
 
     cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
 							abstract_surface);
+
     AutoLockView locker(surface->view);
     if (!locker)
 	return;
 
-
     BBitmap* bitmap_to_draw = _cairo_image_surface_to_bitmap(image);
-
     surface->view->PushState();
 
 	surface->view->SetDrawingMode(B_OP_COPY);
@@ -617,46 +690,78 @@ _cairo_beos_surface_composite (cairo_ope
 
     cairo_surface_t* src_surface = reinterpret_cast<cairo_surface_pattern_t*>(src)->
 					surface;
-    if (_cairo_surface_is_image(src_surface)) {
-    	fprintf(stderr, "Composite\n");
 
-	// Draw it on screen.
+    // Get a bitmap
+    BBitmap* bmp = NULL;
+    bool free_bmp = false;
+    if (_cairo_surface_is_image(src_surface)) {
 	cairo_image_surface_t* img_surface =
 	    reinterpret_cast<cairo_image_surface_t*>(src_surface);
 
-	BBitmap* bmp = _cairo_image_surface_to_bitmap(img_surface);
-	surface->view->PushState();
+	bmp = _cairo_image_surface_to_bitmap(img_surface);
+	free_bmp = true;
+    } else if (src_surface->backend == surface->base.backend) {
+	cairo_beos_surface_t *beos_surface =
+	    reinterpret_cast<cairo_beos_surface_t*>(src_surface);
+	if (beos_surface->bitmap) {
+	    AutoLockView locker(beos_surface->view);
+	    if (locker)
+		beos_surface->view->Sync();
+	    bmp = beos_surface->bitmap;
+	} else {
+	    _cairo_beos_view_to_bitmap(surface->view, &bmp);
+	    free_bmp = true;
+	}
+    }
+
+    if (!bmp)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
 
-	    // If our image rect is only a subrect of the desired size, and we
-	    // aren't using B_OP_ALPHA, then we need to fill the rect first.
-	    if (mode == B_OP_COPY && !bmp->Bounds().Contains(srcRect)) {
-		rgb_color black = { 0, 0, 0, 0 };
-
-		surface->view->SetDrawingMode(mode);
-		surface->view->SetHighColor(black);
-		surface->view->FillRect(dstRect);
-	    }
+    // So, BeOS seems to screw up painting an opaque bitmap onto a
+    // translucent one (it makes them partly transparent). Just return
+    // unsupported.
+    if (bmp->ColorSpace() == B_RGB32 && surface->bitmap &&
+	surface->bitmap->ColorSpace() == B_RGBA32 &&
+	(mode == B_OP_COPY || mode == B_OP_ALPHA))
+    {
+	if (free_bmp)
+	    delete bmp;
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
 
-	    if (mode == B_OP_ALPHA && img_surface->format != CAIRO_FORMAT_ARGB32) {
-		mode = B_OP_COPY;
+    fprintf(stderr, "Composite\n");
+
+    // Draw it on screen.
+    surface->view->PushState();
+
+	// If our image rect is only a subrect of the desired size, and we
+	// aren't using B_OP_ALPHA, then we need to fill the rect first.
+	if (mode == B_OP_COPY && !bmp->Bounds().Contains(srcRect)) {
+	    rgb_color black = { 0, 0, 0, 0 };
 
-	    }
 	    surface->view->SetDrawingMode(mode);
+	    surface->view->SetHighColor(black);
+	    surface->view->FillRect(dstRect);
+	}
 
-	    if (surface->bitmap && surface->bitmap->ColorSpace() == B_RGBA32)
-		surface->view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_COMPOSITE);
-	    else
-		surface->view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
+	if (mode == B_OP_ALPHA && bmp->ColorSpace() == B_RGB32) {
+	    mode = B_OP_COPY;
+	}
+	surface->view->SetDrawingMode(mode);
 
-	    surface->view->DrawBitmap(bmp, srcRect, dstRect);
+	if (surface->bitmap && surface->bitmap->ColorSpace() == B_RGBA32)
+	    surface->view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_COMPOSITE);
+	else
+	    surface->view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
 
-	surface->view->PopState();
-	delete bmp;
+	surface->view->DrawBitmap(bmp, srcRect, dstRect);
 
-	return CAIRO_INT_STATUS_SUCCESS;
-    }
+    surface->view->PopState();
 
-    return CAIRO_INT_STATUS_UNSUPPORTED;
+    if (free_bmp)
+	delete bmp;
+
+    return CAIRO_INT_STATUS_SUCCESS;
 }
 
 
@@ -778,7 +883,7 @@ _cairo_beos_surface_get_extents (void   
 
 static const struct _cairo_surface_backend cairo_beos_surface_backend = {
     CAIRO_SURFACE_TYPE_BEOS,
-    NULL, /* create_similar */
+    _cairo_beos_surface_create_similar,
     _cairo_beos_surface_finish,
     _cairo_beos_surface_acquire_source_image,
     _cairo_beos_surface_release_source_image,
@@ -807,6 +912,28 @@ static const struct _cairo_surface_backe
     NULL  /* show_glyphs */
 };
 
+static cairo_surface_t *
+_cairo_beos_surface_create_internal (BView*   view,
+				     BBitmap* bmp,
+				     bool     owns_bitmap_view)
+{
+    // Must use malloc, because cairo code will use free() on the surface
+    cairo_beos_surface_t *surface = static_cast<cairo_beos_surface_t*>(
+					malloc(sizeof(cairo_beos_surface_t)));
+    if (surface == NULL) {
+	_cairo_error (CAIRO_STATUS_NO_MEMORY);
+        return const_cast<cairo_surface_t*>(&_cairo_surface_nil);
+    }
+
+    _cairo_surface_init(&surface->base, &cairo_beos_surface_backend);
+
+    surface->view = view;
+    surface->bitmap = bmp;
+    surface->owns_bitmap_view = owns_bitmap_view;
+
+    return (cairo_surface_t *) surface;
+}
+
 /**
  * cairo_beos_surface_create:
  * @view: The view to draw on
@@ -843,20 +970,7 @@ cairo_surface_t *
 cairo_beos_surface_create_for_bitmap (BView*   view,
 				      BBitmap* bmp)
 {
-    // Must use malloc, because cairo code will use free() on the surface
-    cairo_beos_surface_t *surface = static_cast<cairo_beos_surface_t*>(
-					malloc(sizeof(cairo_beos_surface_t)));
-    if (surface == NULL) {
-	_cairo_error (CAIRO_STATUS_NO_MEMORY);
-        return const_cast<cairo_surface_t*>(&_cairo_surface_nil);
-    }
-
-    _cairo_surface_init(&surface->base, &cairo_beos_surface_backend);
-
-    surface->view = view;
-    surface->bitmap = bmp;
-
-    return (cairo_surface_t *) surface;
+    return _cairo_beos_surface_create_internal(view, bmp);
 }
 
 // ---------------------------------------------------------------------------


More information about the cairo-commit mailing list