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
37 // This is a C++ file in order to use the C++ BeOS API
41 #include "cairo-beos.h"
48 #include <DirectWindow.h>
54 #define CAIRO_INT_STATUS_SUCCESS (cairo_int_status_t)(CAIRO_STATUS_SUCCESS)
56 struct cairo_beos_surface_t
{
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.
74 // If true, surface and view should be deleted when this surface is
76 bool owns_bitmap_view
;
81 AutoLockView(BView
* view
) : mView(view
) {
82 mOK
= mView
->LockLooper();
87 mView
->UnlockLooper();
99 static cairo_surface_t
*
100 _cairo_beos_surface_create_internal (BView
* view
,
102 bool owns_bitmap_view
= false);
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;
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
) };
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
,
155 const BRect
* interestRect
= NULL
)
159 BWindow
* wnd
= view
->Window();
160 // If we have no window, can't do anything
168 // Is it a direct window?
169 BDirectWindow
* directWnd
= dynamic_cast<BDirectWindow
*>(wnd
);
175 // Is it visible? If so, we can copy the content off the screen
179 BRect
rectToCopy(view
->Bounds());
181 rectToCopy
= rectToCopy
& *interestRect
;
183 if (!rectToCopy
.IsValid())
187 BRect
screenRect(view
->ConvertToScreen(rectToCopy
));
188 screenRect
= screenRect
& screen
.Frame();
190 if (!screen
.IsValid())
194 *rect
= view
->ConvertFromScreen(screenRect
);
196 if (screen
.GetBitmap(bitmap
, false, &screenRect
) == B_OK
)
203 unpremultiply (unsigned char color
,
208 // plus alpha/2 to round instead of truncate
209 return (color
* 255 + alpha
/ 2) / alpha
;
213 premultiply (unsigned char color
,
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.
227 unpremultiply_rgba (unsigned char* data
,
231 unsigned char* retdata
)
233 unsigned char* end
= data
+ stride
* height
;
234 for (unsigned char* in
= data
, *out
= retdata
;
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
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
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
,
262 unsigned char* retdata
= reinterpret_cast<unsigned char*>(_cairo_malloc_ab(height
, stride
));
266 unsigned char* end
= data
+ stride
* height
;
267 for (unsigned char* in
= data
, *out
= retdata
;
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
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
285 * _cairo_beos_bitmap_to_surface:
287 * Returns an addrefed image surface for a BBitmap. The bitmap need not outlive
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);
302 view
.DrawBitmap(bitmap
, BPoint(0.0, 0.0));
305 cairo_image_surface_t
* imgsurf
= _cairo_beos_bitmap_to_surface(&bmp
);
308 bmp
.RemoveChild(&view
);
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());
324 premultiplied
= reinterpret_cast<unsigned char*>(
325 _cairo_malloc_ab(bitmap
->BytesPerRow(), height
));
327 memcpy(premultiplied
, bits
, bitmap
->BytesPerRow() * height
);
332 cairo_image_surface_t
* surf
= reinterpret_cast<cairo_image_surface_t
*>
333 (cairo_image_surface_create_for_data(premultiplied
,
337 bitmap
->BytesPerRow()));
338 if (surf
->base
.status
)
341 _cairo_image_surface_assume_ownership_of_data(surf
);
346 * _cairo_image_surface_to_bitmap:
348 * Converts an image surface to a BBitmap. The return value must be freed with
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
,
362 reinterpret_cast<unsigned char*>(data
->Bits()));
365 case CAIRO_FORMAT_RGB24
: {
366 BBitmap
* data
= new BBitmap(size
, B_RGB32
);
367 memcpy(data
->Bits(), surface
->data
, surface
->height
* surface
->stride
);
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.
383 _cairo_op_to_be_op (cairo_operator_t cairo_op
,
384 drawing_mode
* beos_op
)
388 case CAIRO_OPERATOR_SOURCE
:
389 *beos_op
= B_OP_COPY
;
391 case CAIRO_OPERATOR_OVER
:
392 *beos_op
= B_OP_ALPHA
;
395 case CAIRO_OPERATOR_ADD
:
396 // Does not actually work
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
:
427 static cairo_surface_t
*
428 _cairo_beos_surface_create_similar (void *abstract_surface
,
429 cairo_content_t content
,
433 fprintf(stderr
, "Creating similar\n");
435 cairo_beos_surface_t
*surface
= reinterpret_cast<cairo_beos_surface_t
*>(
443 BRect
rect(0.0, 0.0, width
- 1, height
- 1);
446 case CAIRO_CONTENT_ALPHA
:
447 // Can't support this natively
448 return _cairo_image_surface_create_with_content(content
, width
,
450 case CAIRO_CONTENT_COLOR_ALPHA
:
451 bmp
= new BBitmap(rect
, B_RGBA32
, true);
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
)
461 if (space
== B_RGBA15
)
463 bmp
= new BBitmap(rect
, space
, true);
465 BScreen
scr(surface
->view
->Window());
466 color_space space
= B_RGB32
;
468 space
= scr
.ColorSpace();
469 bmp
= new BBitmap(rect
, space
, true);
477 BView
* view
= new BView(rect
, "Cairo bitmap view", B_FOLLOW_ALL_SIDES
, 0);
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
*>(
487 if (surface
->owns_bitmap_view
) {
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
,
506 fprintf(stderr
, "Getting source image\n");
507 cairo_beos_surface_t
*surface
= reinterpret_cast<cairo_beos_surface_t
*>(
509 AutoLockView
locker(surface
->view
);
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
);
519 return CAIRO_STATUS_NO_MEMORY
;
522 return CAIRO_STATUS_SUCCESS
;
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
);
532 return CAIRO_STATUS_NO_MEMORY
;
536 return CAIRO_STATUS_SUCCESS
;
540 _cairo_beos_surface_release_source_image (void *abstract_surface
,
541 cairo_image_surface_t
*image
,
544 cairo_surface_destroy (&image
->base
);
546 BBitmap
* bmp
= static_cast<BBitmap
*>(image_extra
);
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
,
559 cairo_beos_surface_t
*surface
= reinterpret_cast<cairo_beos_surface_t
*>(
562 AutoLockView
locker(surface
->view
);
566 return CAIRO_STATUS_SUCCESS
;
569 if (surface
->bitmap
) {
570 surface
->view
->Sync();
571 *image_out
= _cairo_beos_bitmap_to_surface(surface
->bitmap
);
573 return CAIRO_STATUS_NO_MEMORY
;
577 image_rect
->width
= (*image_out
)->width
;
578 image_rect
->height
= (*image_out
)->height
;
581 return CAIRO_STATUS_SUCCESS
;
584 BRect
b_interest_rect(_cairo_rect_to_brect(interest_rect
));
588 ViewCopyStatus status
= _cairo_beos_view_to_bitmap(surface
->view
, &bitmap
,
589 &rect
, &b_interest_rect
);
590 if (status
== NOT_VISIBLE
) {
593 return CAIRO_STATUS_SUCCESS
;
596 return CAIRO_STATUS_NO_MEMORY
;
598 *image_rect
= _brect_to_cairo_rect(rect
);
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
);
606 *image_out
= _cairo_beos_bitmap_to_surface(bitmap
);
609 return CAIRO_STATUS_NO_MEMORY
;
613 return CAIRO_STATUS_SUCCESS
;
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
,
624 fprintf(stderr
, "Fallback drawing\n");
626 cairo_beos_surface_t
*surface
= reinterpret_cast<cairo_beos_surface_t
*>(
629 AutoLockView
locker(surface
->view
);
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
,
661 cairo_beos_surface_t
*surface
= reinterpret_cast<cairo_beos_surface_t
*>(
663 AutoLockView
locker(surface
->view
);
665 return CAIRO_INT_STATUS_SUCCESS
;
668 if (!_cairo_op_to_be_op(op
, &mode
))
669 return CAIRO_INT_STATUS_UNSUPPORTED
;
671 // XXX Masks are not yet supported
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)
684 if (!_cairo_matrix_is_integer_translation(&src
->matrix
, &itx
, &ity
))
685 return CAIRO_INT_STATUS_UNSUPPORTED
;
687 BRect
srcRect(src_x
+ itx
,
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
)->
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
);
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
);
711 beos_surface
->view
->Sync();
712 bmp
= beos_surface
->bitmap
;
714 _cairo_beos_view_to_bitmap(surface
->view
, &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
725 if (bmp
->ColorSpace() == B_RGB32
&& surface
->bitmap
&&
726 surface
->bitmap
->ColorSpace() == B_RGBA32
&&
727 (mode
== B_OP_COPY
|| mode
== B_OP_ALPHA
))
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
) {
752 surface
->view
->SetDrawingMode(mode
);
754 if (surface
->bitmap
&& surface
->bitmap
->ColorSpace() == B_RGBA32
)
755 surface
->view
->SetBlendingMode(B_PIXEL_ALPHA
, B_ALPHA_COMPOSITE
);
757 surface
->view
->SetBlendingMode(B_PIXEL_ALPHA
, B_ALPHA_OVERLAY
);
759 surface
->view
->DrawBitmap(bmp
, srcRect
, dstRect
);
761 surface
->view
->PopState();
766 return CAIRO_INT_STATUS_SUCCESS
;
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
,
781 const cairo_color_t
*color
,
782 cairo_rectangle_int16_t
*rects
,
785 fprintf(stderr
, "Drawing %i rectangles\n", num_rects
);
786 cairo_beos_surface_t
*surface
= reinterpret_cast<cairo_beos_surface_t
*>(
790 return CAIRO_INT_STATUS_SUCCESS
;
792 AutoLockView
locker(surface
->view
);
794 return CAIRO_INT_STATUS_SUCCESS
;
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)
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
);
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
*>(
843 AutoLockView
locker(surface
->view
);
845 return CAIRO_INT_STATUS_SUCCESS
;
847 if (region
== NULL
) {
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
);
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
*>(
871 AutoLockView
locker(surface
->view
);
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)
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 */
908 NULL
, /* mark_dirty_rectangle */
909 NULL
, /* scaled_font_fini */
910 NULL
, /* scaled_glyph_fini */
916 NULL
/* show_glyphs */
919 static cairo_surface_t
*
920 _cairo_beos_surface_create_internal (BView
* view
,
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.
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
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.
977 cairo_beos_surface_create_for_bitmap (BView
* view
,
980 return _cairo_beos_surface_create_internal(view
, bmp
);