Add stubs for Direct3D9 backend.
[cairo/gpu.git] / src / cairo-beos-surface.cpp
blobe527272e63724fd42fe6e3f693c7874b1af7091e
1 /* vim:set ts=8 sw=4 noet cin: */
2 /* cairo - a vector graphics library with display and print output
4 * Copyright © 2005 Christian Biesinger <cbiesinger@web.de>
6 * This library is free software; you can redistribute it and/or
7 * modify it either under the terms of the GNU Lesser General Public
8 * License version 2.1 as published by the Free Software Foundation
9 * (the "LGPL") or, at your option, under the terms of the Mozilla
10 * Public License Version 1.1 (the "MPL"). If you do not alter this
11 * notice, a recipient may use your version of this file under either
12 * the MPL or the LGPL.
14 * You should have received a copy of the LGPL along with this library
15 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 * You should have received a copy of the MPL along with this library
18 * in the file COPYING-MPL-1.1
20 * The contents of this file are subject to the Mozilla Public License
21 * Version 1.1 (the "License"); you may not use this file except in
22 * compliance with the License. You may obtain a copy of the License at
23 * http://www.mozilla.org/MPL/
25 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
26 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
27 * the specific language governing rights and limitations.
29 * The Original Code is the cairo graphics library.
31 * The Initial Developer of the Original Code is Christian Biesinger
32 * <cbiesinger@web.de>
34 * Contributor(s):
37 // This is a C++ file in order to use the C++ BeOS API
39 #include "cairoint.h"
41 #include "cairo-beos.h"
43 #include <new>
45 #include <Bitmap.h>
46 #include <Region.h>
47 #if 0
48 #include <DirectWindow.h>
49 #endif
50 #include <Screen.h>
51 #include <Window.h>
52 #include <Locker.h>
54 #define CAIRO_INT_STATUS_SUCCESS (cairo_int_status_t)(CAIRO_STATUS_SUCCESS)
56 struct cairo_beos_surface_t {
57 cairo_surface_t base;
59 BView* view;
62 * A view is either attached to a bitmap, a window, or unattached.
63 * If it is attached to a window, we can copy data out of it using BScreen.
64 * If it is attached to a bitmap, we can read the bitmap data.
65 * If it is not attached, it doesn't draw anything, we need not bother.
67 * Since there doesn't seem to be a way to get the bitmap from a view if it
68 * is attached to one, we have to use a special surface creation function.
71 BBitmap* bitmap;
74 // If true, surface and view should be deleted when this surface is
75 // destroyed
76 bool owns_bitmap_view;
79 class AutoLockView {
80 public:
81 AutoLockView(BView* view) : mView(view) {
82 mOK = mView->LockLooper();
85 ~AutoLockView() {
86 if (mOK)
87 mView->UnlockLooper();
90 operator bool() {
91 return mOK;
94 private:
95 BView* mView;
96 bool mOK;
99 static cairo_surface_t *
100 _cairo_beos_surface_create_internal (BView* view,
101 BBitmap* bmp,
102 bool owns_bitmap_view = false);
104 static BRect
105 _cairo_rect_to_brect (const cairo_rectangle_int16_t* rect)
107 // A BRect is one pixel wider than you'd think
108 return BRect(rect->x, rect->y, rect->x + rect->width - 1,
109 rect->y + rect->height - 1);
112 static cairo_rectangle_int16_t
113 _brect_to_cairo_rect (const BRect& rect)
115 cairo_rectangle_int16_t retval;
116 retval.x = int(rect.left + 0.5);
117 retval.y = int(rect.top + 0.5);
118 retval.width = rect.IntegerWidth() + 1;
119 retval.height = rect.IntegerHeight() + 1;
120 return retval;
123 static rgb_color
124 _cairo_color_to_be_color (const cairo_color_t* color)
126 // This factor ensures a uniform distribution of numbers
127 const float factor = 256 - 1e-5;
128 // Using doubles to have non-premultiplied colors
129 rgb_color be_color = { uint8(color->red * factor),
130 uint8(color->green * factor),
131 uint8(color->blue * factor),
132 uint8(color->alpha * factor) };
134 return be_color;
137 enum ViewCopyStatus {
139 NOT_VISIBLE, // The view or the interest rect is not visible on screen
140 ERROR // The view was visible, but the rect could not be copied. Probably OOM
144 * _cairo_beos_view_to_bitmap:
145 * @bitmap: [out] The resulting bitmap.
146 * @rect: [out] The rectangle that was copied, in the view's coordinate system
147 * @interestRect: If non-null, only this part of the view will be copied (view's coord system).
149 * Gets the contents of the view as a BBitmap*. Caller must delete the bitmap.
151 static ViewCopyStatus
152 _cairo_beos_view_to_bitmap (BView* view,
153 BBitmap** bitmap,
154 BRect* rect = NULL,
155 const BRect* interestRect = NULL)
157 *bitmap = NULL;
159 BWindow* wnd = view->Window();
160 // If we have no window, can't do anything
161 if (!wnd)
162 return NOT_VISIBLE;
164 view->Sync();
165 wnd->Sync();
167 #if 0
168 // Is it a direct window?
169 BDirectWindow* directWnd = dynamic_cast<BDirectWindow*>(wnd);
170 if (directWnd) {
171 // WRITEME
173 #endif
175 // Is it visible? If so, we can copy the content off the screen
176 if (wnd->IsHidden())
177 return NOT_VISIBLE;
179 BRect rectToCopy(view->Bounds());
180 if (interestRect)
181 rectToCopy = rectToCopy & *interestRect;
183 if (!rectToCopy.IsValid())
184 return NOT_VISIBLE;
186 BScreen screen(wnd);
187 BRect screenRect(view->ConvertToScreen(rectToCopy));
188 screenRect = screenRect & screen.Frame();
190 if (!screen.IsValid())
191 return NOT_VISIBLE;
193 if (rect)
194 *rect = view->ConvertFromScreen(screenRect);
196 if (screen.GetBitmap(bitmap, false, &screenRect) == B_OK)
197 return OK;
199 return ERROR;
202 inline unsigned char
203 unpremultiply (unsigned char color,
204 unsigned char alpha)
206 if (alpha == 0)
207 return 0;
208 // plus alpha/2 to round instead of truncate
209 return (color * 255 + alpha / 2) / alpha;
212 inline unsigned char
213 premultiply (unsigned char color,
214 unsigned char alpha)
216 // + 127 to round, instead of truncate
217 return (color * alpha + 127) / 255;
221 * unpremultiply_rgba:
223 * Takes an input in ABGR premultiplied image data and unmultiplies it.
224 * The result is stored in retdata.
226 static void
227 unpremultiply_rgba (unsigned char* data,
228 int width,
229 int height,
230 int stride,
231 unsigned char* retdata)
233 unsigned char* end = data + stride * height;
234 for (unsigned char* in = data, *out = retdata;
235 in < end;
236 in += stride, out += stride)
238 for (int i = 0; i < width; ++i) {
239 // XXX for a big-endian platform this'd have to change
240 int idx = 4 * i;
241 unsigned char alpha = in[idx + 3];
242 out[idx + 0] = unpremultiply(in[idx + 0], alpha); // B
243 out[idx + 1] = unpremultiply(in[idx + 1], alpha); // G
244 out[idx + 2] = unpremultiply(in[idx + 2], alpha); // R
245 out[idx + 3] = in[idx + 3]; // Alpha
251 * premultiply_rgba:
253 * Takes an input in ABGR non-premultiplied image data and premultiplies it.
254 * The returned data must be freed with free().
256 static unsigned char*
257 premultiply_rgba (unsigned char* data,
258 int width,
259 int height,
260 int stride)
262 unsigned char* retdata = reinterpret_cast<unsigned char*>(_cairo_malloc_ab(height, stride));
263 if (!retdata)
264 return NULL;
266 unsigned char* end = data + stride * height;
267 for (unsigned char* in = data, *out = retdata;
268 in < end;
269 in += stride, out += stride)
271 for (int i = 0; i < width; ++i) {
272 // XXX for a big-endian platform this'd have to change
273 int idx = 4 * i;
274 unsigned char alpha = in[idx + 3];
275 out[idx + 0] = premultiply(in[idx + 0], alpha); // B
276 out[idx + 1] = premultiply(in[idx + 1], alpha); // G
277 out[idx + 2] = premultiply(in[idx + 2], alpha); // R
278 out[idx + 3] = in[idx + 3]; // Alpha
281 return retdata;
285 * _cairo_beos_bitmap_to_surface:
287 * Returns an addrefed image surface for a BBitmap. The bitmap need not outlive
288 * the surface.
290 static cairo_image_surface_t*
291 _cairo_beos_bitmap_to_surface (BBitmap* bitmap)
293 color_space format = bitmap->ColorSpace();
294 if (format != B_RGB32 && format != B_RGBA32) {
295 BBitmap bmp(bitmap->Bounds(), B_RGB32, true);
296 BView view(bitmap->Bounds(), "Cairo bitmap drawing view",
297 B_FOLLOW_ALL_SIDES, 0);
298 bmp.AddChild(&view);
300 view.LockLooper();
302 view.DrawBitmap(bitmap, BPoint(0.0, 0.0));
303 view.Sync();
305 cairo_image_surface_t* imgsurf = _cairo_beos_bitmap_to_surface(&bmp);
307 view.UnlockLooper();
308 bmp.RemoveChild(&view);
309 return imgsurf;
312 cairo_format_t cformat = format == B_RGB32 ? CAIRO_FORMAT_RGB24
313 : CAIRO_FORMAT_ARGB32;
315 BRect bounds(bitmap->Bounds());
316 unsigned char* bits = reinterpret_cast<unsigned char*>(bitmap->Bits());
317 int width = bounds.IntegerWidth() + 1;
318 int height = bounds.IntegerHeight() + 1;
319 unsigned char* premultiplied;
320 if (cformat == CAIRO_FORMAT_ARGB32) {
321 premultiplied = premultiply_rgba(bits, width, height,
322 bitmap->BytesPerRow());
323 } else {
324 premultiplied = reinterpret_cast<unsigned char*>(
325 _cairo_malloc_ab(bitmap->BytesPerRow(), height));
326 if (premultiplied)
327 memcpy(premultiplied, bits, bitmap->BytesPerRow() * height);
329 if (!premultiplied)
330 return NULL;
332 cairo_image_surface_t* surf = reinterpret_cast<cairo_image_surface_t*>
333 (cairo_image_surface_create_for_data(premultiplied,
334 cformat,
335 width,
336 height,
337 bitmap->BytesPerRow()));
338 if (surf->base.status)
339 free(premultiplied);
340 else
341 _cairo_image_surface_assume_ownership_of_data(surf);
342 return surf;
346 * _cairo_image_surface_to_bitmap:
348 * Converts an image surface to a BBitmap. The return value must be freed with
349 * delete.
351 static BBitmap*
352 _cairo_image_surface_to_bitmap (cairo_image_surface_t* surface)
354 BRect size(0.0, 0.0, surface->width - 1, surface->height - 1);
355 switch (surface->format) {
356 case CAIRO_FORMAT_ARGB32: {
357 BBitmap* data = new BBitmap(size, B_RGBA32);
358 unpremultiply_rgba(surface->data,
359 surface->width,
360 surface->height,
361 surface->stride,
362 reinterpret_cast<unsigned char*>(data->Bits()));
363 return data;
365 case CAIRO_FORMAT_RGB24: {
366 BBitmap* data = new BBitmap(size, B_RGB32);
367 memcpy(data->Bits(), surface->data, surface->height * surface->stride);
368 return data;
370 default:
371 assert(0);
372 return NULL;
377 * _cairo_op_to_be_op:
379 * Converts a cairo drawing operator to a beos drawing_mode. Returns true if
380 * the operator could be converted, false otherwise.
382 static bool
383 _cairo_op_to_be_op (cairo_operator_t cairo_op,
384 drawing_mode* beos_op)
386 switch (cairo_op) {
388 case CAIRO_OPERATOR_SOURCE:
389 *beos_op = B_OP_COPY;
390 return true;
391 case CAIRO_OPERATOR_OVER:
392 *beos_op = B_OP_ALPHA;
393 return true;
395 case CAIRO_OPERATOR_ADD:
396 // Does not actually work
397 #if 1
398 return false;
399 #else
400 *beos_op = B_OP_ADD;
401 return true;
402 #endif
404 case CAIRO_OPERATOR_CLEAR:
405 // Does not map to B_OP_ERASE - it replaces the dest with the low
406 // color, instead of transparency; could be done by setting low
407 // color appropriately.
409 case CAIRO_OPERATOR_IN:
410 case CAIRO_OPERATOR_OUT:
411 case CAIRO_OPERATOR_ATOP:
413 case CAIRO_OPERATOR_DEST:
414 case CAIRO_OPERATOR_DEST_OVER:
415 case CAIRO_OPERATOR_DEST_IN:
416 case CAIRO_OPERATOR_DEST_OUT:
417 case CAIRO_OPERATOR_DEST_ATOP:
419 case CAIRO_OPERATOR_XOR:
420 case CAIRO_OPERATOR_SATURATE:
422 default:
423 return false;
427 static cairo_surface_t *
428 _cairo_beos_surface_create_similar (void *abstract_surface,
429 cairo_content_t content,
430 int width,
431 int height)
433 fprintf(stderr, "Creating similar\n");
435 cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
436 abstract_surface);
438 if (width <= 0)
439 width = 1;
440 if (height <= 0)
441 height = 1;
443 BRect rect(0.0, 0.0, width - 1, height - 1);
444 BBitmap* bmp;
445 switch (content) {
446 case CAIRO_CONTENT_ALPHA:
447 // Can't support this natively
448 return _cairo_image_surface_create_with_content(content, width,
449 height);
450 case CAIRO_CONTENT_COLOR_ALPHA:
451 bmp = new BBitmap(rect, B_RGBA32, true);
452 break;
453 case CAIRO_CONTENT_COLOR:
454 // Match the color depth
455 if (surface->bitmap) {
456 color_space space = surface->bitmap->ColorSpace();
457 // No alpha was requested -> make sure not to return
458 // a surface with alpha
459 if (space == B_RGBA32)
460 space = B_RGB32;
461 if (space == B_RGBA15)
462 space = B_RGB15;
463 bmp = new BBitmap(rect, space, true);
464 } else {
465 BScreen scr(surface->view->Window());
466 color_space space = B_RGB32;
467 if (scr.IsValid())
468 space = scr.ColorSpace();
469 bmp = new BBitmap(rect, space, true);
471 break;
472 default:
473 assert(0);
474 return NULL;
477 BView* view = new BView(rect, "Cairo bitmap view", B_FOLLOW_ALL_SIDES, 0);
478 bmp->AddChild(view);
479 return _cairo_beos_surface_create_internal(view, bmp, true);
482 static cairo_status_t
483 _cairo_beos_surface_finish (void *abstract_surface)
485 cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
486 abstract_surface);
487 if (surface->owns_bitmap_view) {
488 if (surface->bitmap)
489 surface->bitmap->RemoveChild(surface->view);
491 delete surface->view;
492 delete surface->bitmap;
494 surface->view = NULL;
495 surface->bitmap = NULL;
498 return CAIRO_STATUS_SUCCESS;
501 static cairo_status_t
502 _cairo_beos_surface_acquire_source_image (void *abstract_surface,
503 cairo_image_surface_t **image_out,
504 void **image_extra)
506 fprintf(stderr, "Getting source image\n");
507 cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
508 abstract_surface);
509 AutoLockView locker(surface->view);
510 if (!locker)
511 return CAIRO_STATUS_NO_MEMORY; /// XXX not exactly right, but what can we do?
514 surface->view->Sync();
516 if (surface->bitmap) {
517 *image_out = _cairo_beos_bitmap_to_surface(surface->bitmap);
518 if (!*image_out)
519 return CAIRO_STATUS_NO_MEMORY;
521 *image_extra = NULL;
522 return CAIRO_STATUS_SUCCESS;
525 BBitmap* bmp;
526 if (_cairo_beos_view_to_bitmap(surface->view, &bmp) != OK)
527 return CAIRO_STATUS_NO_MEMORY; /// XXX incorrect if the error was NOT_VISIBLE
529 *image_out = _cairo_beos_bitmap_to_surface(bmp);
530 if (!*image_out) {
531 delete bmp;
532 return CAIRO_STATUS_NO_MEMORY;
534 *image_extra = bmp;
536 return CAIRO_STATUS_SUCCESS;
539 static void
540 _cairo_beos_surface_release_source_image (void *abstract_surface,
541 cairo_image_surface_t *image,
542 void *image_extra)
544 cairo_surface_destroy (&image->base);
546 BBitmap* bmp = static_cast<BBitmap*>(image_extra);
547 delete bmp;
552 static cairo_status_t
553 _cairo_beos_surface_acquire_dest_image (void *abstract_surface,
554 cairo_rectangle_int16_t *interest_rect,
555 cairo_image_surface_t **image_out,
556 cairo_rectangle_int16_t *image_rect,
557 void **image_extra)
559 cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
560 abstract_surface);
562 AutoLockView locker(surface->view);
563 if (!locker) {
564 *image_out = NULL;
565 *image_extra = NULL;
566 return CAIRO_STATUS_SUCCESS;
569 if (surface->bitmap) {
570 surface->view->Sync();
571 *image_out = _cairo_beos_bitmap_to_surface(surface->bitmap);
572 if (!*image_out)
573 return CAIRO_STATUS_NO_MEMORY;
575 image_rect->x = 0;
576 image_rect->y = 0;
577 image_rect->width = (*image_out)->width;
578 image_rect->height = (*image_out)->height;
580 *image_extra = NULL;
581 return CAIRO_STATUS_SUCCESS;
584 BRect b_interest_rect(_cairo_rect_to_brect(interest_rect));
586 BRect rect;
587 BBitmap* bitmap;
588 ViewCopyStatus status = _cairo_beos_view_to_bitmap(surface->view, &bitmap,
589 &rect, &b_interest_rect);
590 if (status == NOT_VISIBLE) {
591 *image_out = NULL;
592 *image_extra = NULL;
593 return CAIRO_STATUS_SUCCESS;
595 if (status == ERROR)
596 return CAIRO_STATUS_NO_MEMORY;
598 *image_rect = _brect_to_cairo_rect(rect);
600 #if 0
601 fprintf(stderr, "Requested: (cairo rects) (%ix%i) dim (%u, %u) returning (%ix%i) dim (%u, %u)\n",
602 interest_rect->x, interest_rect->y, interest_rect->width, interest_rect->height,
603 image_rect->x, image_rect->y, image_rect->width, image_rect->height);
604 #endif
606 *image_out = _cairo_beos_bitmap_to_surface(bitmap);
607 delete bitmap;
608 if (!*image_out)
609 return CAIRO_STATUS_NO_MEMORY;
611 *image_extra = NULL;
613 return CAIRO_STATUS_SUCCESS;
617 static void
618 _cairo_beos_surface_release_dest_image (void *abstract_surface,
619 cairo_rectangle_int16_t *intersect_rect,
620 cairo_image_surface_t *image,
621 cairo_rectangle_int16_t *image_rect,
622 void *image_extra)
624 fprintf(stderr, "Fallback drawing\n");
626 cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
627 abstract_surface);
629 AutoLockView locker(surface->view);
630 if (!locker)
631 return;
633 BBitmap* bitmap_to_draw = _cairo_image_surface_to_bitmap(image);
634 surface->view->PushState();
636 surface->view->SetDrawingMode(B_OP_COPY);
637 BRect rect(_cairo_rect_to_brect(image_rect));
639 surface->view->DrawBitmap(bitmap_to_draw, rect);
641 surface->view->PopState();
643 delete bitmap_to_draw;
644 cairo_surface_destroy(&image->base);
647 static cairo_int_status_t
648 _cairo_beos_surface_composite (cairo_operator_t op,
649 cairo_pattern_t *src,
650 cairo_pattern_t *mask,
651 void *dst,
652 int src_x,
653 int src_y,
654 int mask_x,
655 int mask_y,
656 int dst_x,
657 int dst_y,
658 unsigned int width,
659 unsigned int height)
661 cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
662 dst);
663 AutoLockView locker(surface->view);
664 if (!locker)
665 return CAIRO_INT_STATUS_SUCCESS;
667 drawing_mode mode;
668 if (!_cairo_op_to_be_op(op, &mode))
669 return CAIRO_INT_STATUS_UNSUPPORTED;
671 // XXX Masks are not yet supported
672 if (mask)
673 return CAIRO_INT_STATUS_UNSUPPORTED;
675 // XXX should eventually support the others
676 if (src->type != CAIRO_PATTERN_TYPE_SURFACE ||
677 src->extend != CAIRO_EXTEND_NONE)
679 return CAIRO_INT_STATUS_UNSUPPORTED;
682 // Can we maybe support other matrices as well? (scale? if the filter is right)
683 int itx, ity;
684 if (!_cairo_matrix_is_integer_translation(&src->matrix, &itx, &ity))
685 return CAIRO_INT_STATUS_UNSUPPORTED;
687 BRect srcRect(src_x + itx,
688 src_y + ity,
689 src_x + itx + width - 1,
690 src_y + ity + height - 1);
691 BRect dstRect(dst_x, dst_y, dst_x + width - 1, dst_y + height - 1);
693 cairo_surface_t* src_surface = reinterpret_cast<cairo_surface_pattern_t*>(src)->
694 surface;
696 // Get a bitmap
697 BBitmap* bmp = NULL;
698 bool free_bmp = false;
699 if (_cairo_surface_is_image(src_surface)) {
700 cairo_image_surface_t* img_surface =
701 reinterpret_cast<cairo_image_surface_t*>(src_surface);
703 bmp = _cairo_image_surface_to_bitmap(img_surface);
704 free_bmp = true;
705 } else if (src_surface->backend == surface->base.backend) {
706 cairo_beos_surface_t *beos_surface =
707 reinterpret_cast<cairo_beos_surface_t*>(src_surface);
708 if (beos_surface->bitmap) {
709 AutoLockView locker(beos_surface->view);
710 if (locker)
711 beos_surface->view->Sync();
712 bmp = beos_surface->bitmap;
713 } else {
714 _cairo_beos_view_to_bitmap(surface->view, &bmp);
715 free_bmp = true;
719 if (!bmp)
720 return CAIRO_INT_STATUS_UNSUPPORTED;
722 // So, BeOS seems to screw up painting an opaque bitmap onto a
723 // translucent one (it makes them partly transparent). Just return
724 // unsupported.
725 if (bmp->ColorSpace() == B_RGB32 && surface->bitmap &&
726 surface->bitmap->ColorSpace() == B_RGBA32 &&
727 (mode == B_OP_COPY || mode == B_OP_ALPHA))
729 if (free_bmp)
730 delete bmp;
731 return CAIRO_INT_STATUS_UNSUPPORTED;
734 fprintf(stderr, "Composite\n");
736 // Draw it on screen.
737 surface->view->PushState();
739 // If our image rect is only a subrect of the desired size, and we
740 // aren't using B_OP_ALPHA, then we need to fill the rect first.
741 if (mode == B_OP_COPY && !bmp->Bounds().Contains(srcRect)) {
742 rgb_color black = { 0, 0, 0, 0 };
744 surface->view->SetDrawingMode(mode);
745 surface->view->SetHighColor(black);
746 surface->view->FillRect(dstRect);
749 if (mode == B_OP_ALPHA && bmp->ColorSpace() == B_RGB32) {
750 mode = B_OP_COPY;
752 surface->view->SetDrawingMode(mode);
754 if (surface->bitmap && surface->bitmap->ColorSpace() == B_RGBA32)
755 surface->view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_COMPOSITE);
756 else
757 surface->view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
759 surface->view->DrawBitmap(bmp, srcRect, dstRect);
761 surface->view->PopState();
763 if (free_bmp)
764 delete bmp;
766 return CAIRO_INT_STATUS_SUCCESS;
770 static void
771 _cairo_beos_surface_fill_rectangle (cairo_beos_surface_t *surface,
772 cairo_rectangle_int16_t *rect)
774 BRect brect(_cairo_rect_to_brect(rect));
775 surface->view->FillRect(brect);
778 static cairo_int_status_t
779 _cairo_beos_surface_fill_rectangles (void *abstract_surface,
780 cairo_operator_t op,
781 const cairo_color_t *color,
782 cairo_rectangle_int16_t *rects,
783 int num_rects)
785 fprintf(stderr, "Drawing %i rectangles\n", num_rects);
786 cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
787 abstract_surface);
789 if (num_rects <= 0)
790 return CAIRO_INT_STATUS_SUCCESS;
792 AutoLockView locker(surface->view);
793 if (!locker)
794 return CAIRO_INT_STATUS_SUCCESS;
796 drawing_mode mode;
797 if (!_cairo_op_to_be_op(op, &mode))
798 return CAIRO_INT_STATUS_UNSUPPORTED;
800 rgb_color be_color = _cairo_color_to_be_color(color);
802 if (mode == B_OP_ALPHA && be_color.alpha == 0xFF)
803 mode = B_OP_COPY;
805 // For CAIRO_OPERATOR_SOURCE, cairo expects us to use the premultiplied
806 // color info. This is only relevant when drawing into an rgb24 buffer
807 // (as for others, we can convert when asked for the image)
808 if (mode == B_OP_COPY && be_color.alpha != 0xFF &&
809 (!surface->bitmap || surface->bitmap->ColorSpace() != B_RGBA32))
811 be_color.red = premultiply(be_color.red, be_color.alpha);
812 be_color.green = premultiply(be_color.green, be_color.alpha);
813 be_color.blue = premultiply(be_color.blue, be_color.alpha);
816 surface->view->PushState();
818 surface->view->SetDrawingMode(mode);
819 surface->view->SetHighColor(be_color);
820 if (surface->bitmap && surface->bitmap->ColorSpace() == B_RGBA32)
821 surface->view->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE);
822 else
823 surface->view->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY);
825 for (int i = 0; i < num_rects; ++i) {
826 _cairo_beos_surface_fill_rectangle(surface, &rects[i]);
829 surface->view->PopState();
831 return CAIRO_INT_STATUS_SUCCESS;
836 static cairo_int_status_t
837 _cairo_beos_surface_set_clip_region (void *abstract_surface,
838 pixman_region16_t *region)
840 fprintf(stderr, "Setting clip region\n");
841 cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
842 abstract_surface);
843 AutoLockView locker(surface->view);
844 if (!locker)
845 return CAIRO_INT_STATUS_SUCCESS;
847 if (region == NULL) {
848 // No clipping
849 surface->view->ConstrainClippingRegion(NULL);
850 return CAIRO_INT_STATUS_SUCCESS;
853 int count = pixman_region_num_rects(region);
854 pixman_box16_t* rects = pixman_region_rects(region);
855 BRegion bregion;
856 for (int i = 0; i < count; ++i) {
857 // Have to substract one, because for pixman, the second coordinate
858 // lies outside the rectangle.
859 bregion.Include(BRect(rects[i].x1, rects[i].y1, rects[i].x2 - 1, rects[i].y2 - 1));
861 surface->view->ConstrainClippingRegion(&bregion);
862 return CAIRO_INT_STATUS_SUCCESS;
865 static cairo_int_status_t
866 _cairo_beos_surface_get_extents (void *abstract_surface,
867 cairo_rectangle_int16_t *rectangle)
869 cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
870 abstract_surface);
871 AutoLockView locker(surface->view);
872 if (!locker)
873 return CAIRO_INT_STATUS_UNSUPPORTED;
875 BRect size = surface->view->Bounds();
877 *rectangle = _brect_to_cairo_rect(size);
879 // Make sure to have our upperleft edge as (0,0)
880 rectangle->x = 0;
881 rectangle->y = 0;
883 return CAIRO_INT_STATUS_SUCCESS;
886 static const struct _cairo_surface_backend cairo_beos_surface_backend = {
887 CAIRO_SURFACE_TYPE_BEOS,
888 _cairo_beos_surface_create_similar,
889 _cairo_beos_surface_finish,
890 _cairo_beos_surface_acquire_source_image,
891 _cairo_beos_surface_release_source_image,
892 _cairo_beos_surface_acquire_dest_image,
893 _cairo_beos_surface_release_dest_image,
894 NULL, /* clone_similar */
895 _cairo_beos_surface_composite, /* composite */
896 _cairo_beos_surface_fill_rectangles,
897 NULL, /* composite_trapezoids */
898 NULL, /* create_span_renderer */
899 NULL, /* check_span_renderer */
900 NULL, /* copy_page */
901 NULL, /* show_page */
902 _cairo_beos_surface_set_clip_region,
903 NULL, /* intersect_clip_path */
904 _cairo_beos_surface_get_extents,
905 NULL, /* old_show_glyphs */
906 NULL, /* get_font_options */
907 NULL, /* flush */
908 NULL, /* mark_dirty_rectangle */
909 NULL, /* scaled_font_fini */
910 NULL, /* scaled_glyph_fini */
912 NULL, /* paint */
913 NULL, /* mask */
914 NULL, /* stroke */
915 NULL, /* fill */
916 NULL /* show_glyphs */
919 static cairo_surface_t *
920 _cairo_beos_surface_create_internal (BView* view,
921 BBitmap* bmp,
922 bool owns_bitmap_view)
924 // Must use malloc, because cairo code will use free() on the surface
925 cairo_beos_surface_t *surface = static_cast<cairo_beos_surface_t*>(
926 malloc(sizeof(cairo_beos_surface_t)));
927 if (surface == NULL) {
928 _cairo_error (CAIRO_STATUS_NO_MEMORY);
929 return const_cast<cairo_surface_t*>(&_cairo_surface_nil);
932 cairo_content_t content = CAIRO_CONTENT_COLOR;
933 if (bmp && (bmp->ColorSpace() == B_RGBA32 || bmp->ColorSpace() == B_RGBA15))
934 content = CAIRO_CONTENT_COLOR_ALPHA;
935 _cairo_surface_init(&surface->base, &cairo_beos_surface_backend, content);
937 surface->view = view;
938 surface->bitmap = bmp;
939 surface->owns_bitmap_view = owns_bitmap_view;
941 return (cairo_surface_t *) surface;
945 * cairo_beos_surface_create:
946 * @view: The view to draw on
948 * Creates a Cairo surface that draws onto a BeOS BView.
949 * The caller must ensure that the view does not get deleted before the surface.
950 * If the view is attached to a bitmap rather than an on-screen window, use
951 * cairo_beos_surface_create_for_bitmap() instead of this function.
953 cairo_surface_t *
954 cairo_beos_surface_create (BView* view)
956 return cairo_beos_surface_create_for_bitmap(view, NULL);
960 * cairo_beos_surface_create_for_bitmap:
961 * @view: The view to draw on
962 * @bmp: The bitmap to which the view is attached
964 * Creates a Cairo surface that draws onto a BeOS BView which is attached to a
965 * BBitmap.
966 * The caller must ensure that the view and the bitmap do not get deleted
967 * before the surface.
969 * For views that draw to a bitmap (as opposed to a screen), use this function
970 * rather than cairo_beos_surface_create(). Not using this function WILL lead to
971 * incorrect behaviour.
973 * For now, only views that draw to the entire area of bmp are supported.
974 * The view must already be attached to the bitmap.
976 cairo_surface_t *
977 cairo_beos_surface_create_for_bitmap (BView* view,
978 BBitmap* bmp)
980 return _cairo_beos_surface_create_internal(view, bmp);