O2D:
- 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:
o3d
core
plugin
@ -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
|
||||
|
Reference in New Issue
Block a user