diff options
author | tschmelcher@chromium.org <tschmelcher@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-01-20 21:41:51 +0000 |
---|---|---|
committer | tschmelcher@chromium.org <tschmelcher@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-01-20 21:41:51 +0000 |
commit | ee383ec41ac64fa524998fed735f5cafa1b11214 (patch) | |
tree | 8c351d77756b31b87de26e69d0672b6a7708d230 /o3d | |
parent | 1d0bb92191e7c495f29ef71bedda2ef4c72eb8aa (diff) | |
download | chromium_src-ee383ec41ac64fa524998fed735f5cafa1b11214.zip chromium_src-ee383ec41ac64fa524998fed735f5cafa1b11214.tar.gz chromium_src-ee383ec41ac64fa524998fed735f5cafa1b11214.tar.bz2 |
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
Diffstat (limited to 'o3d')
-rw-r--r-- | o3d/core/cross/cairo/layer.cc | 6 | ||||
-rw-r--r-- | o3d/core/cross/cairo/layer.h | 50 | ||||
-rw-r--r-- | o3d/core/cross/cairo/pattern.cc | 11 | ||||
-rw-r--r-- | o3d/core/cross/cairo/pattern.h | 10 | ||||
-rw-r--r-- | o3d/core/cross/cairo/renderer_cairo.cc | 77 | ||||
-rw-r--r-- | o3d/core/cross/cairo/renderer_cairo.h | 4 | ||||
-rw-r--r-- | o3d/plugin/idl/layer.idl | 35 | ||||
-rw-r--r-- | o3d/plugin/idl/pattern.idl | 18 |
8 files changed, 183 insertions, 28 deletions
diff --git a/o3d/core/cross/cairo/layer.cc b/o3d/core/cross/cairo/layer.cc index 7317dc1..943308f 100644 --- a/o3d/core/cross/cairo/layer.cc +++ b/o3d/core/cross/cairo/layer.cc @@ -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); diff --git a/o3d/core/cross/cairo/layer.h b/o3d/core/cross/cairo/layer.h index 8e81206..df2832b 100644 --- a/o3d/core/cross/cairo/layer.h +++ b/o3d/core/cross/cairo/layer.h @@ -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 diff --git a/o3d/core/cross/cairo/pattern.cc b/o3d/core/cross/cairo/pattern.cc index 8a59d3e..93c7582 100644 --- a/o3d/core/cross/cairo/pattern.cc +++ b/o3d/core/cross/cairo/pattern.cc @@ -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) { diff --git a/o3d/core/cross/cairo/pattern.h b/o3d/core/cross/cairo/pattern.h index 8828c6d..fbb91d3 100644 --- a/o3d/core/cross/cairo/pattern.h +++ b/o3d/core/cross/cairo/pattern.h @@ -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); diff --git a/o3d/core/cross/cairo/renderer_cairo.cc b/o3d/core/cross/cairo/renderer_cairo.cc index 1cdc7e1..dabf61b 100644 --- a/o3d/core/cross/cairo/renderer_cairo.cc +++ b/o3d/core/cross/cairo/renderer_cairo.cc @@ -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. - cairo_save(current_drawing); - - // Preparing and updating the Layer. Layer* cur = *i; + if (!cur->ShouldPaint()) continue; + Pattern* pattern = cur->pattern(); - if (!pattern) { - // Skip layers with no pattern assigned. - continue; - } - // Masking areas for other scene. + // Save the current drawing state. + cairo_save(current_drawing); + + // 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); - cairo_translate(current_drawing, cur->x(), cur->y()); + // 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; + + 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 the state with no mask. + // 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); } } diff --git a/o3d/core/cross/cairo/renderer_cairo.h b/o3d/core/cross/cairo/renderer_cairo.h index e985dc1..ced0d5e 100644 --- a/o3d/core/cross/cairo/renderer_cairo.h +++ b/o3d/core/cross/cairo/renderer_cairo.h @@ -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. diff --git a/o3d/plugin/idl/layer.idl b/o3d/plugin/idl/layer.idl index 3a479ba..ef28380 100644 --- a/o3d/plugin/idl/layer.idl +++ b/o3d/plugin/idl/layer.idl @@ -39,12 +39,40 @@ namespace o2d { %] [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 diff --git a/o3d/plugin/idl/pattern.idl b/o3d/plugin/idl/pattern.idl index c511809..bed3daf 100644 --- a/o3d/plugin/idl/pattern.idl +++ b/o3d/plugin/idl/pattern.idl @@ -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 |