📄 cairo-beos-surface.cpp
字号:
/* vim:set ts=8 sw=4 noet cin: *//* cairo - a vector graphics library with display and print output * * Copyright © 2005 Christian Biesinger <cbiesinger@web.de> * * This library is free software; you can redistribute it and/or * modify it either under the terms of the GNU Lesser General Public * License version 2.1 as published by the Free Software Foundation * (the "LGPL") or, at your option, under the terms of the Mozilla * Public License Version 1.1 (the "MPL"). If you do not alter this * notice, a recipient may use your version of this file under either * the MPL or the LGPL. * * You should have received a copy of the LGPL along with this library * in the file COPYING-LGPL-2.1; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * You should have received a copy of the MPL along with this library * in the file COPYING-MPL-1.1 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY * OF ANY KIND, either express or implied. See the LGPL or the MPL for * the specific language governing rights and limitations. * * The Original Code is the cairo graphics library. * * The Initial Developer of the Original Code is Christian Biesinger * <cbiesinger@web.de> * * Contributor(s): */// This is a C++ file in order to use the C++ BeOS API#include <new>#include <Bitmap.h>#include <Region.h>#if 0#include <DirectWindow.h>#endif#include <Screen.h>#include <Window.h>#include <Locker.h>#include "cairoint.h"#include "cairo-beos.h"#define CAIRO_INT_STATUS_SUCCESS (cairo_int_status_t)(CAIRO_STATUS_SUCCESS)struct cairo_beos_surface_t { cairo_surface_t base; BView* view; /* * A view is either attached to a bitmap, a window, or unattached. * If it is attached to a window, we can copy data out of it using BScreen. * If it is attached to a bitmap, we can read the bitmap data. * If it is not attached, it doesn't draw anything, we need not bother. * * Since there doesn't seem to be a way to get the bitmap from a view if it * is attached to one, we have to use a special surface creation function. */ BBitmap* bitmap; // If true, surface and view should be deleted when this surface is // destroyed bool owns_bitmap_view;};class AutoLockView { public: AutoLockView(BView* view) : mView(view) { mOK = mView->LockLooper(); } ~AutoLockView() { if (mOK) mView->UnlockLooper(); } operator bool() { return mOK; } private: BView* mView; 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_fixed_t* rect){ // A BRect is one pixel wider than you'd think return BRect(rect->x, rect->y, rect->x + rect->width - 1, rect->y + rect->height - 1);}static cairo_rectangle_fixed_t_brect_to_cairo_rect (const BRect& rect){ cairo_rectangle_fixed_t retval; retval.x = int(rect.left + 0.5); retval.y = int(rect.top + 0.5); retval.width = rect.IntegerWidth() + 1; retval.height = rect.IntegerHeight() + 1; return retval;}static rgb_color_cairo_color_to_be_color (const cairo_color_t* color){ // This factor ensures a uniform distribution of numbers const float factor = 256 - 1e-5; // Using doubles to have non-premultiplied colors rgb_color be_color = { uint8(color->red * factor), uint8(color->green * factor), uint8(color->blue * factor), uint8(color->alpha * factor) }; return be_color;}enum ViewCopyStatus { OK, NOT_VISIBLE, // The view or the interest rect is not visible on screen ERROR // The view was visible, but the rect could not be copied. Probably OOM};/** * _cairo_beos_view_to_bitmap: * @bitmap: [out] The resulting bitmap. * @rect: [out] The rectangle that was copied, in the view's coordinate system * @interestRect: If non-null, only this part of the view will be copied (view's coord system). * * Gets the contents of the view as a BBitmap*. Caller must delete the bitmap. **/static ViewCopyStatus_cairo_beos_view_to_bitmap (BView* view, BBitmap** bitmap, BRect* rect = NULL, const BRect* interestRect = NULL){ *bitmap = NULL; BWindow* wnd = view->Window(); // If we have no window, can't do anything if (!wnd) return NOT_VISIBLE; view->Sync(); wnd->Sync();#if 0 // Is it a direct window? BDirectWindow* directWnd = dynamic_cast<BDirectWindow*>(wnd); if (directWnd) { // WRITEME }#endif // Is it visible? If so, we can copy the content off the screen if (wnd->IsHidden()) return NOT_VISIBLE; BRect rectToCopy(view->Bounds()); if (interestRect) rectToCopy = rectToCopy & *interestRect; if (!rectToCopy.IsValid()) return NOT_VISIBLE; BScreen screen(wnd); BRect screenRect(view->ConvertToScreen(rectToCopy)); screenRect = screenRect & screen.Frame(); if (!screen.IsValid()) return NOT_VISIBLE; if (rect) *rect = view->ConvertFromScreen(screenRect); if (screen.GetBitmap(bitmap, false, &screenRect) == B_OK) return OK; return ERROR;}inline unsigned charunpremultiply (unsigned char color, unsigned char alpha){ if (alpha == 0) return 0; // plus alpha/2 to round instead of truncate return (color * 255 + alpha / 2) / alpha;}inline unsigned charpremultiply (unsigned char color, unsigned char alpha){ // + 127 to round, instead of truncate return (color * alpha + 127) / 255;}/** * unpremultiply_rgba: * * Takes an input in ABGR premultiplied image data and unmultiplies it. * The result is stored in retdata. **/static voidunpremultiply_rgba (unsigned char* data, int width, int height, int stride, unsigned char* retdata){ unsigned char* end = data + stride * height; for (unsigned char* in = data, *out = retdata; in < end; in += stride, out += stride) { for (int i = 0; i < width; ++i) { // XXX for a big-endian platform this'd have to change int idx = 4 * i; unsigned char alpha = in[idx + 3]; out[idx + 0] = unpremultiply(in[idx + 0], alpha); // B out[idx + 1] = unpremultiply(in[idx + 1], alpha); // G out[idx + 2] = unpremultiply(in[idx + 2], alpha); // R out[idx + 3] = in[idx + 3]; // Alpha } }}/** * premultiply_rgba: * * Takes an input in ABGR non-premultiplied image data and premultiplies it. * The returned data must be freed with free(). **/static unsigned char*premultiply_rgba (unsigned char* data, int width, int height, int stride){ unsigned char* retdata = reinterpret_cast<unsigned char*>(malloc(stride * height)); if (!retdata) return NULL; unsigned char* end = data + stride * height; for (unsigned char* in = data, *out = retdata; in < end; in += stride, out += stride) { for (int i = 0; i < width; ++i) { // XXX for a big-endian platform this'd have to change int idx = 4 * i; unsigned char alpha = in[idx + 3]; out[idx + 0] = premultiply(in[idx + 0], alpha); // B out[idx + 1] = premultiply(in[idx + 1], alpha); // G out[idx + 2] = premultiply(in[idx + 2], alpha); // R out[idx + 3] = in[idx + 3]; // Alpha } } return retdata;}/** * _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*>( malloc(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;}/** * _cairo_image_surface_to_bitmap: * * Converts an image surface to a BBitmap. The return value must be freed with * delete. **/static BBitmap*_cairo_image_surface_to_bitmap (cairo_image_surface_t* surface){ BRect size(0.0, 0.0, surface->width - 1, surface->height - 1); switch (surface->format) { case CAIRO_FORMAT_ARGB32: { BBitmap* data = new BBitmap(size, B_RGBA32); unpremultiply_rgba(surface->data, surface->width, surface->height, surface->stride, reinterpret_cast<unsigned char*>(data->Bits())); return data; } case CAIRO_FORMAT_RGB24: { BBitmap* data = new BBitmap(size, B_RGB32); memcpy(data->Bits(), surface->data, surface->height * surface->stride); return data; } default: assert(0); return NULL; }}/** * _cairo_op_to_be_op: * * Converts a cairo drawing operator to a beos drawing_mode. Returns true if * the operator could be converted, false otherwise. **/static bool_cairo_op_to_be_op (cairo_operator_t cairo_op, drawing_mode* beos_op){ switch (cairo_op) { case CAIRO_OPERATOR_SOURCE: *beos_op = B_OP_COPY; return true; case CAIRO_OPERATOR_OVER: *beos_op = B_OP_ALPHA; return true; case CAIRO_OPERATOR_ADD: // Does not actually work#if 1 return false;#else *beos_op = B_OP_ADD; return true;#endif case CAIRO_OPERATOR_CLEAR: // Does not map to B_OP_ERASE - it replaces the dest with the low // color, instead of transparency; could be done by setting low // color appropriately. case CAIRO_OPERATOR_IN: case CAIRO_OPERATOR_OUT: case CAIRO_OPERATOR_ATOP: case CAIRO_OPERATOR_DEST: case CAIRO_OPERATOR_DEST_OVER: case CAIRO_OPERATOR_DEST_IN: case CAIRO_OPERATOR_DEST_OUT: case CAIRO_OPERATOR_DEST_ATOP: case CAIRO_OPERATOR_XOR: case CAIRO_OPERATOR_SATURATE: default: return false; };}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){ 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;}static cairo_status_t_cairo_beos_surface_acquire_source_image (void *abstract_surface, cairo_image_surface_t **image_out, void **image_extra){ fprintf(stderr, "Getting source image\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -