text: // -------------------------------------------------
  // BlinKit - cc Library
  // -------------------------------------------------
  //   File Name: display_item_list.cc
  // Description: DisplayItemList Class
  //      Author: Ziming Li
  //     Created: 2020-12-22
  // -------------------------------------------------
  // Copyright (C) 2020 MingYang Software Technology.
  // -------------------------------------------------
  
  // 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 "cc/paint/display_item_list.h"
  
  #include <stddef.h>
  
  #include <string>
  
  #include "base/trace_event/trace_event.h"
  #include "base/trace_event/trace_event_argument.h"
  #if 0 // BKTODO:
  #include "cc/base/math_util.h"
  #include "cc/debug/picture_debug_util.h"
  #include "cc/paint/solid_color_analyzer.h"
  #endif
  #include "third_party/skia/include/core/SkCanvas.h"
  #include "third_party/skia/include/core/SkPictureRecorder.h"
  #include "ui/gfx/geometry/rect.h"
  #if 0 // BKTODO:
  #include "ui/gfx/geometry/rect_conversions.h"
  #include "ui/gfx/skia_util.h"
  #endif
  
  namespace cc {
  
  namespace {
  
  bool GetCanvasClipBounds(SkCanvas* canvas, gfx::Rect* clip_bounds) {
    SkRect canvas_clip_bounds;
    if (!canvas->getLocalClipBounds(&canvas_clip_bounds))
      return false;
    ASSERT(false); // BKTODO: *clip_bounds = ToEnclosingRect(gfx::SkRectToRectF(canvas_clip_bounds));
    return true;
  }
  
  }  // namespace
  
  DisplayItemList::DisplayItemList(UsageHint usage_hint)
      : usage_hint_(usage_hint) {
    if (usage_hint_ == kTopLevelDisplayItemList) {
      visual_rects_.reserve(1024);
      offsets_.reserve(1024);
      begin_paired_indices_.reserve(32);
    }
  }
  
  DisplayItemList::~DisplayItemList() = default;
  
  void DisplayItemList::Raster(SkCanvas* canvas,
                               ImageProvider* image_provider) const {
    DCHECK(usage_hint_ == kTopLevelDisplayItemList);
    gfx::Rect canvas_playback_rect;
    if (!GetCanvasClipBounds(canvas, &canvas_playback_rect))
      return;
  
    ASSERT(false); // BKTODO:
  #if 0
    std::vector<size_t> offsets = rtree_.Search(canvas_playback_rect);
    paint_op_buffer_.Playback(canvas, PlaybackParams(image_provider), &offsets);
  #endif
  }
  
  void DisplayItemList::Finalize() {
    TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
                 "DisplayItemList::Finalize");
  #if DCHECK_IS_ON()
    // If this fails a call to StartPaint() was not ended.
    DCHECK(!IsPainting());
    // If this fails we had more calls to EndPaintOfPairedBegin() than
    // to EndPaintOfPairedEnd().
    DCHECK(begin_paired_indices_.empty());
    DCHECK_EQ(visual_rects_.size(), offsets_.size());
  #endif
  
    if (usage_hint_ == kTopLevelDisplayItemList) {
      ASSERT(false); // BKTODO:
  #if 0
      rtree_.Build(visual_rects_,
                   [](const std::vector<gfx::Rect>& rects, size_t index) {
                     return rects[index];
                   },
                   [this](const std::vector<gfx::Rect>& rects, size_t index) {
                     // Ignore the given rects, since the payload comes from
                     // offsets. However, the indices match, so we can just index
                     // into offsets.
                     return offsets_[index];
                   });
  #endif
    }
    paint_op_buffer_.ShrinkToFit();
    visual_rects_.clear();
    visual_rects_.shrink_to_fit();
    offsets_.clear();
    offsets_.shrink_to_fit();
    begin_paired_indices_.shrink_to_fit();
  }
  
  size_t DisplayItemList::BytesUsed() const {
    // TODO(jbroman): Does anything else owned by this class substantially
    // contribute to memory usage?
    // TODO(vmpstr): Probably DiscardableImageMap is worth counting here.
    return sizeof(*this) + paint_op_buffer_.bytes_used();
  }
  
  void DisplayItemList::EmitTraceSnapshot() const {
    // BKOMIT: bool include_items;
    TRACE_EVENT_CATEGORY_GROUP_ENABLED(
        TRACE_DISABLED_BY_DEFAULT("cc.debug.display_items"), &include_items);
    TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
        TRACE_DISABLED_BY_DEFAULT("cc.debug.display_items") ","
        TRACE_DISABLED_BY_DEFAULT("cc.debug.picture") ","
        TRACE_DISABLED_BY_DEFAULT("devtools.timeline.picture"),
        "cc::DisplayItemList", TRACE_ID_LOCAL(this),
        CreateTracedValue(include_items));
  }
  
  #if 0 // BKTODO:
  std::unique_ptr<base::trace_event::TracedValue>
  DisplayItemList::CreateTracedValue(bool include_items) const {
    auto state = std::make_unique<base::trace_event::TracedValue>();
    state->BeginDictionary("params");
  
    if (include_items) {
      state->BeginArray("items");
  
      PlaybackParams params(nullptr, SkMatrix::I());
      const auto& bounds = rtree_.GetAllBoundsForTracing();
      size_t i = 0;
      for (const PaintOp* op : PaintOpBuffer::Iterator(&paint_op_buffer_)) {
        state->BeginDictionary();
        state->SetString("name", PaintOpTypeToString(op->GetType()));
        MathUtil::AddToTracedValue("visual_rect", bounds[i++], state.get());
  
        SkPictureRecorder recorder;
        SkCanvas* canvas =
            recorder.beginRecording(gfx::RectToSkRect(rtree_.GetBounds()));
        op->Raster(canvas, params);
        sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture();
  
        if (picture->approximateOpCount()) {
          std::string b64_picture;
          PictureDebugUtil::SerializeAsBase64(picture.get(), &b64_picture);
          state->SetString("skp64", b64_picture);
        }
  
        state->EndDictionary();
      }
  
      state->EndArray();  // "items".
    }
  
    MathUtil::AddToTracedValue("layer_rect", rtree_.GetBounds(), state.get());
    state->EndDictionary();  // "params".
  
    {
      SkPictureRecorder recorder;
      gfx::Rect bounds = rtree_.GetBounds();
      SkCanvas* canvas = recorder.beginRecording(gfx::RectToSkRect(bounds));
      canvas->translate(-bounds.x(), -bounds.y());
      canvas->clipRect(gfx::RectToSkRect(bounds));
      Raster(canvas);
      sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture();
  
      std::string b64_picture;
      PictureDebugUtil::SerializeAsBase64(picture.get(), &b64_picture);
      state->SetString("skp64", b64_picture);
    }
    return state;
  }
  #endif
  
  void DisplayItemList::GenerateDiscardableImagesMetadata() {
    DCHECK(usage_hint_ == kTopLevelDisplayItemList);
    ASSERT(false); // BKTODO: image_map_.Generate(&paint_op_buffer_, rtree_.GetBounds());
  }
  
  void DisplayItemList::Reset() {
  #if DCHECK_IS_ON()
    DCHECK(!IsPainting());
    DCHECK(begin_paired_indices_.empty());
  #endif
  
  #if 0 // BKTODO:
    rtree_.Reset();
    image_map_.Reset();
  #endif
    paint_op_buffer_.Reset();
    visual_rects_.clear();
    visual_rects_.shrink_to_fit();
    offsets_.clear();
    offsets_.shrink_to_fit();
    begin_paired_indices_.clear();
    begin_paired_indices_.shrink_to_fit();
  }
  
  sk_sp<PaintRecord> DisplayItemList::ReleaseAsRecord() {
    sk_sp<PaintRecord> record =
        sk_make_sp<PaintOpBuffer>(std::move(paint_op_buffer_));
  
    Reset();
    return record;
  }
  
  bool DisplayItemList::GetColorIfSolidInRect(const gfx::Rect& rect,
                                              SkColor* color,
                                              int max_ops_to_analyze) {
    DCHECK(usage_hint_ == kTopLevelDisplayItemList);
    std::vector<size_t>* offsets_to_use = nullptr;
    std::vector<size_t> offsets;
    ASSERT(false); // BKTODO:
  #if 0
    if (!rect.Contains(rtree_.GetBounds())) {
      offsets = rtree_.Search(rect);
      offsets_to_use = &offsets;
    }
  
    base::Optional<SkColor> solid_color =
        SolidColorAnalyzer::DetermineIfSolidColor(
            &paint_op_buffer_, rect, max_ops_to_analyze, offsets_to_use);
    if (solid_color) {
      *color = *solid_color;
      return true;
    }
  #endif
    return false;
  }
  
  }  // namespace cc
  