| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "content/browser/android/composited_touch_handle_drawable.h" |
| |
| #include "base/android/context_utils.h" |
| #include "base/lazy_instance.h" |
| #include "base/logging.h" |
| #include "base/macros.h" |
| #include "base/trace_event/trace_event.h" |
| #include "cc/layers/ui_resource_layer.h" |
| #include "content/public/browser/android/compositor.h" |
| #include "jni/HandleViewResources_jni.h" |
| #include "ui/gfx/android/java_bitmap.h" |
| |
| namespace content { |
| |
| namespace { |
| |
| static SkBitmap CreateSkBitmapFromJavaBitmap( |
| base::android::ScopedJavaLocalRef<jobject> jbitmap) { |
| return jbitmap.is_null() |
| ? SkBitmap() |
| : CreateSkBitmapFromJavaBitmap(gfx::JavaBitmap(jbitmap.obj())); |
| } |
| |
| class HandleResources { |
| public: |
| HandleResources() : loaded_(false) { |
| } |
| |
| void LoadIfNecessary(jobject context) { |
| if (loaded_) |
| return; |
| |
| loaded_ = true; |
| |
| TRACE_EVENT0("browser", "HandleResources::Create"); |
| JNIEnv* env = base::android::AttachCurrentThread(); |
| if (!context) |
| context = base::android::GetApplicationContext(); |
| |
| left_bitmap_ = CreateSkBitmapFromJavaBitmap( |
| Java_HandleViewResources_getLeftHandleBitmap(env, context)); |
| right_bitmap_ = CreateSkBitmapFromJavaBitmap( |
| Java_HandleViewResources_getRightHandleBitmap(env, context)); |
| center_bitmap_ = CreateSkBitmapFromJavaBitmap( |
| Java_HandleViewResources_getCenterHandleBitmap(env, context)); |
| |
| left_bitmap_.setImmutable(); |
| right_bitmap_.setImmutable(); |
| center_bitmap_.setImmutable(); |
| |
| drawable_horizontal_padding_ratio_ = |
| Java_HandleViewResources_getHandleHorizontalPaddingRatio(env); |
| } |
| |
| const SkBitmap& GetBitmap(ui::TouchHandleOrientation orientation) { |
| DCHECK(loaded_); |
| switch (orientation) { |
| case ui::TouchHandleOrientation::LEFT: |
| return left_bitmap_; |
| case ui::TouchHandleOrientation::RIGHT: |
| return right_bitmap_; |
| case ui::TouchHandleOrientation::CENTER: |
| return center_bitmap_; |
| case ui::TouchHandleOrientation::UNDEFINED: |
| NOTREACHED() << "Invalid touch handle orientation."; |
| }; |
| return center_bitmap_; |
| } |
| |
| float GetDrawableHorizontalPaddingRatio() const { |
| DCHECK(loaded_); |
| return drawable_horizontal_padding_ratio_; |
| } |
| |
| private: |
| SkBitmap left_bitmap_; |
| SkBitmap right_bitmap_; |
| SkBitmap center_bitmap_; |
| float drawable_horizontal_padding_ratio_; |
| bool loaded_; |
| |
| DISALLOW_COPY_AND_ASSIGN(HandleResources); |
| }; |
| |
| base::LazyInstance<HandleResources>::Leaky g_selection_resources; |
| |
| } // namespace |
| |
| CompositedTouchHandleDrawable::CompositedTouchHandleDrawable( |
| cc::Layer* root_layer, |
| float dpi_scale, |
| jobject context) |
| : dpi_scale_(dpi_scale), |
| orientation_(ui::TouchHandleOrientation::UNDEFINED), |
| layer_(cc::UIResourceLayer::Create(Compositor::LayerSettings())) { |
| g_selection_resources.Get().LoadIfNecessary(context); |
| drawable_horizontal_padding_ratio_ = |
| g_selection_resources.Get().GetDrawableHorizontalPaddingRatio(); |
| DCHECK(root_layer); |
| root_layer->AddChild(layer_.get()); |
| } |
| |
| CompositedTouchHandleDrawable::~CompositedTouchHandleDrawable() { |
| DetachLayer(); |
| } |
| |
| void CompositedTouchHandleDrawable::SetEnabled(bool enabled) { |
| layer_->SetIsDrawable(enabled); |
| // Force a position update in case the disabled layer's properties are stale. |
| if (enabled) |
| UpdateLayerPosition(); |
| } |
| |
| void CompositedTouchHandleDrawable::SetOrientation( |
| ui::TouchHandleOrientation orientation, |
| bool mirror_vertical, |
| bool mirror_horizontal) { |
| DCHECK(layer_->parent()); |
| bool orientation_changed = orientation_ != orientation; |
| |
| orientation_ = orientation; |
| |
| if (orientation_changed) { |
| const SkBitmap& bitmap = g_selection_resources.Get().GetBitmap(orientation); |
| const int bitmap_height = bitmap.height(); |
| const int bitmap_width = bitmap.width(); |
| layer_->SetBitmap(bitmap); |
| layer_->SetBounds(gfx::Size(bitmap_width, bitmap_height)); |
| } |
| |
| const int layer_height = layer_->bounds().height(); |
| const int layer_width = layer_->bounds().width(); |
| |
| // Invert about X and Y axis based on the mirror values |
| gfx::Transform transform; |
| float scale_x = mirror_horizontal ? -1.f : 1.f; |
| float scale_y = mirror_vertical ? -1.f : 1.f; |
| |
| layer_->SetTransformOrigin( |
| gfx::Point3F(layer_width * 0.5f, layer_height * 0.5f, 0)); |
| transform.Scale(scale_x, scale_y); |
| layer_->SetTransform(transform); |
| } |
| |
| void CompositedTouchHandleDrawable::SetOrigin(const gfx::PointF& origin) { |
| origin_position_ = gfx::ScalePoint(origin, dpi_scale_); |
| UpdateLayerPosition(); |
| } |
| |
| void CompositedTouchHandleDrawable::SetAlpha(float alpha) { |
| DCHECK(layer_->parent()); |
| alpha = std::max(0.f, std::min(1.f, alpha)); |
| bool hidden = alpha <= 0; |
| layer_->SetOpacity(alpha); |
| layer_->SetHideLayerAndSubtree(hidden); |
| } |
| |
| gfx::RectF CompositedTouchHandleDrawable::GetVisibleBounds() const { |
| return gfx::ScaleRect(gfx::RectF(layer_->position().x(), |
| layer_->position().y(), |
| layer_->bounds().width(), |
| layer_->bounds().height()), |
| 1.f / dpi_scale_); |
| } |
| |
| float CompositedTouchHandleDrawable::GetDrawableHorizontalPaddingRatio() const { |
| return drawable_horizontal_padding_ratio_; |
| } |
| |
| void CompositedTouchHandleDrawable::DetachLayer() { |
| layer_->RemoveFromParent(); |
| } |
| |
| void CompositedTouchHandleDrawable::UpdateLayerPosition() { |
| layer_->SetPosition(origin_position_); |
| } |
| |
| // static |
| bool CompositedTouchHandleDrawable::RegisterHandleViewResources(JNIEnv* env) { |
| return RegisterNativesImpl(env); |
| } |
| |
| } // namespace content |