1 // Copyright 2014 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 "content/browser/android/composited_touch_handle_drawable.h" 6 7 #include "base/debug/trace_event.h" 8 #include "base/lazy_instance.h" 9 #include "base/logging.h" 10 #include "cc/layers/ui_resource_layer.h" 11 #include "jni/HandleViewResources_jni.h" 12 #include "ui/gfx/android/java_bitmap.h" 13 14 namespace content { 15 16 namespace { 17 18 static SkBitmap CreateSkBitmapFromJavaBitmap( 19 base::android::ScopedJavaLocalRef<jobject> jbitmap) { 20 return jbitmap.is_null() 21 ? SkBitmap() 22 : CreateSkBitmapFromJavaBitmap(gfx::JavaBitmap(jbitmap.obj())); 23 } 24 25 class HandleResources { 26 public: 27 HandleResources() : loaded_(false) { 28 } 29 30 void LoadIfNecessary(jobject context) { 31 if (loaded_) 32 return; 33 34 loaded_ = true; 35 36 TRACE_EVENT0("browser", "HandleResources::Create"); 37 JNIEnv* env = base::android::AttachCurrentThread(); 38 if (!context) 39 context = base::android::GetApplicationContext(); 40 41 left_bitmap_ = CreateSkBitmapFromJavaBitmap( 42 Java_HandleViewResources_getLeftHandleBitmap(env, context)); 43 right_bitmap_ = CreateSkBitmapFromJavaBitmap( 44 Java_HandleViewResources_getRightHandleBitmap(env, context)); 45 center_bitmap_ = CreateSkBitmapFromJavaBitmap( 46 Java_HandleViewResources_getCenterHandleBitmap(env, context)); 47 48 left_bitmap_.setImmutable(); 49 right_bitmap_.setImmutable(); 50 center_bitmap_.setImmutable(); 51 } 52 53 const SkBitmap& GetBitmap(TouchHandleOrientation orientation) { 54 DCHECK(loaded_); 55 switch (orientation) { 56 case TOUCH_HANDLE_LEFT: 57 return left_bitmap_; 58 case TOUCH_HANDLE_RIGHT: 59 return right_bitmap_; 60 case TOUCH_HANDLE_CENTER: 61 return center_bitmap_; 62 case TOUCH_HANDLE_ORIENTATION_UNDEFINED: 63 NOTREACHED() << "Invalid touch handle orientation."; 64 }; 65 return center_bitmap_; 66 } 67 68 private: 69 SkBitmap left_bitmap_; 70 SkBitmap right_bitmap_; 71 SkBitmap center_bitmap_; 72 bool loaded_; 73 74 DISALLOW_COPY_AND_ASSIGN(HandleResources); 75 }; 76 77 base::LazyInstance<HandleResources>::Leaky g_selection_resources; 78 79 } // namespace 80 81 CompositedTouchHandleDrawable::CompositedTouchHandleDrawable( 82 cc::Layer* root_layer, 83 float dpi_scale, 84 jobject context) 85 : dpi_scale_(dpi_scale), 86 orientation_(TOUCH_HANDLE_ORIENTATION_UNDEFINED), 87 layer_(cc::UIResourceLayer::Create()) { 88 g_selection_resources.Get().LoadIfNecessary(context); 89 DCHECK(root_layer); 90 root_layer->AddChild(layer_.get()); 91 } 92 93 CompositedTouchHandleDrawable::~CompositedTouchHandleDrawable() { 94 Detach(); 95 } 96 97 void CompositedTouchHandleDrawable::SetEnabled(bool enabled) { 98 layer_->SetIsDrawable(enabled); 99 } 100 101 void CompositedTouchHandleDrawable::SetOrientation( 102 TouchHandleOrientation orientation) { 103 DCHECK(layer_->parent()); 104 orientation_ = orientation; 105 106 const SkBitmap& bitmap = g_selection_resources.Get().GetBitmap(orientation); 107 layer_->SetBitmap(bitmap); 108 layer_->SetBounds(gfx::Size(bitmap.width(), bitmap.height())); 109 110 switch (orientation_) { 111 case TOUCH_HANDLE_LEFT: 112 focal_offset_from_origin_ = gfx::Vector2dF(bitmap.width() * 0.75f, 0); 113 break; 114 case TOUCH_HANDLE_RIGHT: 115 focal_offset_from_origin_ = gfx::Vector2dF(bitmap.width() * 0.25f, 0); 116 break; 117 case TOUCH_HANDLE_CENTER: 118 focal_offset_from_origin_ = gfx::Vector2dF(bitmap.width() * 0.5f, 0); 119 break; 120 case TOUCH_HANDLE_ORIENTATION_UNDEFINED: 121 NOTREACHED() << "Invalid touch handle orientation."; 122 break; 123 }; 124 125 layer_->SetPosition(focal_position_ - focal_offset_from_origin_); 126 } 127 128 void CompositedTouchHandleDrawable::SetAlpha(float alpha) { 129 DCHECK(layer_->parent()); 130 layer_->SetOpacity(std::max(0.f, std::min(1.f, alpha))); 131 } 132 133 void CompositedTouchHandleDrawable::SetFocus(const gfx::PointF& position) { 134 DCHECK(layer_->parent()); 135 focal_position_ = gfx::ScalePoint(position, dpi_scale_); 136 layer_->SetPosition(focal_position_ - focal_offset_from_origin_); 137 } 138 139 void CompositedTouchHandleDrawable::SetVisible(bool visible) { 140 DCHECK(layer_->parent()); 141 layer_->SetHideLayerAndSubtree(!visible); 142 } 143 144 bool CompositedTouchHandleDrawable::IntersectsWith( 145 const gfx::RectF& rect) const { 146 return BoundingRect().Intersects(gfx::ScaleRect(rect, dpi_scale_)); 147 } 148 149 void CompositedTouchHandleDrawable::Detach() { 150 layer_->RemoveFromParent(); 151 } 152 153 gfx::RectF CompositedTouchHandleDrawable::BoundingRect() const { 154 return gfx::RectF(layer_->position().x(), 155 layer_->position().y(), 156 layer_->bounds().width(), 157 layer_->bounds().height()); 158 } 159 160 // static 161 bool CompositedTouchHandleDrawable::RegisterHandleViewResources(JNIEnv* env) { 162 return RegisterNativesImpl(env); 163 } 164 165 } // namespace content 166