opacity_layer.cc 3.5 KB
Newer Older
M
Michael Goderbauer 已提交
1
// Copyright 2013 The Flutter Authors. All rights reserved.
2 3 4
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5
#include "flutter/flow/layers/opacity_layer.h"
6

7 8
#include "flutter/flow/layers/transform_layer.h"

A
Adam Barth 已提交
9
namespace flow {
10

11
OpacityLayer::OpacityLayer() = default;
12

13
OpacityLayer::~OpacityLayer() = default;
14

15 16 17 18 19 20 21 22
void OpacityLayer::EnsureSingleChild() {
  FML_DCHECK(layers().size() > 0);  // OpacityLayer should never be a leaf

  if (layers().size() == 1) {
    return;
  }

  auto new_child = std::make_shared<flow::TransformLayer>();
23 24 25 26 27 28 29

  // Be careful: SkMatrix's default constructor doesn't initialize the matrix to
  // identity. Hence we have to explicitly call SkMatrix::setIdentity.
  SkMatrix identity;
  identity.setIdentity();

  new_child->set_transform(identity);
30 31 32 33 34 35 36
  for (auto& child : layers()) {
    new_child->Add(child);
  }
  ClearChildren();
  Add(new_child);
}

37
void OpacityLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
38
  EnsureSingleChild();
39 40 41
  SkMatrix child_matrix = matrix;
  child_matrix.postTranslate(offset_.fX, offset_.fY);
  ContainerLayer::Preroll(context, child_matrix);
42
  set_paint_bounds(paint_bounds().makeOffset(offset_.fX, offset_.fY));
43 44 45
  // See |EnsureSingleChild|.
  FML_DCHECK(layers().size() == 1);
  if (context->raster_cache &&
46
      SkRect::Intersects(context->cull_rect, paint_bounds())) {
47
    Layer* child = layers()[0].get();
48
    SkMatrix ctm = child_matrix;
49 50 51 52 53 54 55
#ifndef SUPPORT_FRACTIONAL_TRANSLATION
    ctm = RasterCache::GetIntegralTransCTM(ctm);
#endif
    context->raster_cache->Prepare(context, child, ctm);
  }
}

56
void OpacityLayer::Paint(PaintContext& context) const {
57
  TRACE_EVENT0("flutter", "OpacityLayer::Paint");
58
  FML_DCHECK(needs_painting());
59

60
  SkPaint paint;
61
  paint.setAlpha(alpha_);
62

63 64
  SkAutoCanvasRestore save(context.internal_nodes_canvas, true);
  context.internal_nodes_canvas->translate(offset_.fX, offset_.fY);
65 66

#ifndef SUPPORT_FRACTIONAL_TRANSLATION
67 68
  context.internal_nodes_canvas->setMatrix(RasterCache::GetIntegralTransCTM(
      context.leaf_nodes_canvas->getTotalMatrix()));
69 70
#endif

71 72 73
  // See |EnsureSingleChild|.
  FML_DCHECK(layers().size() == 1);

74 75 76 77
  // Embedded platform views are changing the canvas in the middle of the paint
  // traversal. To make sure we paint on the right canvas, when the embedded
  // platform views preview is enabled (context.view_embedded is not null) we
  // don't use the cache.
78
  if (context.view_embedder == nullptr && context.raster_cache) {
79
    const SkMatrix& ctm = context.leaf_nodes_canvas->getTotalMatrix();
80 81 82
    RasterCacheResult child_cache =
        context.raster_cache->Get(layers()[0].get(), ctm);
    if (child_cache.is_valid()) {
83
      child_cache.draw(*context.leaf_nodes_canvas, &paint);
84 85 86 87
      return;
    }
  }

88 89 90 91 92 93 94 95 96 97 98 99 100 101
  // Skia may clip the content with saveLayerBounds (although it's not a
  // guaranteed clip). So we have to provide a big enough saveLayerBounds. To do
  // so, we first remove the offset from paint bounds since it's already in the
  // matrix. Then we round out the bounds because of our
  // RasterCache::GetIntegralTransCTM optimization.
  //
  // Note that the following lines are only accessible when the raster cache is
  // not available (e.g., when we're using the software backend in golden
  // tests).
  SkRect saveLayerBounds;
  paint_bounds()
      .makeOffset(-offset_.fX, -offset_.fY)
      .roundOut(&saveLayerBounds);

102
  Layer::AutoSaveLayer save_layer =
103
      Layer::AutoSaveLayer::Create(context, saveLayerBounds, &paint);
104
  PaintChildren(context);
105 106
}

A
Adam Barth 已提交
107
}  // namespace flow