Commit 5f5daa12 authored by Liquan(Max) Gu's avatar Liquan(Max) Gu Committed by Commit Bot

[FCP++] Refactor CalculateVisualSize in TextPaint and ImagePaint

TextPaintTimingDetector and ImagePaintTimingDetector have the same codes to
calculate the visual size of a rect. We can move this common part into
PaintTimingDetector.

This CL also refactor the logic in CalculateVisualSize for simplification.
The new signature return the size value instead of the rect. By do this, we can
save the logic of getting size from rect in RecordText and RecordImage.

Bug: 869924
Change-Id: Icc2b88db90c1816e24f8ba7446ada701996fc652
Reviewed-on: https://chromium-review.googlesource.com/c/1348859
Commit-Queue: Liquan (Max) Gǔ <maxlg@chromium.org>
Reviewed-by: default avatarSteve Kobes <skobes@chromium.org>
Cr-Commit-Position: refs/heads/master@{#610668}
parent 579d6501
...@@ -134,33 +134,6 @@ void ImagePaintTimingDetector::PopulateTraceValue( ...@@ -134,33 +134,6 @@ void ImagePaintTimingDetector::PopulateTraceValue(
IdentifiersFactory::FrameId(&frame_view_->GetFrame())); IdentifiersFactory::FrameId(&frame_view_->GetFrame()));
} }
IntRect ImagePaintTimingDetector::CalculateTransformedRect(
LayoutRect& invalidated_rect,
const PaintLayer& painting_layer) const {
const auto* local_transform = painting_layer.GetLayoutObject()
.FirstFragment()
.LocalBorderBoxProperties()
.Transform();
const auto* ancestor_transform = painting_layer.GetLayoutObject()
.View()
->FirstFragment()
.LocalBorderBoxProperties()
.Transform();
FloatRect invalidated_rect_abs = FloatRect(invalidated_rect);
if (invalidated_rect_abs.IsEmpty() || invalidated_rect_abs.IsZero())
return IntRect();
DCHECK(local_transform);
DCHECK(ancestor_transform);
GeometryMapper::SourceToDestinationRect(local_transform, ancestor_transform,
invalidated_rect_abs);
IntRect invalidated_rect_in_viewport = RoundedIntRect(invalidated_rect_abs);
ScrollableArea* scrollable_area = frame_view_->GetScrollableArea();
DCHECK(scrollable_area);
IntRect viewport = scrollable_area->VisibleContentRect();
invalidated_rect_in_viewport.Intersect(viewport);
return invalidated_rect_in_viewport;
}
void ImagePaintTimingDetector::OnLargestImagePaintDetected( void ImagePaintTimingDetector::OnLargestImagePaintDetected(
const ImageRecord& largest_image_record) { const ImageRecord& largest_image_record) {
largest_image_paint_ = largest_image_record.first_paint_time_after_loaded; largest_image_paint_ = largest_image_record.first_paint_time_after_loaded;
...@@ -357,14 +330,14 @@ void ImagePaintTimingDetector::RecordImage(const LayoutObject& object, ...@@ -357,14 +330,14 @@ void ImagePaintTimingDetector::RecordImage(const LayoutObject& object,
recorded_node_count_++; recorded_node_count_++;
if (recorded_node_count_ < kImageNodeNumberLimit) { if (recorded_node_count_ < kImageNodeNumberLimit) {
LayoutRect invalidated_rect = object.FirstFragment().VisualRect(); LayoutRect invalidated_rect = object.FirstFragment().VisualRect();
// Do not record first size until invalidated_rect's size becomes // Before the image resource is loaded, <img> has size 0, so we do not
// record the first size until the invalidated rect's size becomes
// non-empty. // non-empty.
if (invalidated_rect.IsEmpty()) if (invalidated_rect.IsEmpty())
return; return;
IntRect invalidated_rect_in_viewport = unsigned rect_size =
CalculateTransformedRect(invalidated_rect, painting_layer); frame_view_->GetPaintTimingDetector().CalculateVisualSize(
int rect_size = invalidated_rect_in_viewport.Height() * invalidated_rect, painting_layer);
invalidated_rect_in_viewport.Width();
if (rect_size == 0) { if (rect_size == 0) {
// When rect_size == 0, it either means the image is size 0 or the image // When rect_size == 0, it either means the image is size 0 or the image
// is out of viewport. Either way, we don't track this image anymore, to // is out of viewport. Either way, we don't track this image anymore, to
......
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
namespace blink { namespace blink {
class PaintLayer; class PaintLayer;
class IntRect;
class LayoutObject; class LayoutObject;
class TracedValue; class TracedValue;
class LocalFrameView; class LocalFrameView;
...@@ -78,8 +77,6 @@ class CORE_EXPORT ImagePaintTimingDetector final ...@@ -78,8 +77,6 @@ class CORE_EXPORT ImagePaintTimingDetector final
void PopulateTraceValue(TracedValue&, void PopulateTraceValue(TracedValue&,
const ImageRecord& first_image_paint, const ImageRecord& first_image_paint,
unsigned report_count) const; unsigned report_count) const;
IntRect CalculateTransformedRect(LayoutRect& visual_rect,
const PaintLayer&) const;
// This is provided for unit test to force invoking swap promise callback. // This is provided for unit test to force invoking swap promise callback.
void ReportSwapTime(unsigned max_frame_index_to_time, void ReportSwapTime(unsigned max_frame_index_to_time,
WebLayerTreeView::SwapResult, WebLayerTreeView::SwapResult,
......
...@@ -163,6 +163,20 @@ TEST_F(ImagePaintTimingDetectorTest, LargestImagePaint_OneImage) { ...@@ -163,6 +163,20 @@ TEST_F(ImagePaintTimingDetectorTest, LargestImagePaint_OneImage) {
EXPECT_TRUE(record->loaded); EXPECT_TRUE(record->loaded);
} }
TEST_F(ImagePaintTimingDetectorTest,
IgnoreImageUntilInvalidatedRectSizeNonZero) {
SetBodyInnerHTML(R"HTML(
<img id="target"></img>
)HTML");
UpdateAllLifecyclePhasesAndInvokeCallbackIfAny();
EXPECT_EQ(CountRecords(), 0u);
SetImageAndPaint("target", 5, 5);
UpdateAllLifecyclePhasesAndInvokeCallbackIfAny();
ImageRecord* record = FindLargestPaintCandidate();
EXPECT_TRUE(record);
EXPECT_EQ(CountRecords(), 1u);
}
TEST_F(ImagePaintTimingDetectorTest, LargestImagePaint_Largest) { TEST_F(ImagePaintTimingDetectorTest, LargestImagePaint_Largest) {
SetBodyInnerHTML(R"HTML( SetBodyInnerHTML(R"HTML(
<img id="smaller"></img> <img id="smaller"></img>
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h" #include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/layout/layout_object.h" #include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/loader/document_loader.h" #include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/core/paint/image_paint_timing_detector.h" #include "third_party/blink/renderer/core/paint/image_paint_timing_detector.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h" #include "third_party/blink/renderer/core/paint/paint_layer.h"
...@@ -59,6 +60,27 @@ void PaintTimingDetector::DidChangePerformanceTiming() { ...@@ -59,6 +60,27 @@ void PaintTimingDetector::DidChangePerformanceTiming() {
loader->DidChangePerformanceTiming(); loader->DidChangePerformanceTiming();
} }
unsigned PaintTimingDetector::CalculateVisualSize(
const LayoutRect& invalidated_rect,
const PaintLayer& painting_layer) const {
// This case should be dealt with outside the function.
DCHECK(!invalidated_rect.IsEmpty());
// As Layout objects live in different transform spaces, the object's rect
// should be projected to the viewport's transform space.
IntRect visual_rect = EnclosedIntRect(invalidated_rect);
painting_layer.GetLayoutObject().FirstFragment().MapRectToFragment(
painting_layer.GetLayoutObject().View()->FirstFragment(), visual_rect);
// A visual rect means the part of the rect that's visible within
// the viewport. We define the size of it as visual size.
ScrollableArea* scrollable_area = frame_view_->GetScrollableArea();
DCHECK(scrollable_area);
IntRect viewport = scrollable_area->VisibleContentRect();
visual_rect.Intersect(viewport);
return visual_rect.Height() * visual_rect.Width();
}
void PaintTimingDetector::Dispose() { void PaintTimingDetector::Dispose() {
text_paint_timing_detector_->Dispose(); text_paint_timing_detector_->Dispose();
} }
......
...@@ -13,6 +13,7 @@ namespace blink { ...@@ -13,6 +13,7 @@ namespace blink {
class LayoutObject; class LayoutObject;
class LocalFrameView; class LocalFrameView;
class PaintLayer; class PaintLayer;
class LayoutRect;
class TextPaintTimingDetector; class TextPaintTimingDetector;
class ImagePaintTimingDetector; class ImagePaintTimingDetector;
...@@ -32,6 +33,8 @@ class CORE_EXPORT PaintTimingDetector ...@@ -32,6 +33,8 @@ class CORE_EXPORT PaintTimingDetector
void NotifyNodeRemoved(const LayoutObject& object); void NotifyNodeRemoved(const LayoutObject& object);
void NotifyPrePaintFinished(); void NotifyPrePaintFinished();
void DidChangePerformanceTiming(); void DidChangePerformanceTiming();
unsigned CalculateVisualSize(const LayoutRect& invalidated_rect,
const PaintLayer& painting_layer) const;
void Dispose(); void Dispose();
TextPaintTimingDetector& GetTextPaintTimingDetector() { TextPaintTimingDetector& GetTextPaintTimingDetector() {
......
...@@ -53,29 +53,6 @@ void TextPaintTimingDetector::PopulateTraceValue( ...@@ -53,29 +53,6 @@ void TextPaintTimingDetector::PopulateTraceValue(
IdentifiersFactory::FrameId(&frame_view_->GetFrame())); IdentifiersFactory::FrameId(&frame_view_->GetFrame()));
} }
IntRect TextPaintTimingDetector::CalculateTransformedRect(
LayoutRect& invalidated_rect,
const PaintLayer& painting_layer) const {
const auto* local_transform = painting_layer.GetLayoutObject()
.FirstFragment()
.LocalBorderBoxProperties()
.Transform();
const auto* ancestor_transform = painting_layer.GetLayoutObject()
.View()
->FirstFragment()
.LocalBorderBoxProperties()
.Transform();
FloatRect invalidated_rect_abs = FloatRect(invalidated_rect);
if (invalidated_rect_abs.IsEmpty() || invalidated_rect_abs.IsZero())
return IntRect();
GeometryMapper::SourceToDestinationRect(local_transform, ancestor_transform,
invalidated_rect_abs);
IntRect invalidated_rect_in_viewport = RoundedIntRect(invalidated_rect_abs);
invalidated_rect_in_viewport.Intersect(
frame_view_->GetScrollableArea()->VisibleContentRect());
return invalidated_rect_in_viewport;
}
void TextPaintTimingDetector::OnLargestTextDetected( void TextPaintTimingDetector::OnLargestTextDetected(
const TextRecord& largest_text_record) { const TextRecord& largest_text_record) {
largest_text_paint_ = largest_text_record.first_paint_time; largest_text_paint_ = largest_text_record.first_paint_time;
...@@ -217,14 +194,13 @@ void TextPaintTimingDetector::RecordText(const LayoutObject& object, ...@@ -217,14 +194,13 @@ void TextPaintTimingDetector::RecordText(const LayoutObject& object,
recorded_node_count_); recorded_node_count_);
return; return;
} }
unsigned rect_size = 0;
LayoutRect invalidated_rect = object.FirstFragment().VisualRect(); LayoutRect invalidated_rect = object.FirstFragment().VisualRect();
int rect_size = 0;
if (!invalidated_rect.IsEmpty()) { if (!invalidated_rect.IsEmpty()) {
IntRect invalidated_rect_in_viewport = rect_size = frame_view_->GetPaintTimingDetector().CalculateVisualSize(
CalculateTransformedRect(invalidated_rect, painting_layer); invalidated_rect, painting_layer);
rect_size = invalidated_rect_in_viewport.Height() *
invalidated_rect_in_viewport.Width();
} }
// When rect_size == 0, it either means invalidated_rect.IsEmpty() or // When rect_size == 0, it either means invalidated_rect.IsEmpty() or
// the text is size 0 or the text is out of viewport. Either way, we don't // the text is size 0 or the text is out of viewport. Either way, we don't
// record their time, to reduce computation. // record their time, to reduce computation.
......
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
namespace blink { namespace blink {
class PaintLayer; class PaintLayer;
class IntRect;
class LayoutObject; class LayoutObject;
class TracedValue; class TracedValue;
class LocalFrameView; class LocalFrameView;
...@@ -70,8 +69,6 @@ class CORE_EXPORT TextPaintTimingDetector final ...@@ -70,8 +69,6 @@ class CORE_EXPORT TextPaintTimingDetector final
void PopulateTraceValue(TracedValue& value, void PopulateTraceValue(TracedValue& value,
const TextRecord& first_text_paint, const TextRecord& first_text_paint,
unsigned candidate_index) const; unsigned candidate_index) const;
IntRect CalculateTransformedRect(LayoutRect& visual_rect,
const PaintLayer& painting_layer) const;
void TimerFired(TimerBase*); void TimerFired(TimerBase*);
void Analyze(); void Analyze();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment