1 // Copyright 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "cc/quads/texture_draw_quad.h" 6 7 #include "base/logging.h" 8 #include "base/values.h" 9 #include "cc/base/math_util.h" 10 #include "ui/gfx/vector2d_f.h" 11 12 namespace cc { 13 14 TextureDrawQuad::TextureDrawQuad() 15 : resource_id(0), 16 premultiplied_alpha(false), 17 background_color(SK_ColorTRANSPARENT), 18 flipped(false) { 19 this->vertex_opacity[0] = 0.f; 20 this->vertex_opacity[1] = 0.f; 21 this->vertex_opacity[2] = 0.f; 22 this->vertex_opacity[3] = 0.f; 23 } 24 25 scoped_ptr<TextureDrawQuad> TextureDrawQuad::Create() { 26 return make_scoped_ptr(new TextureDrawQuad); 27 } 28 29 void TextureDrawQuad::SetNew(const SharedQuadState* shared_quad_state, 30 gfx::Rect rect, gfx::Rect opaque_rect, 31 unsigned resource_id, bool premultiplied_alpha, 32 gfx::PointF uv_top_left, 33 gfx::PointF uv_bottom_right, 34 SkColor background_color, 35 const float vertex_opacity[4], 36 bool flipped) { 37 gfx::Rect visible_rect = rect; 38 bool needs_blending = vertex_opacity[0] != 1.0f || vertex_opacity[1] != 1.0f 39 || vertex_opacity[2] != 1.0f || vertex_opacity[3] != 1.0f; 40 DrawQuad::SetAll(shared_quad_state, DrawQuad::TEXTURE_CONTENT, rect, 41 opaque_rect, visible_rect, needs_blending); 42 this->resource_id = resource_id; 43 this->premultiplied_alpha = premultiplied_alpha; 44 this->uv_top_left = uv_top_left; 45 this->uv_bottom_right = uv_bottom_right; 46 this->background_color = background_color; 47 this->vertex_opacity[0] = vertex_opacity[0]; 48 this->vertex_opacity[1] = vertex_opacity[1]; 49 this->vertex_opacity[2] = vertex_opacity[2]; 50 this->vertex_opacity[3] = vertex_opacity[3]; 51 this->flipped = flipped; 52 } 53 54 void TextureDrawQuad::SetAll(const SharedQuadState* shared_quad_state, 55 gfx::Rect rect, gfx::Rect opaque_rect, 56 gfx::Rect visible_rect, bool needs_blending, 57 unsigned resource_id, bool premultiplied_alpha, 58 gfx::PointF uv_top_left, 59 gfx::PointF uv_bottom_right, 60 SkColor background_color, 61 const float vertex_opacity[4], 62 bool flipped) { 63 DrawQuad::SetAll(shared_quad_state, DrawQuad::TEXTURE_CONTENT, rect, 64 opaque_rect, visible_rect, needs_blending); 65 this->resource_id = resource_id; 66 this->premultiplied_alpha = premultiplied_alpha; 67 this->uv_top_left = uv_top_left; 68 this->uv_bottom_right = uv_bottom_right; 69 this->background_color = background_color; 70 this->vertex_opacity[0] = vertex_opacity[0]; 71 this->vertex_opacity[1] = vertex_opacity[1]; 72 this->vertex_opacity[2] = vertex_opacity[2]; 73 this->vertex_opacity[3] = vertex_opacity[3]; 74 this->flipped = flipped; 75 } 76 77 void TextureDrawQuad::IterateResources( 78 const ResourceIteratorCallback& callback) { 79 resource_id = callback.Run(resource_id); 80 } 81 82 const TextureDrawQuad* TextureDrawQuad::MaterialCast(const DrawQuad* quad) { 83 DCHECK(quad->material == DrawQuad::TEXTURE_CONTENT); 84 return static_cast<const TextureDrawQuad*>(quad); 85 } 86 87 bool TextureDrawQuad::PerformClipping() { 88 // This only occurs if the rect is only scaled and translated (and thus still 89 // axis aligned). 90 if (!quadTransform().IsPositiveScaleOrTranslation()) 91 return false; 92 93 // Grab our scale and make sure it's positive. 94 float x_scale = static_cast<float>(quadTransform().matrix().getDouble(0, 0)); 95 float y_scale = static_cast<float>(quadTransform().matrix().getDouble(1, 1)); 96 97 // Grab our offset. 98 gfx::Vector2dF offset( 99 static_cast<float>(quadTransform().matrix().getDouble(0, 3)), 100 static_cast<float>(quadTransform().matrix().getDouble(1, 3))); 101 102 // Transform the rect by the scale and offset. 103 gfx::RectF rect_f = rect; 104 rect_f.Scale(x_scale, y_scale); 105 rect_f += offset; 106 107 // Perform clipping and check to see if the result is empty. 108 gfx::RectF clipped_rect = IntersectRects(rect_f, clipRect()); 109 if (clipped_rect.IsEmpty()) { 110 rect = gfx::Rect(); 111 uv_top_left = gfx::PointF(); 112 uv_bottom_right = gfx::PointF(); 113 return true; 114 } 115 116 // Create a new uv-rect by clipping the old one to the new bounds. 117 gfx::Vector2dF uv_scale(uv_bottom_right - uv_top_left); 118 uv_scale.Scale(1.f / rect_f.width(), 1.f / rect_f.height()); 119 uv_bottom_right = uv_top_left + 120 gfx::ScaleVector2d( 121 clipped_rect.bottom_right() - rect_f.origin(), 122 uv_scale.x(), 123 uv_scale.y()); 124 uv_top_left = uv_top_left + 125 gfx::ScaleVector2d( 126 clipped_rect.origin() - rect_f.origin(), 127 uv_scale.x(), 128 uv_scale.y()); 129 130 // Indexing according to the quad vertex generation: 131 // 1--2 132 // | | 133 // 0--3 134 if (vertex_opacity[0] != vertex_opacity[1] 135 || vertex_opacity[0] != vertex_opacity[2] 136 || vertex_opacity[0] != vertex_opacity[3]) { 137 const float x1 = (clipped_rect.x() - rect_f.x()) / rect_f.width(); 138 const float y1 = (clipped_rect.y() - rect_f.y()) / rect_f.height(); 139 const float x3 = (clipped_rect.right() - rect_f.x()) / rect_f.width(); 140 const float y3 = (clipped_rect.bottom() - rect_f.y()) / rect_f.height(); 141 const float x1y1 = x1 * vertex_opacity[2] + (1.0f - x1) * vertex_opacity[1]; 142 const float x1y3 = x1 * vertex_opacity[3] + (1.0f - x1) * vertex_opacity[0]; 143 const float x3y1 = x3 * vertex_opacity[2] + (1.0f - x3) * vertex_opacity[1]; 144 const float x3y3 = x3 * vertex_opacity[3] + (1.0f - x3) * vertex_opacity[0]; 145 vertex_opacity[0] = y3 * x1y3 + (1.0f - y3) * x1y1; 146 vertex_opacity[1] = y1 * x1y3 + (1.0f - y1) * x1y1; 147 vertex_opacity[2] = y1 * x3y3 + (1.0f - y1) * x3y1; 148 vertex_opacity[3] = y3 * x3y3 + (1.0f - y3) * x3y1; 149 } 150 151 // Move the clipped rectangle back into its space. 152 clipped_rect -= offset; 153 clipped_rect.Scale(1.0f / x_scale, 1.0f / y_scale); 154 rect = gfx::Rect(static_cast<int>(clipped_rect.x() + 0.5f), 155 static_cast<int>(clipped_rect.y() + 0.5f), 156 static_cast<int>(clipped_rect.width() + 0.5f), 157 static_cast<int>(clipped_rect.height() + 0.5f)); 158 return true; 159 } 160 161 void TextureDrawQuad::ExtendValue(base::DictionaryValue* value) const { 162 value->SetInteger("resource_id", resource_id); 163 value->SetBoolean("premultiplied_alpha", premultiplied_alpha); 164 value->Set("uv_top_left", MathUtil::AsValue(uv_top_left).release()); 165 value->Set("uv_bottom_right", MathUtil::AsValue(uv_bottom_right).release()); 166 value->SetInteger("background_color", background_color); 167 scoped_ptr<ListValue> vertex_opacity_value(new ListValue); 168 for (size_t i = 0; i < 4; ++i) 169 vertex_opacity_value->AppendDouble(vertex_opacity[i]); 170 value->Set("vertex_opacity", vertex_opacity_value.release()); 171 value->SetBoolean("flipped", flipped); 172 } 173 174 } // namespace cc 175