[go: nahoru, domu]

Tickmarks for Aura Overlay Scrollbars

Currently Aura Overlay Scrollbar paints in PaintedOverlayScrollbarLayer which
only paint the thumb part. In this patch, we paint the tickmarks when
we have tickmarks in scrollbar when PaintedOverlayScrollbarLayer update.

Bug: 759152
Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel;master.tryserver.chromium.android:android_optional_gpu_tests_rel
Change-Id: I9e351b475cd9afa14cdae9264a2b78ab36a18258
Reviewed-on: https://chromium-review.googlesource.com/641611
Commit-Queue: Jianpeng Chao <chaopeng@chromium.org>
Reviewed-by: Rick Byers <rbyers@chromium.org>
Reviewed-by: weiliangc <weiliangc@chromium.org>
Reviewed-by: David Bokan <bokan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#540284}
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index 30d71bb..4f5c5fe3 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -589,6 +589,7 @@
     "layers/nine_patch_generator_unittest.cc",
     "layers/nine_patch_layer_impl_unittest.cc",
     "layers/nine_patch_layer_unittest.cc",
+    "layers/painted_overlay_scrollbar_layer_unittest.cc",
     "layers/painted_scrollbar_layer_impl_unittest.cc",
     "layers/painted_scrollbar_layer_unittest.cc",
     "layers/picture_image_layer_unittest.cc",
diff --git a/cc/blink/scrollbar_impl.cc b/cc/blink/scrollbar_impl.cc
index 0ed7a337..46d4200 100644
--- a/cc/blink/scrollbar_impl.cc
+++ b/cc/blink/scrollbar_impl.cc
@@ -84,6 +84,10 @@
   return geometry_->NinePatchThumbAperture(scrollbar_.get());
 }
 
+bool ScrollbarImpl::HasTickmarks() const {
+  return scrollbar_->HasTickmarks();
+}
+
 void ScrollbarImpl::PaintPart(cc::PaintCanvas* canvas,
                               cc::ScrollbarPart part,
                               const gfx::Rect& content_rect) {
@@ -92,6 +96,11 @@
     return;
   }
 
+  if (part == cc::TICKMARKS) {
+    painter_.PaintTickmarks(canvas, content_rect);
+    return;
+  }
+
   // The following is a simplification of ScrollbarThemeComposite::paint.
   painter_.PaintScrollbarBackground(canvas, content_rect);
 
diff --git a/cc/blink/scrollbar_impl.h b/cc/blink/scrollbar_impl.h
index c0534d5..5cab188 100644
--- a/cc/blink/scrollbar_impl.h
+++ b/cc/blink/scrollbar_impl.h
@@ -37,6 +37,7 @@
   gfx::Rect TrackRect() const override;
   float ThumbOpacity() const override;
   bool NeedsPaintPart(cc::ScrollbarPart part) const override;
+  bool HasTickmarks() const override;
   void PaintPart(cc::PaintCanvas* canvas,
                  cc::ScrollbarPart part,
                  const gfx::Rect& content_rect) override;
diff --git a/cc/input/scrollbar.h b/cc/input/scrollbar.h
index e0302bf..ab67bce 100644
--- a/cc/input/scrollbar.h
+++ b/cc/input/scrollbar.h
@@ -16,7 +16,7 @@
 enum ScrollDirection { SCROLL_BACKWARD, SCROLL_FORWARD };
 // For now, TRACK includes everything but the thumb including background and
 // buttons.
-enum ScrollbarPart { THUMB, TRACK };
+enum ScrollbarPart { THUMB, TRACK, TICKMARKS };
 
 class Scrollbar {
  public:
@@ -31,6 +31,7 @@
   virtual int ThumbLength() const = 0;
   virtual gfx::Rect TrackRect() const = 0;
   virtual float ThumbOpacity() const = 0;
+  virtual bool HasTickmarks() const = 0;
   virtual bool NeedsPaintPart(ScrollbarPart part) const = 0;
   virtual void PaintPart(PaintCanvas* canvas,
                          ScrollbarPart part,
diff --git a/cc/layers/painted_overlay_scrollbar_layer.cc b/cc/layers/painted_overlay_scrollbar_layer.cc
index f60f6cd..acb02ad 100644
--- a/cc/layers/painted_overlay_scrollbar_layer.cc
+++ b/cc/layers/painted_overlay_scrollbar_layer.cc
@@ -90,6 +90,11 @@
     scrollbar_layer->SetAperture(gfx::Rect());
     scrollbar_layer->set_thumb_ui_resource_id(0);
   }
+
+  if (track_resource_.get())
+    scrollbar_layer->set_track_ui_resource_id(track_resource_->id());
+  else
+    scrollbar_layer->set_track_ui_resource_id(0);
 }
 
 ScrollbarLayerInterface* PaintedOverlayScrollbarLayer::ToScrollbarLayer() {
@@ -99,8 +104,10 @@
 void PaintedOverlayScrollbarLayer::SetLayerTreeHost(LayerTreeHost* host) {
   // When the LTH is set to null or has changed, then this layer should remove
   // all of its associated resources.
-  if (host != layer_tree_host())
-    thumb_resource_ = nullptr;
+  if (host != layer_tree_host()) {
+    thumb_resource_.reset();
+    track_resource_.reset();
+  }
 
   Layer::SetLayerTreeHost(host);
 }
@@ -121,6 +128,7 @@
   updated |= UpdateProperty(scrollbar_->ThumbThickness(), &thumb_thickness_);
   updated |= UpdateProperty(scrollbar_->ThumbLength(), &thumb_length_);
   updated |= PaintThumbIfNeeded();
+  updated |= PaintTickmarks();
 
   return updated;
 }
@@ -159,4 +167,43 @@
   return true;
 }
 
+bool PaintedOverlayScrollbarLayer::PaintTickmarks() {
+  if (!scrollbar_->HasTickmarks()) {
+    if (!track_resource_) {
+      return false;
+    } else {
+      // Remove previous tickmarks.
+      track_resource_.reset();
+      SetNeedsPushProperties();
+      return true;
+    }
+  }
+
+  gfx::Rect paint_rect = gfx::Rect(gfx::Point(), track_rect_.size());
+
+  DCHECK(!paint_rect.size().IsEmpty());
+
+  SkBitmap skbitmap;
+  skbitmap.allocN32Pixels(paint_rect.width(), paint_rect.height());
+  SkiaPaintCanvas canvas(skbitmap);
+
+  SkRect content_skrect = RectToSkRect(paint_rect);
+  PaintFlags flags;
+  flags.setAntiAlias(false);
+  flags.setBlendMode(SkBlendMode::kClear);
+  canvas.drawRect(content_skrect, flags);
+  canvas.clipRect(content_skrect);
+
+  scrollbar_->PaintPart(&canvas, TICKMARKS, paint_rect);
+  // Make sure that the pixels are no longer mutable to unavoid unnecessary
+  // allocation and copying.
+  skbitmap.setImmutable();
+
+  track_resource_ = ScopedUIResource::Create(
+      layer_tree_host()->GetUIResourceManager(), UIResourceBitmap(skbitmap));
+
+  SetNeedsPushProperties();
+  return true;
+}
+
 }  // namespace cc
diff --git a/cc/layers/painted_overlay_scrollbar_layer.h b/cc/layers/painted_overlay_scrollbar_layer.h
index eb5a749..7f4c555 100644
--- a/cc/layers/painted_overlay_scrollbar_layer.h
+++ b/cc/layers/painted_overlay_scrollbar_layer.h
@@ -53,6 +53,7 @@
   }
 
   bool PaintThumbIfNeeded();
+  bool PaintTickmarks();
 
   std::unique_ptr<Scrollbar> scrollbar_;
   ElementId scroll_element_id_;
@@ -65,6 +66,7 @@
   gfx::Rect aperture_;
 
   std::unique_ptr<ScopedUIResource> thumb_resource_;
+  std::unique_ptr<ScopedUIResource> track_resource_;
 
   DISALLOW_COPY_AND_ASSIGN(PaintedOverlayScrollbarLayer);
 };
diff --git a/cc/layers/painted_overlay_scrollbar_layer_impl.cc b/cc/layers/painted_overlay_scrollbar_layer_impl.cc
index cd24f21..79724d1 100644
--- a/cc/layers/painted_overlay_scrollbar_layer_impl.cc
+++ b/cc/layers/painted_overlay_scrollbar_layer_impl.cc
@@ -3,7 +3,10 @@
 // found in the LICENSE file.
 
 #include "cc/layers/painted_overlay_scrollbar_layer_impl.h"
+
 #include "cc/trees/layer_tree_impl.h"
+#include "components/viz/common/quads/solid_color_draw_quad.h"
+#include "components/viz/common/quads/texture_draw_quad.h"
 
 namespace cc {
 
@@ -27,6 +30,7 @@
                              is_left_side_vertical_scrollbar,
                              true),
       thumb_ui_resource_id_(0),
+      track_ui_resource_id_(0),
       thumb_thickness_(0),
       thumb_length_(0),
       track_start_(0),
@@ -55,6 +59,7 @@
   scrollbar_layer->SetAperture(aperture_);
 
   scrollbar_layer->set_thumb_ui_resource_id(thumb_ui_resource_id_);
+  scrollbar_layer->set_track_ui_resource_id(track_ui_resource_id_);
 }
 
 bool PaintedOverlayScrollbarLayerImpl::WillDraw(
@@ -67,11 +72,19 @@
 void PaintedOverlayScrollbarLayerImpl::AppendQuads(
     viz::RenderPass* render_pass,
     AppendQuadsData* append_quads_data) {
+  viz::SharedQuadState* shared_quad_state =
+      render_pass->CreateAndAppendSharedQuadState();
+  AppendThumbQuads(render_pass, append_quads_data, shared_quad_state);
+  AppendTrackQuads(render_pass, append_quads_data, shared_quad_state);
+}
+
+void PaintedOverlayScrollbarLayerImpl::AppendThumbQuads(
+    viz::RenderPass* render_pass,
+    AppendQuadsData* append_quads_data,
+    viz::SharedQuadState* shared_quad_state) {
   if (aperture_.IsEmpty())
     return;
 
-  viz::SharedQuadState* shared_quad_state =
-      render_pass->CreateAndAppendSharedQuadState();
   bool is_resource =
       thumb_ui_resource_id_ &&
       layer_tree_impl()->ResourceIdForUIResource(thumb_ui_resource_id_);
@@ -118,6 +131,41 @@
                               shared_quad_state, patches);
 }
 
+void PaintedOverlayScrollbarLayerImpl::AppendTrackQuads(
+    viz::RenderPass* render_pass,
+    AppendQuadsData* append_quads_data,
+    viz::SharedQuadState* shared_quad_state) {
+  viz::ResourceId track_resource_id =
+      layer_tree_impl()->ResourceIdForUIResource(track_ui_resource_id_);
+  if (!track_resource_id)
+    return;
+
+  bool nearest_neighbor = false;
+
+  gfx::Rect track_quad_rect(bounds());
+  gfx::Rect scaled_track_quad_rect(bounds());
+  gfx::Rect visible_track_quad_rect =
+      draw_properties().occlusion_in_content_space.GetUnoccludedContentRect(
+          track_quad_rect);
+  gfx::Rect scaled_visible_track_quad_rect =
+      gfx::ScaleToEnclosingRect(visible_track_quad_rect, 1.f);
+
+  bool needs_blending = !contents_opaque();
+  bool premultipled_alpha = true;
+  bool flipped = false;
+  gfx::PointF uv_top_left(0.f, 0.f);
+  gfx::PointF uv_bottom_right(1.f, 1.f);
+  float opacity[] = {1.0f, 1.0f, 1.0f, 1.0f};
+  viz::TextureDrawQuad* quad =
+      render_pass->CreateAndAppendDrawQuad<viz::TextureDrawQuad>();
+  quad->SetNew(shared_quad_state, scaled_track_quad_rect,
+               scaled_visible_track_quad_rect, needs_blending,
+               track_resource_id, premultipled_alpha, uv_top_left,
+               uv_bottom_right, SK_ColorTRANSPARENT, opacity, flipped,
+               nearest_neighbor, false);
+  ValidateQuadResources(quad);
+}
+
 void PaintedOverlayScrollbarLayerImpl::SetThumbThickness(int thumb_thickness) {
   if (thumb_thickness_ == thumb_thickness)
     return;
diff --git a/cc/layers/painted_overlay_scrollbar_layer_impl.h b/cc/layers/painted_overlay_scrollbar_layer_impl.h
index 104287b..1152992ad 100644
--- a/cc/layers/painted_overlay_scrollbar_layer_impl.h
+++ b/cc/layers/painted_overlay_scrollbar_layer_impl.h
@@ -47,6 +47,10 @@
     thumb_ui_resource_id_ = uid;
   }
 
+  void set_track_ui_resource_id(UIResourceId uid) {
+    track_ui_resource_id_ = uid;
+  }
+
  protected:
   PaintedOverlayScrollbarLayerImpl(LayerTreeImpl* tree_impl,
                                    int id,
@@ -63,7 +67,16 @@
  private:
   const char* LayerTypeAsString() const override;
 
+  void AppendThumbQuads(viz::RenderPass* render_pass,
+                        AppendQuadsData* append_quads_data,
+                        viz::SharedQuadState* shared_quad_state);
+
+  void AppendTrackQuads(viz::RenderPass* render_pass,
+                        AppendQuadsData* append_quads_data,
+                        viz::SharedQuadState* shared_quad_state);
+
   UIResourceId thumb_ui_resource_id_;
+  UIResourceId track_ui_resource_id_;
 
   int thumb_thickness_;
   int thumb_length_;
diff --git a/cc/layers/painted_overlay_scrollbar_layer_unittest.cc b/cc/layers/painted_overlay_scrollbar_layer_unittest.cc
new file mode 100644
index 0000000..c510444
--- /dev/null
+++ b/cc/layers/painted_overlay_scrollbar_layer_unittest.cc
@@ -0,0 +1,88 @@
+// Copyright 2018 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 "cc/layers/painted_overlay_scrollbar_layer.h"
+
+#include "cc/animation/animation_host.h"
+#include "cc/test/fake_layer_tree_host.h"
+#include "cc/test/fake_layer_tree_host_client.h"
+#include "cc/test/fake_scrollbar.h"
+#include "cc/test/test_task_graph_runner.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace cc {
+
+namespace {
+
+class MockScrollbar : public FakeScrollbar {
+ public:
+  MockScrollbar() : FakeScrollbar(true, true, true) {}
+
+  void PaintPart(PaintCanvas* canvas,
+                 ScrollbarPart part,
+                 const gfx::Rect& content_rect) override {
+    if (part == TICKMARKS)
+      paint_tickmarks_called_ = true;
+  }
+
+  bool UsesNinePatchThumbResource() const override { return true; }
+
+  gfx::Size NinePatchThumbCanvasSize() const override {
+    return gfx::Size(10, 10);
+  }
+
+  bool PaintTickmarksCalled() { return paint_tickmarks_called_; }
+
+  void SetPaintTickmarksCalled(bool called) {
+    paint_tickmarks_called_ = called;
+  }
+
+ private:
+  bool paint_tickmarks_called_ = false;
+};
+
+TEST(PaintedOverlayScrollbarLayerTest, PaintTickmarks) {
+  FakeLayerTreeHostClient fake_client_;
+  TestTaskGraphRunner task_graph_runner_;
+
+  auto animation_host = AnimationHost::CreateForTesting(ThreadInstance::MAIN);
+  auto layer_tree_host = FakeLayerTreeHost::Create(
+      &fake_client_, &task_graph_runner_, animation_host.get());
+
+  MockScrollbar* scrollbar = new MockScrollbar();
+  scrollbar->set_has_tickmarks(false);
+
+  scoped_refptr<PaintedOverlayScrollbarLayer> scrollbar_layer =
+      PaintedOverlayScrollbarLayer::Create(
+          std::unique_ptr<Scrollbar>(scrollbar));
+
+  scrollbar_layer->SetIsDrawable(true);
+  scrollbar_layer->SetBounds(gfx::Size(100, 100));
+
+  layer_tree_host->SetRootLayer(scrollbar_layer);
+  EXPECT_EQ(scrollbar_layer->GetLayerTreeHostForTesting(),
+            layer_tree_host.get());
+
+  // Request no paint when initialization.
+  scrollbar_layer->Update();
+  EXPECT_FALSE(scrollbar->PaintTickmarksCalled());
+
+  // The next update will paint nothing because still no tickmarks applied.
+  scrollbar_layer->Update();
+  EXPECT_FALSE(scrollbar->PaintTickmarksCalled());
+
+  // Enable the tickmarks.
+  scrollbar->set_has_tickmarks(true);
+  scrollbar_layer->Update();
+  EXPECT_TRUE(scrollbar->PaintTickmarksCalled());
+  scrollbar->SetPaintTickmarksCalled(false);
+
+  // Disable the tickmarks. No paint.
+  scrollbar->set_has_tickmarks(false);
+  scrollbar_layer->Update();
+  EXPECT_FALSE(scrollbar->PaintTickmarksCalled());
+}
+
+}  // namespace
+}  // namespace cc
diff --git a/cc/test/fake_scrollbar.cc b/cc/test/fake_scrollbar.cc
index 5002fd5..d7f8be65 100644
--- a/cc/test/fake_scrollbar.cc
+++ b/cc/test/fake_scrollbar.cc
@@ -30,6 +30,7 @@
       thumb_opacity_(1),
       needs_paint_thumb_(true),
       needs_paint_track_(true),
+      has_tickmarks_(false),
       track_rect_(0, 0, 100, 10),
       fill_color_(SK_ColorGREEN) {}
 
@@ -71,6 +72,10 @@
   return needs_paint_track_;
 }
 
+bool FakeScrollbar::HasTickmarks() const {
+  return has_tickmarks_;
+}
+
 void FakeScrollbar::PaintPart(PaintCanvas* canvas,
                               ScrollbarPart part,
                               const gfx::Rect& content_rect) {
diff --git a/cc/test/fake_scrollbar.h b/cc/test/fake_scrollbar.h
index f5a3bd7a..56ed6de 100644
--- a/cc/test/fake_scrollbar.h
+++ b/cc/test/fake_scrollbar.h
@@ -34,6 +34,7 @@
   gfx::Rect TrackRect() const override;
   float ThumbOpacity() const override;
   bool NeedsPaintPart(ScrollbarPart part) const override;
+  bool HasTickmarks() const override;
   void PaintPart(PaintCanvas* canvas,
                  ScrollbarPart part,
                  const gfx::Rect& content_rect) override;
@@ -57,6 +58,7 @@
   void set_needs_paint_track(bool needs_paint) {
     needs_paint_track_ = needs_paint;
   }
+  void set_has_tickmarks(bool has_tickmarks) { has_tickmarks_ = has_tickmarks; }
 
  private:
   bool paint_;
@@ -69,6 +71,7 @@
   float thumb_opacity_;
   bool needs_paint_thumb_;
   bool needs_paint_track_;
+  bool has_tickmarks_;
   gfx::Point location_;
   gfx::Rect track_rect_;
   SkColor fill_color_;
diff --git a/cc/trees/layer_tree_host_pixeltest_scrollbars.cc b/cc/trees/layer_tree_host_pixeltest_scrollbars.cc
index 11c6a23..983d6ed 100644
--- a/cc/trees/layer_tree_host_pixeltest_scrollbars.cc
+++ b/cc/trees/layer_tree_host_pixeltest_scrollbars.cc
@@ -52,6 +52,7 @@
   gfx::Rect TrackRect() const override { return rect_; }
   float ThumbOpacity() const override { return 1.f; }
   bool NeedsPaintPart(ScrollbarPart part) const override { return true; }
+  bool HasTickmarks() const override { return false; }
   void PaintPart(PaintCanvas* canvas,
                  ScrollbarPart part,
                  const gfx::Rect& content_rect) override {
diff --git a/third_party/WebKit/Source/platform/exported/WebScrollbarImpl.cpp b/third_party/WebKit/Source/platform/exported/WebScrollbarImpl.cpp
index c8859d1..da9738d 100644
--- a/third_party/WebKit/Source/platform/exported/WebScrollbarImpl.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebScrollbarImpl.cpp
@@ -64,6 +64,13 @@
   return scrollbar_->IsScrollableAreaActive();
 }
 
+bool WebScrollbarImpl::HasTickmarks() const {
+  Vector<IntRect> tickmarks;
+  scrollbar_->GetTickmarks(tickmarks);
+
+  return !tickmarks.IsEmpty();
+}
+
 void WebScrollbarImpl::GetTickmarks(WebVector<WebRect>& web_tickmarks) const {
   Vector<IntRect> tickmarks;
   scrollbar_->GetTickmarks(tickmarks);
diff --git a/third_party/WebKit/Source/platform/exported/WebScrollbarImpl.h b/third_party/WebKit/Source/platform/exported/WebScrollbarImpl.h
index dc7765a..3649ed5 100644
--- a/third_party/WebKit/Source/platform/exported/WebScrollbarImpl.h
+++ b/third_party/WebKit/Source/platform/exported/WebScrollbarImpl.h
@@ -55,6 +55,7 @@
   int Maximum() const override;
   int TotalSize() const override;
   bool IsScrollableAreaActive() const override;
+  bool HasTickmarks() const override;
   void GetTickmarks(WebVector<WebRect>& tickmarks) const override;
   ScrollbarControlSize GetControlSize() const override;
   ScrollbarPart PressedPart() const override;
diff --git a/third_party/WebKit/public/platform/WebScrollbar.h b/third_party/WebKit/public/platform/WebScrollbar.h
index 5949bcb..8e50d44 100644
--- a/third_party/WebKit/public/platform/WebScrollbar.h
+++ b/third_party/WebKit/public/platform/WebScrollbar.h
@@ -79,6 +79,7 @@
   virtual int Maximum() const = 0;
   virtual int TotalSize() const = 0;
   virtual bool IsScrollableAreaActive() const = 0;
+  virtual bool HasTickmarks() const = 0;
   virtual void GetTickmarks(WebVector<WebRect>& tickmarks) const = 0;
   virtual ScrollbarControlSize GetControlSize() const = 0;
   virtual ScrollbarPart PressedPart() const = 0;