[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] gnash backend/render_handler_cairo.cpp backend/...
From: |
Bastiaan Jacques |
Subject: |
[Gnash-commit] gnash backend/render_handler_cairo.cpp backend/... |
Date: |
Thu, 18 Oct 2007 09:05:40 +0000 |
CVSROOT: /sources/gnash
Module name: gnash
Changes by: Bastiaan Jacques <bjacques> 07/10/18 09:05:40
Modified files:
backend : render_handler_cairo.cpp render_handler_cairo.h
gui : gtk_glue_cairo.cpp gtk_glue_cairo.h
Log message:
* backend/render_handler_cairo.cpp: New Cairo implementation.
Fixes all Cairo bugs currently in Savannah, but adds a set of
new bugs. The new renderer offers significantly better
performance and better rendering quality. This implementation
does not rely on Gnash's own triangulation.
* backend/render_handler_cairo.h: Renamed set_handle to
set_context, which is more descriptive.
* gui/gtk_glue_cairo.{cpp,h}: Updated for set_context.
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/backend/render_handler_cairo.cpp?cvsroot=gnash&r1=1.24&r2=1.25
http://cvs.savannah.gnu.org/viewcvs/gnash/backend/render_handler_cairo.h?cvsroot=gnash&r1=1.6&r2=1.7
http://cvs.savannah.gnu.org/viewcvs/gnash/gui/gtk_glue_cairo.cpp?cvsroot=gnash&r1=1.11&r2=1.12
http://cvs.savannah.gnu.org/viewcvs/gnash/gui/gtk_glue_cairo.h?cvsroot=gnash&r1=1.12&r2=1.13
Patches:
Index: backend/render_handler_cairo.cpp
===================================================================
RCS file: /sources/gnash/gnash/backend/render_handler_cairo.cpp,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -b -r1.24 -r1.25
--- backend/render_handler_cairo.cpp 10 Sep 2007 16:53:29 -0000 1.24
+++ backend/render_handler_cairo.cpp 18 Oct 2007 09:05:40 -0000 1.25
@@ -1,28 +1,55 @@
-// render_handler_cairo.cpp -- Timothy Lee <address@hidden> 2006
-
-// This source code has been donated to the Public Domain. Do
-// whatever you want with it.
-
-// A render_handler that uses cairo
-
+//
+// Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+// Known bugs:
+// - Shape filling problems: renderer skips certain fills. See car_smash.swf.
+// - Fonts: The "a" is not filled in text-test.swf. If subshapes are ignored
+// then it works as expected. The Agg renderer would suggest this has
+// something to do with the fill rule.
+// - Rotation problem in gradient-tests.swf.
+//
+// TODOs:
+// - Implement focal gradients.
+// - Implement alpha bitmaps.
+// - Implement unimplemented methods.
+// - Would be nice to have a header/implementation separation.
+// - Document workings of Cairo and this renderer.
+// - Implement getPixel and friends.
+// - Test bitmap implementation correctness.
+// - Figure out what extend types should be used and when.
+// - Figure out what the deal with subpixel offsets is.
+// - Cleanups.
+// - Optimizations.
+//
+// Already implemented:
+// - outlines
+// - fills: solid, linear, radial and bitmap
+// - bitmaps (excluding alpha)
+// - fonts
+// - masks
+// - video (from old Cairo renderer)
#include <cairo/cairo.h>
+#include <boost/scoped_array.hpp>
#include "render_handler.h"
-#include "render_handler_tri.h"
-#include "types.h"
#include "image.h"
-#include "utility.h"
-
-#include "tu_config.h"
-#include "log.h"
-
namespace gnash {
-namespace renderer {
-namespace cairo {
-static cairo_t* g_cr_output = 0;
-static cairo_t* g_cr = 0;
// Converts from RGB image to 32-bit pixels in CAIRO_FORMAT_RGB24 format
@@ -35,16 +62,14 @@
const uint8_t* src = im->scanline(y);
for (size_t x = 0; x < im->width(); x++, src += 3)
{
- // 32-bit RGB data in native endian format
*dst32++ = (src[0] << 16) | (src[1] << 8) | src[2];
}
}
}
-
// Converts from RGBA image to 32-bit pixels in CAIRO_FORMAT_ARGB32 format
static void
-rgba_to_cairo_argb32(uint8_t* dst, const image::rgba* im)
+rgba_to_cairo_argb(uint8_t* dst, const image::rgba* im)
{
uint32_t* dst32 = reinterpret_cast<uint32_t*>(dst);
for (size_t y = 0; y < im->height(); y++)
@@ -52,706 +77,812 @@
const uint8_t* src = im->scanline(y);
for (size_t x = 0; x < im->width(); x++, src += 4)
{
- // 32-bit ARGB data in native endian format
- *dst32++ = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
+ const uint8_t& r = src[0],
+ g = src[1],
+ b = src[2],
+ a = src[3];
+
+ if (a) {
+ *dst32++ = (a << 24) | (r << 16) | (g << 8) | b;
+ } else {
+ *dst32++ = 0;
+ }
}
}
}
-// bitmap_info_cairo declaration
-class bitmap_info_cairo : public gnash::bitmap_info
+
+class bitmap_info_cairo : public bitmap_info
{
-public:
- // Cairo image surface
- unsigned char* m_buffer;
- cairo_surface_t* m_image;
- cairo_pattern_t* m_pattern;
-
- bitmap_info_cairo();
- bitmap_info_cairo(int width, int height, uint8_t* data);
- bitmap_info_cairo(image::rgb* im);
- bitmap_info_cairo(image::rgba* im);
-
- ~bitmap_info_cairo() {
- if (m_pattern)
- cairo_pattern_destroy(m_pattern);
- if (m_image) cairo_surface_destroy(m_image);
- if (m_buffer) delete [] m_buffer;
+ public:
+ bitmap_info_cairo(uint8_t* data, int width, int height,
+ size_t bpp, cairo_format_t format)
+ : _data(data),
+ _width(width),
+ _height(height),
+ _bytes_per_pixel(bpp),
+ _format(format),
+ _surface(cairo_image_surface_create_for_data(_data.get(),
+ format, width, height, width * bpp)),
+ _pattern(cairo_pattern_create_for_surface (_surface))
+ {
}
+
+ ~bitmap_info_cairo()
+ {
+ cairo_surface_destroy(_surface);
+ }
+
+ cairo_pattern_t* apply(const cairo_matrix_t* mat, int fill_type)
+ {
+ cairo_pattern_set_matrix(_pattern, mat);
+
+ cairo_extend_t extend = CAIRO_EXTEND_REPEAT;
+
+#if 0
+ // The extend type should probably depend on certain factors, but which?
+ switch(fill_type) {
+ case SWF::FILL_CLIPPED_BITMAP:
+ break;
+ case SWF::FILL_CLIPPED_BITMAP_HARD:
+ case SWF::FILL_TILED_BITMAP_HARD:
+ break;
+ case SWF::FILL_TILED_BITMAP:
+ break;
+ }
+#endif
+
+ cairo_pattern_set_extend(_pattern, extend);
+
+ return _pattern;
+ }
+
+ private:
+ boost::scoped_array<uint8_t> _data;
+ int _width;
+ int _height;
+ size_t _bytes_per_pixel;
+ cairo_format_t _format;
+ cairo_surface_t* _surface;
+ cairo_pattern_t* _pattern;
};
-class render_handler_cairo : public gnash::triangulating_render_handler
+
+class DSOEXPORT render_handler_cairo: public render_handler
{
+ typedef std::vector<path> PathVec;
+ typedef std::vector<const path*> PathPtrVec;
public:
- // Some renderer state.
- cairo_t* m_cr_mask;
- cairo_t* m_cr_dummy;
- int m_view_width;
- int m_view_height;
-
- // Video buffer
- uint8_t* m_video_buffer;
- int m_video_bufsize;
-
- // Enable/disable antialiasing.
- bool m_enable_antialias;
-
- // Output size.
- float m_display_width;
- float m_display_height;
-
- gnash::matrix m_current_matrix;
- gnash::cxform m_current_cxform;
- void set_antialiased(bool enable) {
- m_enable_antialias = enable;
- }
- class fill_style
+ render_handler_cairo()
+ : _video_bufsize(0),
+ _drawing_mask(false)
{
- public:
- enum mode
- {
- INVALID,
- COLOR,
- BITMAP_WRAP,
- BITMAP_CLAMP,
- LINEAR_GRADIENT,
- RADIAL_GRADIENT
- };
- mode m_mode;
- gnash::rgba m_color;
- const bitmap_info_cairo* m_bitmap_info;
- gnash::matrix m_bitmap_matrix;
- gnash::cxform m_bitmap_color_transform;
- bool m_has_nonzero_bitmap_additive_color;
+ cairo_surface_t* dummy_surface = cairo_image_surface_create(
+ CAIRO_FORMAT_A8, 1, 1);
+ _cr = cairo_create(dummy_surface);
+ cairo_surface_destroy(dummy_surface);
+ }
- fill_style()
- :
- m_mode(INVALID),
- m_has_nonzero_bitmap_additive_color(false)
+ ~render_handler_cairo()
{
}
- // Push our style into cairo.
- void apply(/*const matrix& current_matrix*/) const
- {
- assert(m_mode != INVALID);
- if (m_mode == COLOR)
+ virtual bitmap_info* create_bitmap_info_alpha(int w, int h, unsigned char*
data)
{
- apply_color(m_color);
+ log_unimpl("create_bitmap_info_alpha");
+ return NULL;
}
- else if (m_mode == BITMAP_WRAP || m_mode == BITMAP_CLAMP)
+
+ virtual bitmap_info* create_bitmap_info_rgb(image::rgb* im)
{
- assert(m_bitmap_info != NULL);
+ int buf_size = im->width() * im->height() * 4;
+ uint8_t* buffer = new uint8_t[buf_size];
- apply_color(m_color);
+ rgb_to_cairo_rgb24(buffer, im);
- if (m_bitmap_info != NULL)
- {
- // Set up the texture for rendering.
- {
- // Do the modulate part of the color
- // transform in the first pass. The
- // additive part, if any, needs to
- // happen in a second pass.
- // FIXME!!! bitmap cannot be modulated by RGB
- cairo_set_source_rgba(g_cr,
- m_bitmap_color_transform.m_[0][0],
- m_bitmap_color_transform.m_[1][0],
- m_bitmap_color_transform.m_[2][0],
- m_bitmap_color_transform.m_[3][0]);
+ return new bitmap_info_cairo(buffer, im->width(), im->height(), 4,
+ CAIRO_FORMAT_RGB24);
}
- cairo_pattern_t* pattern = m_bitmap_info->m_pattern;
+ virtual bitmap_info* create_bitmap_info_rgba(image::rgba* im)
+ {
+ int buf_size = im->width() * im->height() * 4;
+ uint8_t* buffer = new uint8_t[buf_size];
- if (m_mode == BITMAP_CLAMP)
+ rgba_to_cairo_argb(buffer, im);
+
+ return new bitmap_info_cairo(buffer, im->width(), im->height(), 4,
+ CAIRO_FORMAT_ARGB32);
+ }
+
+ virtual void delete_bitmap_info(bitmap_info* bi)
{
- cairo_pattern_set_extend(pattern, CAIRO_EXTEND_NONE);
+ delete bi;
}
- else
+
+ virtual int videoFrameFormat()
{
- cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
+ return render_handler::RGB;
}
- // Set up the bitmap matrix
- // FIXME!!! scaling and offset is wrong
+ virtual void drawVideoFrame(image::image_base* baseframe, const matrix* m,
const rect* bounds)
+ {
+ // Extract frame attributes
+ image::rgb* frame = static_cast<image::rgb*>(baseframe);
+ int w = frame->width();
+ int h = frame->height();
+
+ // Compute bounding rectangle size relative to video object
+ double w_scale = bounds->width() / w;
+ double h_scale = bounds->height() / h;
+
+ // Fit video to bounding rectangle
cairo_matrix_t mat;
- const gnash::matrix& m = m_bitmap_matrix;
- cairo_matrix_init(&mat, m.m_[0][0], m.m_[1][0],
- m.m_[0][1], m.m_[1][1], m.m_[0][2], m.m_[1][2]);
- cairo_pattern_set_matrix(pattern, &mat);
+ cairo_matrix_init_scale(&mat, w_scale, h_scale);
+ cairo_matrix_translate(&mat,
+ bounds->get_x_min(), bounds->get_y_min());
- cairo_set_source(g_cr, pattern);
- }
+ // Now apply transformation to video
+ cairo_matrix_t frame_mat;
+ init_cairo_matrix(&frame_mat, *m);
+
+ cairo_matrix_multiply(&mat, &mat, &frame_mat);
+
+ // Inverse the matrix for pattern space
+ cairo_matrix_invert(&mat);
+
+ // Convert RGB frame to cairo format
+ size_t buf_size = w * h * 4;
+
+ if (_video_bufsize < buf_size) {
+ _video_buffer.reset(new uint8_t[buf_size]);
+ _video_bufsize = buf_size;
}
+
+ rgb_to_cairo_rgb24(_video_buffer.get(), frame);
+
+ // Create a pattern from the the RGB frame
+ cairo_surface_t* surface = cairo_image_surface_create_for_data(
+ _video_buffer.get(), CAIRO_FORMAT_RGB24, w, h, w * 4);
+ cairo_pattern_t* pattern = cairo_pattern_create_for_surface(surface);
+ cairo_pattern_set_extend(pattern, CAIRO_EXTEND_NONE);
+ cairo_pattern_set_matrix(pattern, &mat);
+
+ // Draw the frame now
+ cairo_save(_cr);
+ cairo_set_source(_cr, pattern);
+
+ geometry::Range2d<float> range = bounds->getRange();
+ m->transform(range);
+
+ cairo_rectangle(_cr, range.getMinX(), range.getMinY(), range.width(),
+ range.height());
+ cairo_clip(_cr);
+ cairo_paint(_cr);
+ cairo_restore(_cr);
+
+ // Clean up
+ cairo_pattern_destroy(pattern);
+ cairo_surface_destroy(surface);
}
- // Return true if we need to do a second pass to make
- // a valid color. This is for cxforms with additive
- // parts; this is the simplest way (that we know of)
- // to implement an additive color with stock OpenGL.
- bool needs_second_pass() const
- {
- if (m_mode == BITMAP_WRAP || m_mode == BITMAP_CLAMP)
+ // FIXME
+ geometry::Range2d<int>
+ world_to_pixel(const rect& worldbounds)
+{
+ // TODO: verify this is correct
+ geometry::Range2d<int> ret(worldbounds.getRange());
+ ret.scale(1.0/20.0); // twips to pixels
+ return ret;
+}
+
+ // FIXME
+ point
+ pixel_to_world(int x, int y)
{
- return m_has_nonzero_bitmap_additive_color;
+ // TODO: verify this is correct
+ return point(PIXELS_TO_TWIPS(x), PIXELS_TO_TWIPS(y));
}
- else
+
+ void
+ set_color(const rgba& c)
{
- return false;
- }
+ cairo_set_source_rgba (_cr, c.m_r / 255.0, c.m_g / 255.0,
+ c.m_b / 255.0, c.m_a / 255.0);
}
- // Set OpenGL state for a necessary second pass.
- void apply_second_pass() const
+ virtual void begin_display(
+ const rgba& bg_color,
+ int viewport_x0, int viewport_y0,
+ int viewport_width, int viewport_height,
+ float x0, float x1, float y0, float y1)
{
- assert(needs_second_pass());
- // The additive color also seems to be modulated by the
texture. So,
- // maybe we can fake this in one pass using using the mean
value of
- // the colors: c0*t+c1*t = ((c0+c1)/2) * t*2
- // I don't know what the alpha component of the color is for.
- cairo_set_source_rgba(g_cr,
- m_bitmap_color_transform.m_[0][1] / 255.0f,
- m_bitmap_color_transform.m_[1][1] / 255.0f,
- m_bitmap_color_transform.m_[2][1] / 255.0f,
- m_bitmap_color_transform.m_[3][1] / 255.0f);
+ float display_width = fabsf(x1 - x0);
+ float display_height = fabsf(y1 - y0);
+
+ cairo_identity_matrix(_cr);
+ cairo_rectangle(_cr, x0, y0, display_width, display_height);
+ cairo_clip(_cr);
+ cairo_scale(_cr, viewport_width / display_width,
+ viewport_height / display_height);
+ cairo_translate(_cr, x0, y0);
-/*
- glBlendFunc(GL_ONE, GL_ONE);
-*/
+ // Clear the background, if background color has alpha > 0.
+ if (bg_color.m_a) {
+ set_color(bg_color);
+ cairo_paint(_cr);
+ }
}
- void cleanup_second_pass() const
+ virtual void end_display()
{
-/*
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-*/
}
+ virtual void set_matrix(const matrix& m)
+ {
+ log_unimpl("set_matrix");
+ }
- void disable() { m_mode = INVALID; }
- void set_color(const gnash::rgba& color) { m_mode = COLOR; m_color
= color; }
- void set_bitmap(const gnash::bitmap_info* bi, const gnash::matrix&
m, bitmap_wrap_mode wm, const gnash::cxform& color_transform)
+ virtual void set_cxform(const cxform& cx)
{
- m_mode = (wm == WRAP_REPEAT) ? BITMAP_WRAP : BITMAP_CLAMP;
- m_bitmap_info = static_cast<const bitmap_info_cairo*>(bi);
- m_bitmap_matrix = m;
- m_bitmap_color_transform = color_transform;
- m_bitmap_color_transform.clamp();
+ log_unimpl("set_cxform");
+ }
- m_color = gnash::rgba(
- uint8_t(m_bitmap_color_transform.m_[0][0] * 255.0f),
- uint8_t(m_bitmap_color_transform.m_[1][0] * 255.0f),
- uint8_t(m_bitmap_color_transform.m_[2][0] * 255.0f),
- uint8_t(m_bitmap_color_transform.m_[3][0] * 255.0f));
+ virtual void draw_line_strip(const void* coords, int vertex_count,
+ const rgba& color)
+ {
+ log_unimpl("draw_line_strip");
+ }
- if (m_bitmap_color_transform.m_[0][1] > 1.0f
- || m_bitmap_color_transform.m_[1][1] > 1.0f
- || m_bitmap_color_transform.m_[2][1] > 1.0f
- || m_bitmap_color_transform.m_[3][1] > 1.0f)
+ virtual void draw_poly(const point* corners, size_t corner_count,
+ const rgba& fill, const rgba& outline, bool masked)
{
- m_has_nonzero_bitmap_additive_color = true;
+ log_unimpl("draw_poly");
}
- else
+
+ virtual void draw_bitmap(
+ const matrix& m,
+ const bitmap_info* bi,
+ const rect& coords,
+ const rect& uv_coords,
+ const rgba& color)
{
- m_has_nonzero_bitmap_additive_color = false;
+ log_unimpl("draw_bitmap");
}
+
+ virtual void set_antialiased(bool enable)
+ {
+ log_unimpl("set_antialiased");
}
- bool is_valid() const { return m_mode != INVALID; }
- };
+ virtual void begin_submit_mask()
+ {
+ PathVec mask;
+ _masks.push_back(mask);
+
+ _drawing_mask = true;
+ }
- // Style state.
- enum style_index
+ virtual void end_submit_mask()
{
- LEFT_STYLE = 0,
- RIGHT_STYLE,
- LINE_STYLE,
+ _drawing_mask = false;
- STYLE_COUNT
- };
- fill_style m_current_styles[STYLE_COUNT];
+ // Load the mask paths into the cairo context.
+ add_paths(_masks.back());
- gnash::bitmap_info* create_bitmap_info_rgb(image::rgb* im)
- // Given an image, returns a pointer to a bitmap_info class
- // that can later be passed to fill_styleX_bitmap(), to set a
- // bitmap fill style.
- {
- return new bitmap_info_cairo(im);
- }
+ // Save the context so we can return to the former clip later.
+ cairo_save(_cr);
+ // Clip the fills defined by the current paths.
+ cairo_clip(_cr);
+
+ // Remove the current path since we have no further use for it (and may
+ // confuse us later).
+ cairo_new_path(_cr);
- gnash::bitmap_info* create_bitmap_info_rgba(image::rgba* im)
- // Given an image, returns a pointer to a bitmap_info class
- // that can later be passed to fill_style_bitmap(), to set a
- // bitmap fill style.
- //
- // This version takes an image with an alpha channel.
- {
- return new bitmap_info_cairo(im);
}
- gnash::bitmap_info* create_bitmap_info_alpha(int w, int h, uint8_t*
data)
- // Create a bitmap_info so that it contains an alpha texture
- // with the given data (1 byte per texel).
+ virtual void disable_mask()
{
- return new bitmap_info_cairo(w, h, data);
- }
+ // Restore the previous clip.
+ cairo_restore(_cr);
+ _masks.pop_back();
+ }
- void delete_bitmap_info(gnash::bitmap_info* bi)
- // Delete the given bitmap info class.
+ void add_path(cairo_t* cr, const path& cur_path)
{
- delete bi;
+ cairo_move_to(cr, cur_path.m_ax, cur_path.m_ay);
+
+ float prev_x = cur_path.m_ax,
+ prev_y = cur_path.m_ay;
+
+ for (std::vector<edge>::const_iterator it = cur_path.m_edges.begin(),
+ end = cur_path.m_edges.end(); it != end; ++it) {
+ const edge& cur_edge = *it;
+
+ if (cur_edge.is_straight()) {
+ cairo_line_to(cr, cur_edge.m_ax, cur_edge.m_ay);
+ } else {
+
+ // Cairo expects a cubic Bezier curve, while Flash gives us a
+ // quadratic one. We must apply a conversion:
+
+ const float two_thirds = 2.0/3.0;
+ const float one_third = 1 - two_thirds;
+
+ float x1 = prev_x + two_thirds * (cur_edge.m_cx - prev_x);
+ float y1 = prev_y + two_thirds * (cur_edge.m_cy - prev_y);
+
+ float x2 = cur_edge.m_cx + one_third * (cur_edge.m_ax - cur_edge.m_cx);
+ float y2 = cur_edge.m_cy + one_third * (cur_edge.m_ay - cur_edge.m_cy);
+
+ const float& x3 = cur_edge.m_ax;
+ const float& y3 = cur_edge.m_ay;
+
+
+ cairo_curve_to(cr, x1, y1, x2, y2, x3, y3);
}
+ prev_x = cur_edge.m_ax;
+ prev_y = cur_edge.m_ay;
- // Constructor
- render_handler_cairo() :
- m_cr_mask(0), m_view_width(0), m_view_height(0),
- m_video_buffer(0), m_video_bufsize(0)
- {
- cairo_surface_t* dummy = cairo_image_surface_create(
- CAIRO_FORMAT_A8, 1, 1);
- m_cr_dummy = cairo_create(dummy);
- cairo_surface_destroy(dummy);
}
- // Destructor
- ~render_handler_cairo()
- {
- if (m_video_buffer) delete [] m_video_buffer;
- if (m_cr_mask) cairo_destroy(m_cr_mask);
- cairo_destroy(m_cr_dummy);
}
- void begin_display(
- const gnash::rgba& background_color,
- int /*viewport_x0*/, int /*viewport_y0*/,
- int viewport_width, int viewport_height,
- float x0, float x1, float y0, float y1)
- // Set up to render a full frame from a movie and fills the
- // background. Sets up necessary transforms, to scale the
- // movie to fit within the given dimensions. Call
- // end_display() when you're done.
- //
- // The rectangle (viewport_x0, viewport_y0, viewport_x0 +
- // viewport_width, viewport_y0 + viewport_height) defines the
- // window coordinates taken up by the movie.
- //
- // The rectangle (x0, y0, x1, y1) defines the pixel
- // coordinates of the movie that correspond to the viewport
- // bounds.
- {
- g_cr = (g_cr_output ? g_cr_output : m_cr_dummy);
-
- m_display_width = fabsf(x1 - x0);
- m_display_height = fabsf(y1 - y0);
- m_view_width = viewport_width;
- m_view_height = viewport_height;
-
- cairo_identity_matrix(g_cr);
- cairo_rectangle(g_cr, x0, y0, m_display_width, m_display_height);
- cairo_clip(g_cr);
- cairo_scale(g_cr, viewport_width / m_display_width,
- viewport_height / m_display_height);
- cairo_translate(g_cr, x0, y0);
- // Clear the background, if background color has alpha > 0.
- if (background_color.m_a > 0)
+ PathPtrVec
+ get_paths_by_style(const PathVec& path_vec, unsigned int style)
{
- // Draw a big quad.
- apply_color(background_color);
- cairo_rectangle(g_cr, x0, y0, x1 - x0, y1 - y0);
- cairo_fill(g_cr);
+ PathPtrVec paths;
+ for (PathVec::const_iterator it = path_vec.begin(), end = path_vec.end();
+ it != end; ++it) {
+ const path& cur_path = *it;
+
+ if (cur_path.m_fill0 == style) {
+ paths.push_back(&cur_path);
}
+
+ if (cur_path.m_fill1 == style) {
+ paths.push_back(&cur_path);
}
+ }
+ return paths;
+ }
- void end_display()
- // Clean up after rendering a frame.
+ void apply_line_style(const line_style& style, const cxform& cx)
{
+ float width = style.get_width();
+
+ if ( width == 0.0 ) {
+ // TODO: test this!
+ cairo_set_line_width(_cr, 1.0); // expected: 1 pixel
+ } else {
+ cairo_set_line_width(_cr, width);
}
+ rgba color = cx.transform(style.get_color());
- void set_matrix(const gnash::matrix& m)
- // Set the current transform for mesh & line-strip rendering.
+ set_color(color);
+ }
+
+ std::vector<cairo_pattern_t*>
+ build_cairo_styles(const std::vector<fill_style>& fill_styles, const cxform&
cx,
+ const matrix& mat)
{
- m_current_matrix = m;
+ std::vector<cairo_pattern_t*> styles_vec_cairo;
+
+ for (std::vector<fill_style>::const_iterator it = fill_styles.begin(),
+ end = fill_styles.end(); it != end; ++it) {
+ const fill_style& cur_style = *it;
+
+ cairo_pattern_t* pattern = get_cairo_pattern(cur_style, cx, mat);
+ styles_vec_cairo.push_back(pattern);
}
+ return styles_vec_cairo;
+ }
- void set_cxform(const gnash::cxform& cx)
- // Set the current color transform for mesh & line-strip rendering.
+ void
+ pattern_add_color_stops(const fill_style& style, cairo_pattern_t* pattern,
+ const cxform& cx)
{
- m_current_cxform = cx;
+ for (int index = 0; index < style.get_color_stop_count(); ++index) {
+
+ const gradient_record& grad = style.get_color_stop(index);
+
+ rgba c = cx.transform(grad.m_color);
+
+ cairo_pattern_add_color_stop_rgba (pattern,
+ grad.m_ratio / 255.0, c.m_r / 255.0, c.m_g / 255.0,
+ c.m_b / 255.0, c.m_a / 255.0);
+ }
}
- static void apply_matrix(const gnash::matrix& m)
- // add user space transformation
+ cairo_pattern_t*
+ get_cairo_pattern(const fill_style& style, const cxform& cx, const matrix&
mat)
+ {
+ int fill_type = style.get_type();
+ cairo_pattern_t* pattern = NULL;
+
+ switch (fill_type) {
+
+ case SWF::FILL_LINEAR_GRADIENT:
{
+ matrix m = style.get_gradient_matrix();
+ matrix cm;
+ cm.set_inverse(mat);
+ m.concatenate(cm);
+
cairo_matrix_t mat;
- cairo_matrix_init(&mat, m.m_[0][0], m.m_[1][0], m.m_[0][1],
- m.m_[1][1], m.m_[0][2], m.m_[1][2]);
- cairo_transform(g_cr, &mat);
- }
+ init_cairo_matrix(&mat, m);
+
+ pattern = cairo_pattern_create_linear(0, 0, 256.0, 0);
+ cairo_pattern_set_matrix (pattern, &mat);
+
+ pattern_add_color_stops(style, pattern, cx);
- static void apply_color(const gnash::rgba& c)
- // Set the given color.
+ break;
+ }
+ case SWF::FILL_RADIAL_GRADIENT:
{
- cairo_set_source_rgba(g_cr,
- c.m_r / 255.0, c.m_g / 255.0, c.m_b / 255.0, c.m_a / 255.0);
+ matrix m = style.get_gradient_matrix();
+ matrix cm;
+ cm.set_inverse(mat);
+ m.concatenate(cm);
+
+ // move the center of the radial fill to where it should be, according
to Udo
+ gnash::matrix transl;
+ transl.concatenate_translation(-32.0f, -32.0f);
+ transl.concatenate(m);
+
+ cairo_matrix_t mat;
+ init_cairo_matrix(&mat, transl);
+
+ pattern = cairo_pattern_create_radial(0.0, 0.0, 0.0, 0.0, 0.0, 32.0);
+
+ cairo_pattern_set_matrix (pattern, &mat);
+
+ pattern_add_color_stops(style, pattern, cx);
+ break;
}
+ case SWF::FILL_FOCAL_GRADIENT:
+ {
+ log_unimpl("focal gradient fill");
- void fill_style_disable(int fill_side)
- // Don't fill on the {0 == left, 1 == right} side of a path.
+ break;
+ }
+ case SWF::FILL_TILED_BITMAP_HARD:
+ case SWF::FILL_TILED_BITMAP:
+ case SWF::FILL_CLIPPED_BITMAP:
+ case SWF::FILL_CLIPPED_BITMAP_HARD:
{
- assert(fill_side >= 0 && fill_side < 2);
+ matrix m = style.get_bitmap_matrix();
- m_current_styles[fill_side].disable();
+ bitmap_info_cairo* binfo
+ = static_cast<bitmap_info_cairo*>(style.get_bitmap_info());
+
+ if (!binfo) {
+ return NULL;
}
+ cairo_matrix_t mat;
+ init_cairo_matrix(&mat, m);
+
+ pattern = binfo->apply(&mat, fill_type);
+
+ break;
+ }
- void line_style_disable()
- // Don't draw a line on this path.
+ case SWF::FILL_SOLID:
{
- m_current_styles[LINE_STYLE].disable();
+ rgba c = cx.transform(style.get_color());
+ pattern = cairo_pattern_create_rgba (c.m_r / 255.0, c.m_g / 255.0,
+ c.m_b / 255.0, c.m_a / 255.0);
+ break;
}
+ } // switch
- void fill_style_color(int fill_side, const gnash::rgba& color)
- // Set fill style for the left interior of the shape. If
- // enable is false, turn off fill for the left interior.
- {
- assert(fill_side >= 0 && fill_side < 2);
+ return pattern;
-
m_current_styles[fill_side].set_color(m_current_cxform.transform(color));
}
-
- void line_style_color(const gnash::rgba& color)
- // Set the line style of the shape. If enable is false, turn
- // off lines for following curve segments.
+ void draw_outlines(const PathVec& path_vec, const std::vector<line_style>&
line_styles, const cxform& cx)
{
-
m_current_styles[LINE_STYLE].set_color(m_current_cxform.transform(color));
+ cairo_set_line_cap(_cr, CAIRO_LINE_CAP_ROUND); // TODO: move to init
+
+ for (PathVec::const_iterator it = path_vec.begin(), end = path_vec.end();
+ it != end; ++it) {
+ const path& cur_path = *it;
+ if (!cur_path.m_line) {
+ continue;
}
+ apply_line_style(line_styles[cur_path.m_line-1], cx);
- void fill_style_bitmap(int fill_side, const gnash::bitmap_info* bi,
const gnash::matrix& m, bitmap_wrap_mode wm)
- {
- assert(fill_side >= 0 && fill_side < 2);
- m_current_styles[fill_side].set_bitmap(bi, m, wm, m_current_cxform);
+ add_path(_cr, cur_path);
+
+ cairo_stroke(_cr);
+ }
}
- void line_style_width(float width)
- {
- if ( width == 1.0 ) // "hairline"
+ void apply_matrix(cairo_t* cr, const gnash::matrix& m)
+ // add user space transformation
{
- width = 20;
- }
- cairo_set_line_width(g_cr, width); // twips expected, it seems
+ cairo_matrix_t mat;
+ init_cairo_matrix(&mat, m);
+ cairo_transform(cr, &mat);
}
- void draw_mesh_strip(const void* coords, int vertex_count)
+
+ void
+ draw_subshape(PathVec& path_vec,
+ const matrix& mat,
+ const cxform& cx,
+ float pixel_scale,
+ const std::vector<cairo_pattern_t*>& fill_styles,
+ const std::vector<line_style>& line_styles)
{
- // Set up current style.
- m_current_styles[LEFT_STYLE].apply();
+ for (size_t i = 0; i < fill_styles.size(); ++i) {
+ PathPtrVec paths = get_paths_by_style(path_vec, i+1);
- cairo_save(g_cr);
- apply_matrix(m_current_matrix);
- // Draw the tris in cairo
- const int16_t* vertex = static_cast<const int16_t*>(coords);
- for (; vertex_count > 2; vertex_count--, vertex += 2)
- {
- cairo_move_to(g_cr, vertex[0], vertex[1]);
- cairo_line_to(g_cr, vertex[2], vertex[3]);
- cairo_line_to(g_cr, vertex[4], vertex[5]);
+ for (PathPtrVec::const_iterator iter = paths.begin(), final =
paths.end();
+ iter != final; ++iter) {
+ const path* cur_path = *iter;
+
+ add_path(_cr, *cur_path);
+
+ } // for (PathVec..)
+
+ if (paths.size()) {
+ cairo_set_source(_cr, fill_styles[i]);
+ cairo_fill(_cr);
}
- cairo_surface_t* mask = 0;
- if (m_cr_mask) mask = cairo_get_target(m_cr_mask);
+ } // for(std::vector<fill_style> ..)
- if (mask) cairo_mask_surface(g_cr, mask, 0, 0);
- else cairo_fill(g_cr);
- if (m_current_styles[LEFT_STYLE].needs_second_pass())
- {
- m_current_styles[LEFT_STYLE].apply_second_pass();
- for (; vertex_count > 2; vertex_count--, vertex += 2)
+
+ draw_outlines(path_vec, line_styles, cx);
+
+ }
+
+
+ std::vector<PathVec::const_iterator>
+ find_subshapes(const PathVec& path_vec)
{
- cairo_move_to(g_cr, vertex[0], vertex[1]);
- cairo_line_to(g_cr, vertex[2], vertex[3]);
- cairo_line_to(g_cr, vertex[4], vertex[5]);
+ std::vector<PathVec::const_iterator> subshapes;
+
+ PathVec::const_iterator it = path_vec.begin(),
+ end = path_vec.end();
+
+ subshapes.push_back(it);
+ ++it;
+
+ for (;it != end; ++it) {
+ const path& cur_path = *it;
+
+ if (cur_path.m_new_shape) {
+ subshapes.push_back(it);
}
- if (mask) cairo_mask_surface(g_cr, mask, 0, 0);
- else cairo_fill(g_cr);
- m_current_styles[LEFT_STYLE].cleanup_second_pass();
}
- cairo_restore(g_cr);
- }
+ subshapes.push_back(end);
+ return subshapes;
+ }
- void draw_line_strip(const void* coords, int vertex_count)
- // Draw the line strip formed by the sequence of points.
+ void draw_mask(const PathVec& path_vec)
{
- // Set up current style.
- m_current_styles[LINE_STYLE].apply();
+ for (PathVec::const_iterator it = path_vec.begin(), end = path_vec.end();
+ it != end; ++it) {
+ const path& cur_path = *it;
- cairo_save(g_cr);
- apply_matrix(m_current_matrix);
+ if (cur_path.m_fill0 || cur_path.m_fill1) {
+ _masks.back().push_back(cur_path);
+ }
+ }
+ }
- // Draw the line-strip in cairo
- const int16_t* vertex = static_cast<const int16_t*>(coords);
- cairo_move_to(g_cr, vertex[0], vertex[1]);
- for (vertex += 2; vertex_count > 1; vertex_count--, vertex += 2)
- cairo_line_to(g_cr, vertex[0], vertex[1]);
- cairo_stroke(g_cr);
+ void
+ add_paths(const PathVec& path_vec)
+ {
+ for (PathVec::const_iterator it = path_vec.begin(), end = path_vec.end();
+ it != end; ++it) {
+ const path& cur_path = *it;
- cairo_restore(g_cr);
+ add_path(_cr, cur_path);
+ }
}
+ /// Takes a path and translates it using the given matrix. The new path
+ /// is stored in paths_out.
+ /// Taken from render_handler_agg.cpp.
+ void apply_matrix_to_paths(const std::vector<path> &paths_in,
+ std::vector<path> &paths_out, const matrix& mat) {
- void draw_bitmap(
- const gnash::matrix& m,
- const gnash::bitmap_info* binfo,
- const gnash::rect& coords,
- const gnash::rect& /*uv_coords*/,
- const gnash::rgba& color)
- // Draw a rectangle textured with the given bitmap, with the
- // given color. Apply given transform; ignore any currently
- // set transforms.
- //
- // Intended for textured glyph rendering.
- {
- gnash::bitmap_info* nonconst_binfo =
const_cast<gnash::bitmap_info*>(binfo);
- bitmap_info_cairo* bi =
dynamic_cast<bitmap_info_cairo*>(nonconst_binfo);
- assert(bi);
+ int pcount, ecount;
+ int pno, eno;
- apply_color(color);
+ // copy path
+ paths_out = paths_in;
+ pcount = paths_out.size();
- gnash::point a, b, c, d;
- m.transform(&a, gnash::point(coords.get_x_min(),
coords.get_y_min()));
- m.transform(&b, gnash::point(coords.get_x_max(),
coords.get_y_min()));
- m.transform(&c, gnash::point(coords.get_x_max(),
coords.get_y_max()));
- m.transform(&d, gnash::point(coords.get_x_min(),
coords.get_y_max()));
+ for (pno=0; pno<pcount; pno++) {
- // FIXME!!! scaling and offset is wrong
- cairo_matrix_t mat;
- cairo_matrix_init_scale(&mat, coords.width(), coords.height());
- cairo_matrix_init_translate(&mat, coords.get_x_min(),
coords.get_y_min());
+ path &the_path = paths_out[pno];
+ point oldpnt(the_path.m_ax, the_path.m_ay);
+ point newpnt;
+ mat.transform(&newpnt, oldpnt);
+ the_path.m_ax = newpnt.m_x;
+ the_path.m_ay = newpnt.m_y;
- cairo_matrix_t new_mat;
- cairo_matrix_init(&new_mat, m.m_[0][0], m.m_[1][0], m.m_[0][1],
- m.m_[1][1], m.m_[0][2], m.m_[1][2]);
+ ecount = the_path.m_edges.size();
+ for (eno=0; eno<ecount; eno++) {
- cairo_matrix_multiply(&mat, &mat, &new_mat);
+ edge &the_edge = the_path.m_edges[eno];
- cairo_pattern_t* pattern = bi->m_pattern;
- cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
- cairo_pattern_set_matrix(pattern, &mat);
- cairo_set_source(g_cr, pattern);
+ oldpnt.m_x = the_edge.m_ax;
+ oldpnt.m_y = the_edge.m_ay;
+ mat.transform(&newpnt, oldpnt);
+ the_edge.m_ax = newpnt.m_x;
+ the_edge.m_ay = newpnt.m_y;
- cairo_save(g_cr);
- cairo_move_to(g_cr, a.m_x, a.m_y);
- cairo_line_to(g_cr, b.m_x, b.m_y);
- cairo_line_to(g_cr, c.m_x, c.m_y);
- cairo_line_to(g_cr, d.m_x, d.m_y);
- cairo_clip(g_cr);
- cairo_paint(g_cr);
- cairo_restore(g_cr);
- }
+ oldpnt.m_x = the_edge.m_cx;
+ oldpnt.m_y = the_edge.m_cy;
+ mat.transform(&newpnt, oldpnt);
+ the_edge.m_cx = newpnt.m_x;
+ the_edge.m_cy = newpnt.m_y;
- void begin_submit_mask()
- {
- if (m_cr_mask) cairo_destroy(m_cr_mask);
- cairo_surface_t* mask = cairo_image_surface_create(
- CAIRO_FORMAT_A8, m_view_width, m_view_height);
- m_cr_mask = cairo_create(mask);
- cairo_surface_destroy(mask);
+ }
- // Start drawing to the mask
- g_cr = m_cr_mask;
}
- void end_submit_mask()
- {
- // Finished with the mask. Now draw to output
- g_cr = (g_cr_output ? g_cr_output : m_cr_dummy);
}
- void disable_mask()
- {
- // Clean up any mask
- if (m_cr_mask)
+
+ virtual void draw_shape_character(shape_character_def *def,
+ const matrix& mat,
+ const cxform& cx,
+ float pixel_scale,
+ const std::vector<fill_style>& fill_styles,
+ const std::vector<line_style>& line_styles)
{
- cairo_destroy(m_cr_mask);
- m_cr_mask = 0;
- // Prepare to draw to output
- g_cr = (g_cr_output ? g_cr_output : m_cr_dummy);
- }
+ const PathVec& path_vec = def->get_paths();
+
+ if (!path_vec.size()) {
+ return;
}
- // Returns the format the current renderer wants videoframes in.
- int videoFrameFormat() {
- return RGB;
+ cairo_set_fill_rule(_cr, CAIRO_FILL_RULE_EVEN_ODD); // TODO: Move to init
+
+ if (_drawing_mask) {
+ PathVec scaled_path_vec;
+
+ apply_matrix_to_paths(path_vec, scaled_path_vec, mat);
+ draw_mask(scaled_path_vec);
+ return;
}
- /// Draws the video frames
- void drawVideoFrame(image::image_base* baseframe, const matrix* m,
const rect* bounds){
- // Obtain on-stage bounding rectangle
- gnash::point a, b, c, d;
- m->transform(&a, gnash::point(bounds->get_x_min(),
bounds->get_y_min()));
- m->transform(&b, gnash::point(bounds->get_x_max(),
bounds->get_y_min()));
- m->transform(&c, gnash::point(bounds->get_x_max(),
bounds->get_y_max()));
- m->transform(&d, gnash::point(bounds->get_x_min(),
bounds->get_y_max()));
+ cairo_matrix_t old_matrix;
+ cairo_get_matrix(_cr, &old_matrix);
- // Extract frame attributes
- image::rgb* frame = static_cast<image::rgb*>(baseframe);
- int w = frame->width();
- int h = frame->height();
+ apply_matrix(_cr, mat);
- // Compute bounding rectangle size relative to video object
- double w_scale = bounds->width() / w;
- double h_scale = bounds->height() / h;
- // Fit video to bounding rectangle
- cairo_matrix_t mat;
- cairo_matrix_init_scale(&mat, w_scale, h_scale);
- cairo_matrix_translate(&mat,
- bounds->get_x_min(), bounds->get_y_min());
+ std::vector<PathVec::const_iterator> subshapes = find_subshapes(path_vec);
- // Now apply transformation to video
- cairo_matrix_t frame_mat;
- cairo_matrix_init(&frame_mat,
- m->m_[0][0], m->m_[1][0],
- m->m_[0][1], m->m_[1][1],
- m->m_[0][2], m->m_[1][2]);
- cairo_matrix_multiply(&mat, &mat, &frame_mat);
+ std::vector<cairo_pattern_t*> fill_styles_cairo
+ = build_cairo_styles(fill_styles, cx, mat);
- // Inverse the matrix for pattern space
- cairo_matrix_invert(&mat);
+ for (size_t i = 0; i < subshapes.size()-1; ++i) {
+ PathVec subshape_paths;
- // Convert RGB frame to cairo format
- int buf_size = w * h * 4;
- if (m_video_bufsize < buf_size)
- {
- if (m_video_buffer) delete [] m_video_buffer;
- m_video_buffer = new unsigned char[buf_size];
- m_video_bufsize = buf_size;
+ if (subshapes[i] != subshapes[i+1]) {
+ subshape_paths = PathVec(subshapes[i], subshapes[i+1]);
+ } else {
+ subshape_paths.push_back(*subshapes[i]);
}
- rgb_to_cairo_rgb24(m_video_buffer, frame);
- // Create a pattern from the the RGB frame
- cairo_surface_t* surface = cairo_image_surface_create_for_data(
- m_video_buffer, CAIRO_FORMAT_RGB24, w, h, w * 4);
- cairo_pattern_t* pattern =
cairo_pattern_create_for_surface(surface);
- cairo_pattern_set_extend(pattern, CAIRO_EXTEND_NONE);
- cairo_pattern_set_matrix(pattern, &mat);
+ draw_subshape(subshape_paths, mat, cx, pixel_scale, fill_styles_cairo,
+ line_styles);
+ }
- // Draw the frame now
- cairo_save(g_cr);
- cairo_set_source(g_cr, pattern);
- cairo_move_to(g_cr, a.m_x, a.m_y);
- cairo_line_to(g_cr, b.m_x, b.m_y);
- cairo_line_to(g_cr, c.m_x, c.m_y);
- cairo_line_to(g_cr, d.m_x, d.m_y);
- cairo_clip(g_cr);
- cairo_paint(g_cr);
- cairo_restore(g_cr);
+ destroy_cairo_patterns(fill_styles_cairo);
- // Clean up
+ cairo_set_matrix(_cr, &old_matrix);
+ }
+
+ void
+ destroy_cairo_patterns(std::vector<cairo_pattern_t*>& patterns)
+ {
+ for (std::vector<cairo_pattern_t*>::iterator it = patterns.begin(),
+ end = patterns.end(); it != end; ++it) {
+ cairo_pattern_t* pattern = *it;
+ if (pattern && cairo_pattern_get_type(pattern) !=
+ CAIRO_PATTERN_TYPE_SURFACE) {
cairo_pattern_destroy(pattern);
- cairo_surface_destroy(surface);
+ }
+ }
}
-}; // end class render_handler_cairo
+ virtual void draw_glyph(shape_character_def *def, const matrix& mat,
+ const rgba& color, float pixel_scale)
+ {
+ cxform dummy_cx;
+ std::vector<fill_style> glyph_fs;
-// bitmap_info_cairo implementation
+ fill_style coloring;
+ coloring.setSolid(color);
-bitmap_info_cairo::bitmap_info_cairo()
-// Make a placeholder bitmap_info. Must be filled in later before using.
-{
- m_buffer = 0;
- m_image = 0;
- m_original_width = 0;
- m_original_height = 0;
-}
+ glyph_fs.push_back(coloring);
+ const PathVec& path_vec = def->get_paths();
-bitmap_info_cairo::bitmap_info_cairo(int width, int height, uint8_t* data)
-// Initialize this bitmap_info to an alpha image
-// containing the specified data (1 byte per texel).
-{
- assert(width > 0);
- assert(height > 0);
- assert(data);
-
- // Allocate output buffer
- int buf_size = width * height;
- m_buffer = new unsigned char[buf_size];
-
- // Copy alpha data
- memcpy(m_buffer, data, buf_size);
-
- // Create the image
- m_original_width = width;
- m_original_height = height;
- m_image = cairo_image_surface_create_for_data(
- m_buffer, CAIRO_FORMAT_A8, width, height, width);
- m_pattern = cairo_pattern_create_for_surface(m_image);
-}
+ std::vector<line_style> dummy_ls;
+ draw_shape_character(def, mat, dummy_cx, pixel_scale, glyph_fs, dummy_ls);
+ }
+ virtual bool allow_glyph_textures()
+ {
+ return false;
+ }
-bitmap_info_cairo::bitmap_info_cairo(image::rgb* im)
-// Version of the constructor that takes an RGB image.
-{
- assert(im);
+ void
+ set_context(cairo_t* context)
+ {
+ if (context == _cr) {
+ return;
+ }
+ if (cairo_get_reference_count(_cr)) {
+ cairo_destroy(_cr);
+ }
+ _cr = context;
+ }
- // Convert 24-bit BGR data to 32-bit RGB
- int buf_size = im->width() * im->height() * 4;
- m_buffer = new unsigned char[buf_size];
- rgb_to_cairo_rgb24(m_buffer, im);
+ void
+ init_cairo_matrix(cairo_matrix_t* cairo_matrix, const matrix& gnash_matrix)
+ {
+ cairo_matrix_init(cairo_matrix,
+ gnash_matrix.m_[0][0], gnash_matrix.m_[1][0],
+ gnash_matrix.m_[0][1], gnash_matrix.m_[1][1],
+ gnash_matrix.m_[0][2], gnash_matrix.m_[1][2]);
+ }
- // Create the cairo image
- m_original_width = im->width();
- m_original_height = im->height();
- m_image = cairo_image_surface_create_for_data(m_buffer,
- CAIRO_FORMAT_RGB24, im->width(), im->height(), im->width() * 4);
- m_pattern = cairo_pattern_create_for_surface(m_image);
-}
+private:
+ /// The cairo context.
+ cairo_t* _cr;
+ boost::scoped_array<uint8_t> _video_buffer;
+ std::vector<PathVec> _masks;
+ size_t _video_bufsize;
+ bool _drawing_mask;
+}; // class render_handler_cairo
-bitmap_info_cairo::bitmap_info_cairo(image::rgba* im)
-// Version of the constructor that takes an image with alpha.
-{
- assert(im);
- // Allocate output buffer
- size_t buf_size = im->size();
- // TODO: who owns this buffer ??
- m_buffer = new unsigned char[buf_size];
- rgba_to_cairo_argb32(m_buffer, im);
-
- // Create the image
- m_original_width = im->width();
- m_original_height = im->height();
- m_image = cairo_image_surface_create_for_data(m_buffer,
- CAIRO_FORMAT_ARGB32, im->width(), im->height(), im->width() * 4);
- m_pattern = cairo_pattern_create_for_surface(m_image);
-}
+
+
+namespace renderer {
+
+
+namespace cairo
+{
DSOEXPORT render_handler*
create_handler()
@@ -761,20 +892,15 @@
}
DSOEXPORT void
-set_handle(cairo_t* handle)
+set_context(render_handler* handler, cairo_t* context)
{
- g_cr_output = handle;
+ render_handler_cairo* cairo_handler =
static_cast<render_handler_cairo*>(handler);
+ cairo_handler->set_context(context);
}
-
-} // namespace gnash::renderer::cairo
-} // namespace gnash::renderer
+} // namespace cairo
+} // namespace renderer
} // namespace gnash
-// Local Variables:
-// mode: C++
-// indent-tabs-mode: t
-// End:
-/* vim: set cindent tabstop=8 softtabstop=4 shiftwidth=4: */
Index: backend/render_handler_cairo.h
===================================================================
RCS file: /sources/gnash/gnash/backend/render_handler_cairo.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -b -r1.6 -r1.7
--- backend/render_handler_cairo.h 1 Jul 2007 10:53:48 -0000 1.6
+++ backend/render_handler_cairo.h 18 Oct 2007 09:05:40 -0000 1.7
@@ -18,12 +18,14 @@
//
//
-/* $Id: render_handler_cairo.h,v 1.6 2007/07/01 10:53:48 bjacques Exp $ */
+/* $Id: render_handler_cairo.h,v 1.7 2007/10/18 09:05:40 bjacques Exp $ */
#ifndef BACKEND_RENDER_HANDLER_CAIRO_H
#define BACKEND_RENDER_HANDLER_CAIRO_H
#include "tu_config.h"
+#include <cairo/cairo.h>
+#include "render_handler.h"
namespace gnash {
namespace renderer {
@@ -35,7 +37,7 @@
gnash::render_handler* create_handler();
/// Make sure to call this before starting display
-void set_handle(cairo_t* handle);
+void set_context(render_handler* handler, cairo_t* context);
} // namespace gnash::renderer::cairo
} // namespace gnash::renderer
Index: gui/gtk_glue_cairo.cpp
===================================================================
RCS file: /sources/gnash/gnash/gui/gtk_glue_cairo.cpp,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -b -r1.11 -r1.12
--- gui/gtk_glue_cairo.cpp 1 Jul 2007 10:54:02 -0000 1.11
+++ gui/gtk_glue_cairo.cpp 18 Oct 2007 09:05:40 -0000 1.12
@@ -59,7 +59,9 @@
render_handler*
GtkCairoGlue::createRenderHandler()
{
- return renderer::cairo::create_handler();
+ _renderer = renderer::cairo::create_handler();
+
+ return _renderer;
}
void
@@ -80,18 +82,25 @@
if (!_drawing_area) return;
// Create cairo handle for output window
- if (_cairo_handle) cairo_destroy(_cairo_handle);
+ if (_cairo_handle) {
+ assert(cairo_get_reference_count(_cairo_handle));
+ cairo_destroy(_cairo_handle);
+ }
_cairo_handle = gdk_cairo_create(_drawing_area->window);
assert(_cairo_handle);
// Create offscreen image for rendering
- if (_cairo_offscreen) cairo_destroy(_cairo_offscreen);
+ if (_cairo_offscreen) {
+ assert(cairo_get_reference_count(_cairo_offscreen));
+ cairo_destroy(_cairo_offscreen);
+ }
+
cairo_surface_t* surface = cairo_image_surface_create(
CAIRO_FORMAT_RGB24, event->width, event->height);
_cairo_offscreen = cairo_create(surface);
- assert(_cairo_offscreen);
cairo_surface_destroy(surface);
- renderer::cairo::set_handle(_cairo_offscreen);
+
+ renderer::cairo::set_context(_renderer, _cairo_offscreen);
}
Index: gui/gtk_glue_cairo.h
===================================================================
RCS file: /sources/gnash/gnash/gui/gtk_glue_cairo.h,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -b -r1.12 -r1.13
--- gui/gtk_glue_cairo.h 9 Jul 2007 07:26:44 -0000 1.12
+++ gui/gtk_glue_cairo.h 18 Oct 2007 09:05:40 -0000 1.13
@@ -45,6 +45,7 @@
private:
cairo_t *_cairo_handle;
cairo_t *_cairo_offscreen;
+ render_handler* _renderer;
};
} // namespace gnash
- [Gnash-commit] gnash backend/render_handler_cairo.cpp backend/...,
Bastiaan Jacques <=