Index: core/cross/cairo/texture_cairo.cc |
=================================================================== |
--- core/cross/cairo/texture_cairo.cc (revision 72525) |
+++ core/cross/cairo/texture_cairo.cc (working copy) |
@@ -1,5 +1,5 @@ |
/* |
- * Copyright 2010, Google Inc. |
+ * Copyright 2011, Google Inc. |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
@@ -34,6 +34,9 @@ |
// Texture Class for handling Cairo Rendering Mode. |
#include "core/cross/cairo/texture_cairo.h" |
+ |
+#include <string.h> |
+ |
#include "core/cross/cairo/renderer_cairo.h" |
namespace o3d { |
@@ -62,7 +65,6 @@ |
TextureCairo::TextureCairo(ServiceLocator* service_locator, |
cairo_surface_t* image_surface, |
- cairo_t* image_surface_context, |
Texture::Format format, |
int levels, |
int width, |
@@ -76,8 +78,7 @@ |
enable_render_surfaces), |
renderer_(static_cast<RendererCairo*>( |
service_locator->GetService<Renderer>())), |
- image_surface_(image_surface), |
- image_surface_context_(image_surface_context) { |
+ image_surface_(image_surface) { |
DLOG(INFO) << "Texture2D Construct"; |
DCHECK_NE(format, Texture::UNKNOWN_FORMAT); |
} |
@@ -91,7 +92,6 @@ |
bool enable_render_surfaces) { |
int cairo_format = CairoFormatFromO3DFormat(format); |
cairo_surface_t* image_surface; |
- cairo_t* image_surface_context; |
cairo_status_t status; |
if (-1 == cairo_format) { |
DLOG(ERROR) << "Texture format " << format << " not supported by Cairo"; |
@@ -106,27 +106,15 @@ |
DLOG(ERROR) << "Error creating Cairo image surface: " << status; |
goto fail1; |
} |
- image_surface_context = cairo_create(image_surface); |
- status = cairo_status(image_surface_context); |
- if (CAIRO_STATUS_SUCCESS != status) { |
- DLOG(ERROR) << "Error creating Cairo image surface draw context: " |
- << status; |
- goto fail2; |
- } |
- cairo_set_operator(image_surface_context, CAIRO_OPERATOR_SOURCE); |
- |
return new TextureCairo(service_locator, |
image_surface, |
- image_surface_context, |
format, |
levels, |
width, |
height, |
enable_render_surfaces); |
- fail2: |
- cairo_destroy(image_surface_context); |
fail1: |
cairo_surface_destroy(image_surface); |
fail0: |
@@ -140,7 +128,6 @@ |
} |
TextureCairo::~TextureCairo() { |
- cairo_destroy(image_surface_context_); |
cairo_surface_destroy(image_surface_); |
renderer_ = NULL; |
DLOG(INFO) << "Texture2DCairo Destruct"; |
@@ -152,7 +139,7 @@ |
unsigned dst_top, |
unsigned src_width, |
unsigned src_height, |
- const void* src_data, |
+ const void* src_data_void, |
int src_pitch) { |
DLOG(INFO) << "Texture2DCairo SetRect"; |
@@ -161,27 +148,49 @@ |
return; |
} |
- // Create image surface to represent the source. |
- cairo_surface_t* source_image_surface = cairo_image_surface_create_for_data( |
- const_cast<unsigned char*>( |
- static_cast<const unsigned char*>(src_data)), |
- cairo_image_surface_get_format(image_surface_), |
- src_width, |
- src_height, |
- src_pitch); |
+ cairo_surface_flush(image_surface_); |
- // Set that surface as the source for paint operations to our texture. |
- cairo_set_source_surface(image_surface_context_, |
- source_image_surface, |
- dst_left, |
- dst_top); |
+ const unsigned char* src_data = reinterpret_cast<const unsigned char*>( |
+ src_data_void); |
- // Paint to the texture. This copies the data. |
- cairo_paint(image_surface_context_); |
+ unsigned char* dst_data = cairo_image_surface_get_data(image_surface_); |
- // Discard our reference to the source surface. |
- cairo_surface_destroy(source_image_surface); |
+ int dst_pitch = cairo_image_surface_get_stride(image_surface_); |
+ dst_data += dst_top * dst_pitch + dst_left * 4; |
+ |
+ if (ARGB8 == format()) { |
+ // Cairo supports only premultiplied alpha, but we get the images as |
+ // non-premultiplied alpha, so we have to convert. |
+ for (unsigned i = 0; i < src_height; ++i) { |
+ for (unsigned j = 0; j < src_width; ++j) { |
+ // NOTE: This assumes a little-endian architecture (e.g., x86). It works |
+ // for RGBA or BGRA where alpha is in byte 3. |
+ // Get alpha. |
+ uint8 alpha = src_data[3]; |
+ // Convert each colour. |
+ for (int i = 0; i < 3; i++) { |
+ dst_data[i] = (src_data[i] * alpha + 128U) / 255U; |
+ } |
+ // Copy alpha. |
+ dst_data[3] = alpha; |
+ src_data += 4; |
+ dst_data += 4; |
+ } |
+ src_data += src_pitch - src_width * 4; |
+ dst_data += dst_pitch - src_width * 4; |
+ } |
+ } else { |
+ // Just copy the data. |
+ for (unsigned i = 0; i < src_height; ++i) { |
+ memcpy(dst_data, src_data, src_width * 4); |
+ src_data += src_pitch; |
+ dst_data += dst_pitch; |
+ } |
+ } |
+ |
+ cairo_surface_mark_dirty(image_surface_); |
+ |
TextureUpdated(); |
} |