0
- New APIs:
  - Add a "visible" property to the Layer class to mimick the visible property of the Transform class.
  - Add a method to set an affine transform on Pattern objects so that texture patterns can be transformed independently from the Layers that use them.
  - Add a "paint operators" API for Layers and define four operators (currently only three of them implemented). The previous hard-coded behaviour was equivalent to the BLEND_WITH_TRANSPARENCY operator.
- Fixes:
  - Replace the "mask" nomenclature with "clip", which is a more standard name.
  - Don't clip alpha-blended layers.
  - Restrict Layer painting to the rectangle defined by the attributes.
  - Set default alpha value to 0.0 instead of 1.0 to match what JavaScript expects.

TEST=loaded O2D and verified all new functionality is working
BUG=none

Review URL: http://codereview.chromium.org/6255003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@72006 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
tschmelcher@chromium.org
2011-01-20 21:41:51 +00:00
parent 1d0bb92191
commit ee383ec41a
8 changed files with 184 additions and 29 deletions

@ -50,14 +50,16 @@ Layer::~Layer() {
Layer::Layer(ServiceLocator* service_locator)
: ObjectBase(service_locator),
alpha_(1.0),
visible_(true),
alpha_(0.0),
x_(0),
y_(0),
z_(0),
width_(0),
height_(0),
scale_x_(1.0),
scale_y_(1.0) {
scale_y_(1.0),
paint_operator_(BLEND) {
DLOG(INFO) << "Create Layer";
Renderer* renderer = service_locator->GetService<Renderer>();
RendererCairo* renderer_cairo = down_cast<RendererCairo*>(renderer);

@ -50,8 +50,17 @@ class Layer : public ObjectBase {
public:
typedef SmartPointer<Layer> Ref;
enum PaintOperator {
BLEND,
BLEND_WITH_TRANSPARENCY,
COPY,
COPY_WITH_FADING,
};
virtual ~Layer();
// Methods exposed to JS.
Pattern* pattern() const {
return pattern_;
}
@ -60,6 +69,14 @@ class Layer : public ObjectBase {
pattern_ = Pattern::Ref(pattern);
}
bool visible() const {
return visible_;
}
void set_visible(bool visible) {
visible_ = visible;
}
double alpha() const {
return alpha_;
}
@ -124,6 +141,30 @@ class Layer : public ObjectBase {
scale_y_ = scale_y;
}
PaintOperator paint_operator() const {
return paint_operator_;
}
void set_paint_operator(PaintOperator paint_operator) {
paint_operator_ = paint_operator;
}
// Methods not exposed to JS.
// Whether we should currently paint this layer.
bool ShouldPaint() const {
return visible() && pattern() != NULL;
}
// Whether this layer should currently clip content behind it (i.e.,
// prevent it from being drawn in the first place).
bool ShouldClip() const {
// When alpha blending is used we cannot clip the background because our
// content will be blended with it.
return ShouldPaint() &&
(paint_operator() == COPY || paint_operator() == COPY_WITH_FADING);
}
private:
explicit Layer(ServiceLocator* service_locator);
@ -133,7 +174,11 @@ class Layer : public ObjectBase {
// The pattern used to paint this Layer.
Pattern::Ref pattern_;
// Transparancy of this layer.
// Whether this layer should be visible or not.
bool visible_;
// The transparency for the BLEND_WITH_TRANSPARENCY operator or the fading for
// the COPY_WITH_FADING operator.
double alpha_;
// The x coordinate of the top-left corner of this layer.
@ -157,6 +202,9 @@ class Layer : public ObjectBase {
// A scaling factor to apply to the pattern's y-axis.
double scale_y_;
// The paint operator to use for painting this Layer.
PaintOperator paint_operator_;
O3D_DECL_CLASS(Layer, ObjectBase)
}; // Layer

@ -73,6 +73,17 @@ Pattern::~Pattern() {
cairo_pattern_destroy(pattern_);
}
void Pattern::SetAffineTransform(double xx,
double yx,
double xy,
double yy,
double x0,
double y0) {
cairo_matrix_t matrix;
cairo_matrix_init(&matrix, xx, yx, xy, yy, x0, y0);
cairo_pattern_set_matrix(pattern_, &matrix);
}
Pattern::Pattern(ServiceLocator* service_locator, cairo_pattern_t* pattern)
: ObjectBase(service_locator),
pattern_(pattern) {

@ -69,6 +69,16 @@ class Pattern : public ObjectBase {
cairo_pattern_t* pattern() const { return pattern_; }
// Set the affine transformation matrix that maps user space to pattern space.
// The default matrix is the identity matrix, so that no transformation
// occurs.
void SetAffineTransform(double xx,
double yx,
double xy,
double yy,
double x0,
double y0);
private:
Pattern(ServiceLocator* service_locator, cairo_pattern_t* pattern);

@ -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
@ -95,32 +95,64 @@ void RendererCairo::Paint() {
// Core process of painting.
for (LayerList::iterator i = layer_list_.begin();
i != layer_list_.end(); i++) {
// Put the state with no mask to the stack.
Layer* cur = *i;
if (!cur->ShouldPaint()) continue;
Pattern* pattern = cur->pattern();
// Save the current drawing state.
cairo_save(current_drawing);
// Preparing and updating the Layer.
Layer* cur = *i;
Pattern* pattern = cur->pattern();
if (!pattern) {
// Skip layers with no pattern assigned.
continue;
}
// Masking areas for other scene.
// Clip areas that will be obscured anyway.
LayerList::iterator start_mask_it = i;
start_mask_it++;
MaskArea(current_drawing, start_mask_it);
ClipArea(current_drawing, start_mask_it);
// Define the region to fill.
cairo_rectangle(current_drawing,
cur->x(),
cur->y(),
cur->width(),
cur->height());
// Transform the pattern to fit into the fill region.
cairo_translate(current_drawing, cur->x(), cur->y());
cairo_scale(current_drawing, cur->scale_x(), cur->scale_y());
// Painting the image to the surface.
// Set source pattern.
cairo_set_source(current_drawing, pattern->pattern());
cairo_paint_with_alpha(current_drawing, cur->alpha());
// Paint the pattern to the off-screen surface.
switch (cur->paint_operator()) {
case Layer::BLEND:
cairo_fill(current_drawing);
break;
// Restore to the state with no mask.
case Layer::BLEND_WITH_TRANSPARENCY:
{
cairo_pattern_t* mask = cairo_pattern_create_rgba(0.0,
0.0,
0.0,
cur->alpha());
cairo_mask(current_drawing, mask);
cairo_pattern_destroy(mask);
}
break;
// TODO(tschmelcher): COPY_WITH_FADING is not implemented yet. For now
// we treat it the same as COPY.
case Layer::COPY_WITH_FADING:
case Layer::COPY:
// Set Cairo to copy the pattern's alpha content instead of blending.
cairo_set_operator(current_drawing, CAIRO_OPERATOR_SOURCE);
cairo_fill(current_drawing);
break;
default:
DCHECK(false);
}
// Restore to a clean state.
cairo_restore(current_drawing);
}
@ -136,7 +168,7 @@ void RendererCairo::Paint() {
void RendererCairo::PaintBackground(cairo_t* cr) {
cairo_save(cr);
MaskArea(cr, layer_list_.begin());
ClipArea(cr, layer_list_.begin());
cairo_rectangle(cr, 0, 0, display_width(), display_height());
cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
@ -144,19 +176,20 @@ void RendererCairo::PaintBackground(cairo_t* cr) {
cairo_restore(cr);
}
void RendererCairo::MaskArea(cairo_t* cr, LayerList::iterator it) {
void RendererCairo::ClipArea(cairo_t* cr, LayerList::iterator it) {
cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
for (LayerList::iterator i = it; i != layer_list_.end(); i++) {
// Preparing and updating the Layer.
Layer* cur_mask = *i;
Layer* cur = *i;
if (!cur->ShouldClip()) continue;
cairo_rectangle(cr, 0, 0, display_width(), display_height());
cairo_rectangle(cr,
cur_mask->x(),
cur_mask->y(),
cur_mask->width(),
cur_mask->height());
cur->x(),
cur->y(),
cur->width(),
cur->height());
cairo_clip(cr);
}
}

@ -218,8 +218,8 @@ class RendererCairo : public Renderer {
float min_z,
float max_z);
// Mask the area of the current layer that will collide with other images.
void MaskArea(cairo_t* cr, LayerList::iterator it);
// Clip the area of the current layer that will collide with other images.
void ClipArea(cairo_t* cr, LayerList::iterator it);
// Paint the background with black color.
// TODO(fransiskusx): Support changing the background color.

@ -38,13 +38,41 @@ namespace o2d {
particular Pattern, with automatic clipping based on stacking order.
%]
[nocpp, include="core/cross/cairo/layer.h"] class Layer : ObjectBase {
%[
Available painting operators.
\var PaintOperator,
\li BLEND, Alpha-blend the Pattern on top of lower Layers based on its
alpha channel. (Default)
\li BLEND_WITH_TRANSPARENCY, Like BLEND, but scale the alpha channel down
based on the alpha property of the Layer as an
additional fractional transparency.
\li COPY, Copy the colour content of the Pattern directly to the
destination, ignoring the alpha channel.
\li COPY_WITH_FADING, Like COPY, but fade the colour to black based on the
alpha property of the Layer as an additional
fractional brightness.
%]
enum PaintOperator {
BLEND,
BLEND_WITH_TRANSPARENCY,
COPY,
COPY_WITH_FADING
};
%[
The Pattern used to paint this Layer.
%]
[getter, setter] Pattern? pattern;
%[
Transparancy of this layer.
Whether this layer should be visible or not.
%]
[getter, setter] bool visible;
%[
The transparency for the BLEND_WITH_TRANSPARENCY operator or the fading for
the COPY_WITH_FADING operator.
%]
[getter, setter] double alpha;
@ -82,6 +110,11 @@ namespace o2d {
A scaling factor to apply to the pattern's y-axis.
%]
[getter, setter] double scale_y;
%[
The paint operator to use for painting this Layer.
%]
[getter, setter] PaintOperator paint_operator;
}; // Layer
} // namespace o2d

@ -75,6 +75,24 @@ namespace o2d {
double green,
double blue,
double alpha);
%[
Set the affine transformation matrix that maps user space to pattern space.
The default matrix is the identity matrix, so that no transformation occurs.
\param xx xx component of the affine transformation
\param yx yx component of the affine transformation
\param xy xy component of the affine transformation
\param yy yy component of the affine transformation
\param x0 X translation component of the affine transformation
\param y0 Y translation component of the affine transformation
%]
void SetAffineTransform(double xx,
double yx,
double xy,
double yy,
double x0,
double y0);
}; // Pattern
} // namespace o2d