diff options
Diffstat (limited to 'chromium/ui/gfx')
102 files changed, 967 insertions, 1264 deletions
diff --git a/chromium/ui/gfx/BUILD.gn b/chromium/ui/gfx/BUILD.gn index af6bc49befd..a32cc340d4a 100644 --- a/chromium/ui/gfx/BUILD.gn +++ b/chromium/ui/gfx/BUILD.gn @@ -306,8 +306,6 @@ component("gfx") { sources += [ "platform_font_skia.cc", "platform_font_skia.h", - "skia_font_delegate.cc", - "skia_font_delegate.h", ] } @@ -367,6 +365,7 @@ component("gfx") { if (is_win) { libs = [ "setupapi.lib", + "dwmapi.lib", "dwrite.lib", ] deps += [ "//components/crash/core/common" ] @@ -382,6 +381,9 @@ component("gfx") { } # Linux. + if (is_linux) { + deps += [ "//ui/linux:linux_ui" ] + } if (is_linux || is_chromeos) { deps += [ "//third_party/fontconfig" ] } @@ -419,6 +421,8 @@ component("color_space") { "color_transform.h", "display_color_spaces.cc", "display_color_spaces.h", + "hdr_metadata.cc", + "hdr_metadata.h", "hdr_static_metadata.cc", "hdr_static_metadata.h", "icc_profile.cc", @@ -543,8 +547,6 @@ source_set("memory_buffer_sources") { "gpu_fence.h", "gpu_fence_handle.cc", "gpu_fence_handle.h", - "hdr_metadata.cc", - "hdr_metadata.h", "native_pixmap.h", "overlay_priority_hint.h", "overlay_transform.h", @@ -670,27 +672,6 @@ static_library("test_support") { } } -if (is_mac) { - component("gfx_io_surface_hdr_metadata") { - sources = [ - "mac/io_surface_hdr_metadata.cc", - "mac/io_surface_hdr_metadata.h", - ] - defines = [ "IS_GFX_IO_SURFACE_HDR_METADATA_IMPL" ] - - # This is a separate component from the other sources because it depends on - # the mojo serialize and deserialize methods. - deps = [ - ":gfx", - "//ui/gfx/mojom:mojom", - ] - frameworks = [ - "CoreFoundation.framework", - "IOSurface.framework", - ] - } -} - test("gfx_unittests") { sources = [ "animation/keyframe/keyframe_animation_unittest.cc", @@ -711,11 +692,11 @@ test("gfx_unittests") { "text_elider_unittest.cc", "text_utils_unittest.cc", ] + if (is_linux) { + sources += [ "font_render_params_linux_unittest.cc" ] + } if (is_linux || is_chromeos) { - sources += [ - "font_fallback_linux_unittest.cc", - "font_render_params_linux_unittest.cc", - ] + sources += [ "font_fallback_linux_unittest.cc" ] } if (is_mac) { sources += [ @@ -850,10 +831,6 @@ test("gfx_unittests") { deps += [ "//ui/resources:ui_test_pak_bundle_data" ] } - if (is_mac) { - deps += [ ":gfx_io_surface_hdr_metadata" ] - } - if (is_android) { deps += [ "//ui/android:ui_java" ] } @@ -904,6 +881,10 @@ test("gfx_unittests") { ] } + if (is_linux) { + deps += [ "//ui/linux:test_support" ] + } + if (is_linux || is_chromeos) { sources += [ "linux/fontconfig_util_unittest.cc", @@ -913,11 +894,10 @@ test("gfx_unittests") { } if (is_fuchsia) { - # TODO(https://crbug.com/1287051): fuchsia.sys.Launcher is used to launch - # fuchsia-pkg://fuchsia.com/fonts#meta/fonts.cmx with specific test - # args. - use_cfv2 = false - deps += [ "//skia:test_fonts" ] + use_cfv1 = false + deps += [ "//skia:test_fonts_cfv2" ] + additional_manifest_fragments = + [ "//build/config/fuchsia/test/test_fonts.shard.test-cml" ] } } diff --git a/chromium/ui/gfx/DEPS b/chromium/ui/gfx/DEPS index bff94453a22..73262fa7085 100644 --- a/chromium/ui/gfx/DEPS +++ b/chromium/ui/gfx/DEPS @@ -8,6 +8,7 @@ include_rules = [ "+third_party/skia", "+third_party/test_fonts", "+ui/ios", + "+ui/linux", "+ui/ozone/buildflags.h", "-testing/gmock", diff --git a/chromium/ui/gfx/android/java_bitmap.cc b/chromium/ui/gfx/android/java_bitmap.cc index 1b9d9e025a0..6aadd5b7ca6 100644 --- a/chromium/ui/gfx/android/java_bitmap.cc +++ b/chromium/ui/gfx/android/java_bitmap.cc @@ -133,7 +133,7 @@ SkBitmap CreateSkBitmapFromJavaBitmap(const JavaBitmap& jbitmap) { // compositor relies on this. SkPixmap src = WrapJavaBitmapAsPixmap(jbitmap); const size_t min_row_bytes = src.info().minRowBytes(); - const size_t row_bytes = base::bits::AlignUp(min_row_bytes, 4u); + const size_t row_bytes = base::bits::AlignUp(min_row_bytes, size_t{4}); SkBitmap skbitmap; skbitmap.allocPixels(src.info(), row_bytes); diff --git a/chromium/ui/gfx/animation/BUILD.gn b/chromium/ui/gfx/animation/BUILD.gn index 78761079e49..b241d3c4422 100644 --- a/chromium/ui/gfx/animation/BUILD.gn +++ b/chromium/ui/gfx/animation/BUILD.gn @@ -45,12 +45,8 @@ component("animation") { sources += [ "animation_win.cc" ] } - if (is_linux || is_chromeos_lacros) { - sources += [ - "animation_linux.cc", - "animation_settings_provider_linux.cc", - "animation_settings_provider_linux.h", - ] + if (is_linux) { + sources += [ "animation_linux.cc" ] } if (!is_android) { @@ -84,5 +80,9 @@ component("animation") { deps += [ "//ui/gfx:gfx_jni_headers" ] } + if (is_linux) { + deps += [ "//ui/linux:linux_ui" ] + } + defines = [ "ANIMATION_IMPLEMENTATION" ] } diff --git a/chromium/ui/gfx/animation/animation.cc b/chromium/ui/gfx/animation/animation.cc index e381b4fea57..fc4b7e469ae 100644 --- a/chromium/ui/gfx/animation/animation.cc +++ b/chromium/ui/gfx/animation/animation.cc @@ -82,8 +82,8 @@ int Animation::CurrentValueBetween(int start, int target) const { gfx::Rect Animation::CurrentValueBetween(const gfx::Rect& start_bounds, const gfx::Rect& target_bounds) const { - return Tween::RectValueBetween( - GetCurrentValue(), start_bounds, target_bounds); + return Tween::RectValueBetween(GetCurrentValue(), start_bounds, + target_bounds); } void Animation::SetContainer(AnimationContainer* container) { @@ -112,8 +112,8 @@ bool Animation::ShouldRenderRichAnimation() { RichAnimationRenderMode::FORCE_ENABLED; } -#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH) || \ - BUILDFLAG(IS_IOS) || BUILDFLAG(IS_FUCHSIA) +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_IOS) || \ + BUILDFLAG(IS_FUCHSIA) // static bool Animation::ShouldRenderRichAnimationImpl() { return true; @@ -137,7 +137,7 @@ void Animation::UpdatePrefersReducedMotion() { prefers_reduced_motion_ = false; } #endif // !BUILDFLAG(IS_ANDROID) -#endif // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH) || +#endif // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS) || // BUILDFLAG(IS_IOS) || BUILDFLAG(IS_FUCHSIA) // static diff --git a/chromium/ui/gfx/animation/animation_linux.cc b/chromium/ui/gfx/animation/animation_linux.cc index 0bcce53e57f..9216c40313c 100644 --- a/chromium/ui/gfx/animation/animation_linux.cc +++ b/chromium/ui/gfx/animation/animation_linux.cc @@ -4,17 +4,17 @@ #include "ui/gfx/animation/animation.h" -#include "ui/gfx/animation/animation_settings_provider_linux.h" +#include "ui/linux/linux_ui.h" namespace gfx { namespace { -// GTK only has a global setting for whether animations should be enabled. So -// use it for all of the specific settings that Chrome needs. +// Linux toolkits only have a global setting for whether animations should be +// enabled. So use it for all of the specific settings that Chrome needs. bool AnimationsEnabled() { - auto* provider = AnimationSettingsProviderLinux::GetInstance(); - return !provider || provider->AnimationsEnabled(); + auto* linux_ui = ui::LinuxUi::instance(); + return !linux_ui || linux_ui->AnimationsEnabled(); } } // namespace diff --git a/chromium/ui/gfx/animation/animation_settings_provider_linux.cc b/chromium/ui/gfx/animation/animation_settings_provider_linux.cc deleted file mode 100644 index e4d4c6c2b67..00000000000 --- a/chromium/ui/gfx/animation/animation_settings_provider_linux.cc +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2020 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 "ui/gfx/animation/animation_settings_provider_linux.h" - -#include "base/check_op.h" - -namespace gfx { - -// static -AnimationSettingsProviderLinux* AnimationSettingsProviderLinux::instance_ = - nullptr; - -// static -AnimationSettingsProviderLinux* AnimationSettingsProviderLinux::GetInstance() { - return instance_; -} - -AnimationSettingsProviderLinux::AnimationSettingsProviderLinux() { - DCHECK(!instance_); - instance_ = this; -} - -AnimationSettingsProviderLinux::~AnimationSettingsProviderLinux() { - DCHECK_EQ(instance_, this); - instance_ = nullptr; -} - -} // namespace gfx diff --git a/chromium/ui/gfx/animation/animation_settings_provider_linux.h b/chromium/ui/gfx/animation/animation_settings_provider_linux.h deleted file mode 100644 index 8664544cc9f..00000000000 --- a/chromium/ui/gfx/animation/animation_settings_provider_linux.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2020 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. - -#ifndef UI_GFX_ANIMATION_ANIMATION_SETTINGS_PROVIDER_LINUX_H_ -#define UI_GFX_ANIMATION_ANIMATION_SETTINGS_PROVIDER_LINUX_H_ - -#include "ui/gfx/animation/animation_export.h" - -namespace gfx { - -class ANIMATION_EXPORT AnimationSettingsProviderLinux { - public: - AnimationSettingsProviderLinux(const AnimationSettingsProviderLinux&) = - delete; - AnimationSettingsProviderLinux& operator=( - const AnimationSettingsProviderLinux&) = delete; - - virtual ~AnimationSettingsProviderLinux(); - - // Indicates if animations are enabled by the toolkit. - virtual bool AnimationsEnabled() const = 0; - - static AnimationSettingsProviderLinux* GetInstance(); - - protected: - AnimationSettingsProviderLinux(); - - private: - static AnimationSettingsProviderLinux* instance_; -}; - -} // namespace gfx - -#endif // UI_GFX_ANIMATION_ANIMATION_SETTINGS_PROVIDER_LINUX_H_ diff --git a/chromium/ui/gfx/animation/tween.cc b/chromium/ui/gfx/animation/tween.cc index c348a312113..15931c801f0 100644 --- a/chromium/ui/gfx/animation/tween.cc +++ b/chromium/ui/gfx/animation/tween.cc @@ -149,9 +149,41 @@ uint8_t BlendColorComponents(uint8_t start, return FloatToColorByte(blended_premultiplied / blended_alpha); } +float BlendColorComponentsFloat(float start, + float target, + float start_alpha, + float target_alpha, + float blended_alpha, + double progress) { + // Since progress can be outside [0, 1], blending can produce a value outside + // [0, 1]. + float blended_premultiplied = Tween::FloatValueBetween( + progress, start * start_alpha, target * target_alpha); + return blended_premultiplied / blended_alpha; +} + } // namespace // static +SkColor4f Tween::ColorValueBetween(double value, + SkColor4f start, + SkColor4f target) { + float start_a = start.fA; + float target_a = target.fA; + float blended_a = FloatValueBetween(value, start_a, target_a); + if (blended_a <= 0.f) + return SkColors::kTransparent; + blended_a = std::min(blended_a, 1.f); + + auto blended_r = BlendColorComponentsFloat(start.fR, target.fR, start_a, + target_a, blended_a, value); + auto blended_g = BlendColorComponentsFloat(start.fG, target.fG, start_a, + target_a, blended_a, value); + auto blended_b = BlendColorComponentsFloat(start.fB, target.fB, start_a, + target_a, blended_a, value); + + return SkColor4f{blended_r, blended_g, blended_b, blended_a}; +} SkColor Tween::ColorValueBetween(double value, SkColor start, SkColor target) { float start_a = SkColorGetA(start) / 255.f; float target_a = SkColorGetA(target) / 255.f; diff --git a/chromium/ui/gfx/animation/tween.h b/chromium/ui/gfx/animation/tween.h index 80a4c60235c..8c6c52803df 100644 --- a/chromium/ui/gfx/animation/tween.h +++ b/chromium/ui/gfx/animation/tween.h @@ -107,6 +107,9 @@ class ANIMATION_EXPORT Tween { static double CalculateValue(Type type, double state); // Conveniences for getting a value between a start and end point. + static SkColor4f ColorValueBetween(double value, + SkColor4f start, + SkColor4f target); static SkColor ColorValueBetween(double value, SkColor start, SkColor target); static double DoubleValueBetween(double value, double start, double target); static float FloatValueBetween(double value, float start, float target); diff --git a/chromium/ui/gfx/bidi_line_iterator.h b/chromium/ui/gfx/bidi_line_iterator.h index 751a1b2f760..bac09180e51 100644 --- a/chromium/ui/gfx/bidi_line_iterator.h +++ b/chromium/ui/gfx/bidi_line_iterator.h @@ -9,7 +9,6 @@ #include <string> #include "base/i18n/rtl.h" -#include "base/memory/raw_ptr.h" #include "third_party/icu/source/common/unicode/ubidi.h" #include "third_party/icu/source/common/unicode/uchar.h" #include "ui/gfx/gfx_export.h" diff --git a/chromium/ui/gfx/break_list.h b/chromium/ui/gfx/break_list.h index 19c947f5afa..5e872cc33a6 100644 --- a/chromium/ui/gfx/break_list.h +++ b/chromium/ui/gfx/break_list.h @@ -28,8 +28,8 @@ template <typename T> class BreakList { public: // The break type and const iterator, typedef'ed for convenience. - typedef std::pair<size_t, T> Break; - typedef typename std::vector<Break>::const_iterator const_iterator; + using Break = std::pair<size_t, T>; + using const_iterator = typename std::vector<Break>::const_iterator; // Initialize a break at position 0 with the default or supplied |value|. BreakList(); @@ -38,22 +38,27 @@ class BreakList { const std::vector<Break>& breaks() const { return breaks_; } // Clear the breaks and set a break at position 0 with the supplied |value|. - void SetValue(T value); + // Returns whether or not the breaks changed while applying the |value|. + bool SetValue(T value); // Adjust the breaks to apply |value| over the supplied |range|. - void ApplyValue(T value, const Range& range); + // Range |range| must be between [0, max_). + // Returns true if the breaks changed while applying the |value|. + bool ApplyValue(T value, const Range& range); // Set the max position and trim any breaks at or beyond that position. void SetMax(size_t max); size_t max() const { return max_; } - // Get the break applicable to |position| (at or preceeding |position|). - typename std::vector<Break>::iterator GetBreak(size_t position); - typename std::vector<Break>::const_iterator GetBreak(size_t position) const; + // Get the break applicable to |position| (at or preceding |position|). + // |position| must be between [0, max_). + // Returns a valid iterator. Can't return |break_.end()|. + const_iterator GetBreak(size_t position) const; // Get the range of the supplied break; returns the break's start position and // the next break's start position (or |max_| for the terminal break). - Range GetRange(const typename BreakList<T>::const_iterator& i) const; + // Iterator |i| must be valid and must not be |break_.end()|. + Range GetRange(const const_iterator& i) const; // Comparison functions for testing purposes. bool EqualsValueForTesting(T value) const; @@ -66,38 +71,46 @@ class BreakList { #endif std::vector<Break> breaks_; - size_t max_; + size_t max_ = 0; }; -template<class T> -BreakList<T>::BreakList() : breaks_(1, Break(0, T())), max_(0) { -} +template <class T> +BreakList<T>::BreakList() : breaks_(1, Break(0, T())) {} -template<class T> -BreakList<T>::BreakList(T value) : breaks_(1, Break(0, value)), max_(0) { -} +template <class T> +BreakList<T>::BreakList(T value) : breaks_(1, Break(0, value)) {} + +template <class T> +bool BreakList<T>::SetValue(T value) { + // Return false if setting |value| does not change the breaks. + if (breaks_.size() == 1 && breaks_[0].second == value) + return false; -template<class T> -void BreakList<T>::SetValue(T value) { breaks_.clear(); breaks_.push_back(Break(0, value)); + return true; } -template<class T> -void BreakList<T>::ApplyValue(T value, const Range& range) { +template <class T> +bool BreakList<T>::ApplyValue(T value, const Range& range) { if (!range.IsValid() || range.is_empty()) - return; + return false; DCHECK(!breaks_.empty()); DCHECK(!range.is_reversed()); DCHECK(Range(0, static_cast<uint32_t>(max_)).Contains(range)); + // Return false if setting |value| does not change the breaks. + const_iterator start = GetBreak(range.start()); + if (start->second == value && GetRange(start).Contains(range)) + return false; + // Erase any breaks in |range|, then add start and end breaks as needed. - typename std::vector<Break>::iterator start = GetBreak(range.start()); start += start->first < range.start() ? 1 : 0; - typename std::vector<Break>::iterator end = GetBreak(range.end()); + const_iterator end = + range.end() == max_ ? breaks_.cend() - 1 : GetBreak(range.end()); T trailing_value = end->second; - typename std::vector<Break>::iterator i = - start == breaks_.end() ? start : breaks_.erase(start, end + 1); + const_iterator i = + start == breaks_.cend() ? start : breaks_.erase(start, end + 1); if (range.start() == 0 || (i - 1)->second != value) i = breaks_.insert(i, Break(range.start(), value)) + 1; if (trailing_value != value && range.end() != max_) @@ -106,13 +119,18 @@ void BreakList<T>::ApplyValue(T value, const Range& range) { #ifndef NDEBUG CheckBreaks(); #endif + + return true; } template<class T> void BreakList<T>::SetMax(size_t max) { - typename std::vector<Break>::iterator i = GetBreak(max); - i += (i == breaks_.begin() || i->first < max) ? 1 : 0; - breaks_.erase(i, breaks_.end()); + if (max < max_) { + const_iterator i = GetBreak(max); + if (i == breaks_.begin() || i->first < max) + i++; + breaks_.erase(i, breaks_.end()); + } max_ = max; #ifndef NDEBUG @@ -120,26 +138,26 @@ void BreakList<T>::SetMax(size_t max) { #endif } -template<class T> -typename std::vector<std::pair<size_t, T> >::iterator BreakList<T>::GetBreak( - size_t position) { - typename std::vector<Break>::iterator i = breaks_.end() - 1; - for (; i != breaks_.begin() && i->first > position; --i); - return i; -} - -template<class T> -typename std::vector<std::pair<size_t, T> >::const_iterator - BreakList<T>::GetBreak(size_t position) const { - typename std::vector<Break>::const_iterator i = breaks_.end() - 1; - for (; i != breaks_.begin() && i->first > position; --i); - return i; +template <class T> +typename BreakList<T>::const_iterator BreakList<T>::GetBreak( + size_t position) const { + DCHECK(!breaks_.empty()); + DCHECK_LT(position, max_); + // Find the iterator with a 'strictly greater' position and return the + // previous one. + return std::upper_bound(breaks_.cbegin(), breaks_.cend(), position, + [](size_t offset, const Break& value) { + return offset < value.first; + }) - + 1; } template<class T> Range BreakList<T>::GetRange( const typename BreakList<T>::const_iterator& i) const { - const typename BreakList<T>::const_iterator next = i + 1; + // BreakLists are never empty. Iterator should always be valid. + DCHECK(i != breaks_.end()); + const const_iterator next = i + 1; return Range(i->first, next == breaks_.end() ? max_ : next->first); } @@ -161,6 +179,7 @@ bool BreakList<T>::EqualsForTesting(const std::vector<Break>& breaks) const { #ifndef NDEBUG template <class T> void BreakList<T>::CheckBreaks() { + DCHECK(!breaks_.empty()) << "BreakList cannot be empty"; DCHECK_EQ(breaks_[0].first, 0U) << "The first break must be at position 0."; for (size_t i = 0; i < breaks_.size() - 1; ++i) { DCHECK_LT(breaks_[i].first, breaks_[i + 1].first) << "Break out of order."; diff --git a/chromium/ui/gfx/break_list_unittest.cc b/chromium/ui/gfx/break_list_unittest.cc index c862df9c44c..e58aac16d6b 100644 --- a/chromium/ui/gfx/break_list_unittest.cc +++ b/chromium/ui/gfx/break_list_unittest.cc @@ -28,6 +28,21 @@ TEST_F(BreakListTest, SetValue) { EXPECT_TRUE(color_breaks.EqualsValueForTesting(SK_ColorBLACK)); } +TEST_F(BreakListTest, SetValueChanged) { + BreakList<bool> breaks(false); + EXPECT_FALSE(breaks.SetValue(false)); + EXPECT_TRUE(breaks.SetValue(true)); + EXPECT_FALSE(breaks.SetValue(true)); + EXPECT_TRUE(breaks.SetValue(false)); + + const size_t max = 99; + breaks.SetMax(max); + breaks.ApplyValue(true, Range(0, 2)); + breaks.ApplyValue(true, Range(3, 6)); + EXPECT_TRUE(breaks.SetValue(false)); + EXPECT_FALSE(breaks.SetValue(false)); +} + TEST_F(BreakListTest, ApplyValue) { BreakList<bool> breaks(false); const size_t max = 99; @@ -102,6 +117,27 @@ TEST_F(BreakListTest, ApplyValue) { EXPECT_TRUE(breaks.EqualsForTesting(overlap)); } +TEST_F(BreakListTest, ApplyValueChanged) { + BreakList<bool> breaks(false); + const size_t max = 99; + breaks.SetMax(max); + + // Set two ranges. + EXPECT_TRUE(breaks.ApplyValue(true, Range(0, 5))); + EXPECT_TRUE(breaks.ApplyValue(true, Range(9, 10))); + + // Setting sub-ranges should be a no-op. + EXPECT_FALSE(breaks.ApplyValue(true, Range(0, 2))); + EXPECT_FALSE(breaks.ApplyValue(true, Range(1, 3))); + + // Merge the two ranges. + EXPECT_TRUE(breaks.ApplyValue(true, Range(2, 10))); + + // Setting sub-ranges should be a no-op. + EXPECT_FALSE(breaks.ApplyValue(true, Range(0, 2))); + EXPECT_FALSE(breaks.ApplyValue(true, Range(1, 3))); +} + TEST_F(BreakListTest, SetMax) { // Ensure values adjust to accommodate max position changes. BreakList<bool> breaks(false); @@ -144,17 +180,9 @@ TEST_F(BreakListTest, GetBreakAndRange) { size_t break_index; Range range; } cases[] = { - { 0, 0, Range(0, 1) }, - { 1, 1, Range(1, 2) }, - { 2, 2, Range(2, 4) }, - { 3, 2, Range(2, 4) }, - { 4, 3, Range(4, 6) }, - { 5, 3, Range(4, 6) }, - { 6, 4, Range(6, 8) }, - { 7, 4, Range(6, 8) }, - // Positions at or beyond the max simply return the last break and range. - { 8, 4, Range(6, 8) }, - { 9, 4, Range(6, 8) }, + {0, 0, Range(0, 1)}, {1, 1, Range(1, 2)}, {2, 2, Range(2, 4)}, + {3, 2, Range(2, 4)}, {4, 3, Range(4, 6)}, {5, 3, Range(4, 6)}, + {6, 4, Range(6, 8)}, {7, 4, Range(6, 8)}, }; for (size_t i = 0; i < std::size(cases); ++i) { diff --git a/chromium/ui/gfx/canvas.cc b/chromium/ui/gfx/canvas.cc index 8b525dcd3db..08925029f28 100644 --- a/chromium/ui/gfx/canvas.cc +++ b/chromium/ui/gfx/canvas.cc @@ -162,7 +162,7 @@ void Canvas::DrawColor(SkColor color) { } void Canvas::DrawColor(SkColor color, SkBlendMode mode) { - canvas_->drawColor(color, mode); + canvas_->drawColor(SkColor4f::FromColor(color), mode); } void Canvas::FillRect(const Rect& rect, SkColor color) { diff --git a/chromium/ui/gfx/color_conversion_sk_filter_cache.cc b/chromium/ui/gfx/color_conversion_sk_filter_cache.cc index 49c0934dff6..6c9a3a32c95 100644 --- a/chromium/ui/gfx/color_conversion_sk_filter_cache.cc +++ b/chromium/ui/gfx/color_conversion_sk_filter_cache.cc @@ -21,9 +21,6 @@ namespace gfx { namespace { -const base::Feature kToneMappingV2{"ToneMappingV2", - base::FEATURE_ENABLED_BY_DEFAULT}; - // Additional YUV information to skia renderer to draw 9- and 10- bits color. struct YUVInput { float offset = 0.f; @@ -39,6 +36,7 @@ bool ColorConversionSkFilterCache::Key::Key::operator==( const Key& other) const { return src == other.src && dst == other.dst && sdr_max_luminance_nits == other.sdr_max_luminance_nits && + src_hdr_metadata == other.src_hdr_metadata && dst_max_luminance_relative == other.dst_max_luminance_relative; } @@ -53,12 +51,15 @@ bool ColorConversionSkFilterCache::Key::operator<(const Key& other) const { other.dst_max_luminance_relative); } -ColorConversionSkFilterCache::Key::Key(const gfx::ColorSpace& src, - const gfx::ColorSpace& dst, - float sdr_max_luminance_nits, - float dst_max_luminance_relative) +ColorConversionSkFilterCache::Key::Key( + const gfx::ColorSpace& src, + const gfx::ColorSpace& dst, + absl::optional<gfx::HDRMetadata> src_hdr_metadata, + float sdr_max_luminance_nits, + float dst_max_luminance_relative) : src(src), dst(dst), + src_hdr_metadata(src_hdr_metadata), sdr_max_luminance_nits(sdr_max_luminance_nits), dst_max_luminance_relative(dst_max_luminance_relative) {} @@ -67,14 +68,16 @@ sk_sp<SkColorFilter> ColorConversionSkFilterCache::Get( const gfx::ColorSpace& dst, float resource_offset, float resource_multiplier, + absl::optional<gfx::HDRMetadata> src_hdr_metadata, float sdr_max_luminance_nits, float dst_max_luminance_relative) { // Set unused parameters to bogus values, so that they do not result in // different keys for the same conversion. if (!src.IsToneMappedByDefault()) { - // If the source is not going to be tone mapped, then - // `dst_max_luminance_relative` will not be used, so set it to a nonsense - // value. + // If the source is not going to be tone mapped, then `src_hdr_metadata` + // and `dst_max_luminance_relative` will not be used, so set them nonsense + // values. + src_hdr_metadata = absl::nullopt; dst_max_luminance_relative = 0; // If neither source nor destination will use `sdr_max_luminance_nits`, then @@ -84,25 +87,20 @@ sk_sp<SkColorFilter> ColorConversionSkFilterCache::Get( } } - const Key key(src, dst, sdr_max_luminance_nits, dst_max_luminance_relative); + const Key key(src, dst, src_hdr_metadata, sdr_max_luminance_nits, + dst_max_luminance_relative); sk_sp<SkRuntimeEffect>& effect = cache_[key]; if (!effect) { gfx::ColorTransform::Options options; - - static const bool tone_mapping_v2_enabled = - base::FeatureList::IsEnabled(kToneMappingV2); - if (tone_mapping_v2_enabled) - options.tone_map_pq_and_hlg_to_dst = true; - else - options.tone_map_pq_and_hlg_to_sdr = dst_max_luminance_relative == 1.f; - + options.tone_map_pq_and_hlg_to_dst = true; options.sdr_max_luminance_nits = key.sdr_max_luminance_nits; // TODO(https://crbug.com/1286076): Ensure that, when tone mapping using // `dst_max_luminance_relative` is implemented, the gfx::ColorTransform's // SkShaderSource not depend on that parameter (rather, that it be left // as a uniform in the shader). If that is not the case, then it will need // to be part of the key. + options.src_hdr_metadata = src_hdr_metadata; options.dst_max_luminance_relative = dst_max_luminance_relative; std::unique_ptr<gfx::ColorTransform> transform = gfx::ColorTransform::NewColorTransform(src, dst, options); @@ -150,11 +148,15 @@ sk_sp<SkImage> ColorConversionSkFilterCache::ConvertImage( sk_sp<SkColorSpace> target_color_space, float sdr_max_luminance_nits, float dst_max_luminance_relative, + bool enable_tone_mapping, GrDirectContext* context) { sk_sp<SkColorSpace> image_sk_color_space = image->refColorSpace(); if (!image_sk_color_space) return image->makeColorSpace(target_color_space, context); + if (!enable_tone_mapping) + return image->makeColorSpace(target_color_space, context); + gfx::ColorSpace image_color_space(*image_sk_color_space); switch (image_color_space.GetTransferID()) { case ColorSpace::TransferID::PQ: @@ -200,7 +202,8 @@ sk_sp<SkImage> ColorConversionSkFilterCache::ConvertImage( sk_sp<SkColorFilter> filter = Get(image_color_space, gfx::ColorSpace(*target_color_space), /*resource_offset=*/0, /*resource_multiplier=*/1, - sdr_max_luminance_nits, dst_max_luminance_relative); + /*src_hdr_metadata=*/absl::nullopt, sdr_max_luminance_nits, + dst_max_luminance_relative); SkPaint paint; paint.setBlendMode(SkBlendMode::kSrc); paint.setColorFilter(filter); diff --git a/chromium/ui/gfx/color_conversion_sk_filter_cache.h b/chromium/ui/gfx/color_conversion_sk_filter_cache.h index 4dd1ecbbc93..add7773f132 100644 --- a/chromium/ui/gfx/color_conversion_sk_filter_cache.h +++ b/chromium/ui/gfx/color_conversion_sk_filter_cache.h @@ -6,10 +6,12 @@ #define UI_GFX_COLOR_CONVERSION_SK_FILTER_CACHE_H_ #include "base/containers/flat_map.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/skia/include/core/SkRefCnt.h" #include "ui/gfx/color_space.h" #include "ui/gfx/color_space_export.h" #include "ui/gfx/gfx_export.h" +#include "ui/gfx/hdr_metadata.h" class GrDirectContext; class SkImage; @@ -27,14 +29,15 @@ class COLOR_SPACE_EXPORT ColorConversionSkFilterCache { ~ColorConversionSkFilterCache(); // Retrieve an SkColorFilter to transform `src` to `dst`. The filter also - // applies the offset `resource_offset` and then scales by - // `resource_multiplier`. - // TODO(https://crbug.com/1286076): Apply tone mapping using - // `sdr_max_luminance_nits` and `dst_max_luminance_relative`. + // applies the offset `src_resource_offset` and then scales by + // `src_resource_multiplier`. Apply tone mapping of `src` is HLG or PQ, + // using `sdr_max_luminance_nits`, `src_hdr_metadata`, and + // `dst_max_luminance_relative` as parameters. sk_sp<SkColorFilter> Get(const gfx::ColorSpace& src, const gfx::ColorSpace& dst, float resource_offset, float resource_multiplier, + absl::optional<gfx::HDRMetadata> src_hdr_metadata, float sdr_max_luminance_nits, float dst_max_luminance_relative); @@ -50,17 +53,20 @@ class COLOR_SPACE_EXPORT ColorConversionSkFilterCache { sk_sp<SkColorSpace> target_color_space, float sdr_max_luminance_nits, float dst_max_luminance_relative, + bool enable_tone_mapping, GrDirectContext* context); public: struct Key { Key(const gfx::ColorSpace& src, const gfx::ColorSpace& dst, + absl::optional<gfx::HDRMetadata> src_hdr_metadata, float sdr_max_luminance_nits, float dst_max_luminance_relative); gfx::ColorSpace src; gfx::ColorSpace dst; + absl::optional<gfx::HDRMetadata> src_hdr_metadata; float sdr_max_luminance_nits = 0.f; float dst_max_luminance_relative = 0.f; @@ -73,6 +79,7 @@ class COLOR_SPACE_EXPORT ColorConversionSkFilterCache { float resource_offset, float resource_multiplier, float sdr_max_luminance_nits, + absl::optional<gfx::HDRMetadata> src_hdr_metadata, float dst_max_luminance_relative); base::flat_map<Key, sk_sp<SkRuntimeEffect>> cache_; diff --git a/chromium/ui/gfx/color_space_win.cc b/chromium/ui/gfx/color_space_win.cc index 2f32286832e..d24c5d6829f 100644 --- a/chromium/ui/gfx/color_space_win.cc +++ b/chromium/ui/gfx/color_space_win.cc @@ -5,7 +5,7 @@ #include "ui/gfx/color_space_win.h" #include "base/logging.h" -#include "third_party/skia/include/third_party/skcms/skcms.h" +#include "third_party/skia/modules/skcms/skcms.h" namespace gfx { diff --git a/chromium/ui/gfx/color_transform.cc b/chromium/ui/gfx/color_transform.cc index c7f9d753e07..86bbceb5ccb 100644 --- a/chromium/ui/gfx/color_transform.cc +++ b/chromium/ui/gfx/color_transform.cc @@ -16,7 +16,7 @@ #include "base/strings/string_number_conversions.h" #include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkM44.h" -#include "third_party/skia/include/third_party/skcms/skcms.h" +#include "third_party/skia/modules/skcms/skcms.h" #include "ui/gfx/color_space.h" #include "ui/gfx/icc_profile.h" #include "ui/gfx/skia_color_space_util.h" @@ -144,6 +144,21 @@ float ToLinear(ColorSpace::TransferID id, float v) { return 0; } +// Return the maximum luminance to be used for tone mapping a PQ signal, with +// the indicated metadata. +float GetToneMapPQMaxLuminanceNits( + const absl::optional<gfx::HDRMetadata>& hdr_metadata) { + if (hdr_metadata) { + if (hdr_metadata->max_content_light_level > 0) + return hdr_metadata->max_content_light_level; + if (hdr_metadata->color_volume_metadata.luminance_max > 0.f) { + return hdr_metadata->color_volume_metadata.luminance_max; + } + } + // The maximum value that ColorTransformPQToLinear can produce. + return 10000.f; +} + } // namespace class ColorTransformMatrix; @@ -917,135 +932,6 @@ class ColorTransformFromBT2020CL : public ColorTransformStep { } }; -class ColorTransformPQToneMapToLinear : public ColorTransformStep { - public: - static float ToLinearToneMap(float v) { - v = max(0.0f, v); - return min(2.3f * pow(v, 2.8f), v / 5.0f + 0.8f); - } - - static float ToLinearPQ(float v) { - v = max(0.0f, v); - float m1 = (2610.0f / 4096.0f) / 4.0f; - float m2 = (2523.0f / 4096.0f) * 128.0f; - float c1 = 3424.0f / 4096.0f; - float c2 = (2413.0f / 4096.0f) * 32.0f; - float c3 = (2392.0f / 4096.0f) * 32.0f; - float p = pow(v, 1.0f / m2); - v = powf(max(p - c1, 0.0f) / (c2 - c3 * p), 1.0f / m1); - v *= 10000.0f / ColorSpace::kDefaultSDRWhiteLevel; - return v; - } - - // Assumes BT2020 primaries. - static float Luma(const ColorTransform::TriStim& c) { - return c.x() * 0.2627f + c.y() * 0.6780f + c.z() * 0.0593f; - } - - static ColorTransform::TriStim ClipToWhite(ColorTransform::TriStim* c) { - float maximum = max(max(c->x(), c->y()), c->z()); - if (maximum > 1.0f) { - float l = Luma(*c); - c->Scale(1.0f / maximum); - ColorTransform::TriStim white(1.0f, 1.0f, 1.0f); - white.Scale((1.0f - 1.0f / maximum) * l / Luma(white)); - ColorTransform::TriStim black(0.0f, 0.0f, 0.0f); - *c += white - black; - } - return *c; - } - - void Transform(ColorTransform::TriStim* colors, size_t num) const override { - for (size_t i = 0; i < num; i++) { - ColorTransform::TriStim ret(ToLinearToneMap(colors[i].x()), - ToLinearToneMap(colors[i].y()), - ToLinearToneMap(colors[i].z())); - if (Luma(ret) > 0.0) { - ColorTransform::TriStim smpte2084(ToLinearPQ(colors[i].x()), - ToLinearPQ(colors[i].y()), - ToLinearPQ(colors[i].z())); - smpte2084.Scale(Luma(ret) / Luma(smpte2084)); - ret = ClipToWhite(&smpte2084); - } - colors[i] = ret; - } - } - - void AppendShaderSource(std::stringstream* hdr, - std::stringstream* src, - size_t step_index) const override { - auto sdr_white_level = - base::NumberToString(ColorSpace::kDefaultSDRWhiteLevel); - *hdr << "vec3 PQToneMapStep" << step_index << "(vec3 color) {\n" - << " vec3 result = max(color, 0.0);\n" - << " result =\n" - << " min(2.3 * pow(result, vec3(2.8)), result / 5.0 + 0.8);\n" - << " vec3 luma_vec = vec3(0.2627, 0.6780, 0.0593);\n" - << " float luma = dot(result, luma_vec);\n" - << " if (luma > 0.0) {\n" - << " result = max(color, 0.0);\n" - << " float m1 = (2610.0 / 4096.0) / 4.0;\n" - << " float m2 = (2523.0 / 4096.0) * 128.0;\n" - << " float c1 = 3424.0 / 4096.0;\n" - << " float c2 = (2413.0 / 4096.0) * 32.0;\n" - << " float c3 = (2392.0 / 4096.0) * 32.0;\n" - << " vec3 p = pow(max(result, 0.0), vec3(1.0 / m2));\n" - << " result =\n" - << " pow(max(p - c1, 0.0) / (c2 - c3 * p), vec3(1.0 / m1));\n" - << " result *= 10000.0 / " + sdr_white_level + ".0;\n" - << " result *= luma / dot(result, luma_vec);\n" - << " float c_max = max(max(result.x, result.y), result.z);\n" - << " if (c_max > 1.0) {\n" - << " luma = dot(result, luma_vec);\n" - << " float s = 1.0 / c_max;\n" - << " result *= s;\n" - << " vec3 white = vec3(1.0);\n" - << " white *= (1.0 - s) * luma / dot(white, luma_vec);\n" - << " result += white - vec3(0.0);\n" - << " }\n" - << " }\n" - << " return result;\n" - << "}\n"; - *src << " color.rgb = PQToneMapStep" << step_index << "(color.rgb);\n"; - } - - void AppendSkShaderSource(std::stringstream* src) const override { - auto sdr_white_level = - base::NumberToString(ColorSpace::kDefaultSDRWhiteLevel); - *src << "{\n" - << " half4 result = max(color, 0.0);\n" - << " result =\n" - << " min(2.3 * pow(result, half4(2.8)), result / 5.0 + 0.8);\n" - << " half4 luma_vec = half4(0.2627, 0.6780, 0.0593, 0.0);\n" - << " half luma = dot(result, luma_vec);\n" - << " if (luma > 0.0) {\n" - << " result = max(color, 0.0);\n" - << " half m1 = (2610.0 / 4096.0) / 4.0;\n" - << " half m2 = (2523.0 / 4096.0) * 128.0;\n" - << " half c1 = 3424.0 / 4096.0;\n" - << " half c2 = (2413.0 / 4096.0) * 32.0;\n" - << " half c3 = (2392.0 / 4096.0) * 32.0;\n" - << " half4 p = pow(max(result, 0.0), half4(1.0 / m2));\n" - << " result =\n" - << " pow(max(p - c1, 0.0) / (c2 - c3 * p), half4(1.0 / m1));\n" - << " result *= 10000.0 / " + sdr_white_level + ".0;\n" - << " result *= luma / dot(result, luma_vec);\n" - << " half c_max = max(max(result.x, result.y), result.z);\n" - << " if (c_max > 1.0) {\n" - << " luma = dot(result, luma_vec);\n" - << " half s = 1.0 / c_max;\n" - << " result *= s;\n" - << " half4 white = half4(1.0);\n" - << " white *= (1.0 - s) * luma / dot(white, luma_vec);\n" - << " result += white - half4(0.0);\n" - << " }\n" - << " }\n" - << " result.a = color.a;\n" - << " color = result;\n" - << "}\n"; - } -}; - // Apply the HLG OOTF for a specified maximum luminance. class ColorTransformHLGOOTF : public ColorTransformStep { public: @@ -1188,13 +1074,7 @@ void ColorTransformInternal::AppendColorSpaceToColorSpaceTransform( switch (src.GetTransferID()) { case ColorSpace::TransferID::HLG: - if (options.tone_map_pq_and_hlg_to_sdr) { - // HLG is designed such that treating it as 2.2 gamma content works - // well. - constexpr skcms_TransferFunction kGamma22 = {2.2, 1, 0, 0, 0, 0, 0}; - steps_.push_back(std::make_unique<ColorTransformSkTransferFn>( - kGamma22, src.HasExtendedSkTransferFn())); - } else if (options.tone_map_pq_and_hlg_to_dst) { + if (options.tone_map_pq_and_hlg_to_dst) { // Convert to linear with a maximum value of 1. steps_.push_back(std::make_unique<ColorTransformHLGToLinear>( 12.f * ColorSpace::kDefaultSDRWhiteLevel)); @@ -1204,12 +1084,8 @@ void ColorTransformInternal::AppendColorSpaceToColorSpaceTransform( } break; case ColorSpace::TransferID::PQ: - if (options.tone_map_pq_and_hlg_to_sdr) { - steps_.push_back(std::make_unique<ColorTransformPQToneMapToLinear>()); - } else { - steps_.push_back(std::make_unique<ColorTransformPQToLinear>( - options.sdr_max_luminance_nits)); - } + steps_.push_back(std::make_unique<ColorTransformPQToLinear>( + options.sdr_max_luminance_nits)); break; case ColorSpace::TransferID::PIECEWISE_HDR: { skcms_TransferFunction fn; @@ -1258,9 +1134,9 @@ void ColorTransformInternal::AppendColorSpaceToColorSpaceTransform( break; } case ColorSpace::TransferID::PQ: { - // The maximum value that ColorTransformPQToLinear can produce. const float src_max_luminance_relative = - 10000 / options.sdr_max_luminance_nits; + GetToneMapPQMaxLuminanceNits(options.src_hdr_metadata) / + options.sdr_max_luminance_nits; if (src_max_luminance_relative > options.dst_max_luminance_relative) { const ColorSpace rec2020_linear( ColorSpace::PrimaryID::BT2020, ColorSpace::TransferID::LINEAR, diff --git a/chromium/ui/gfx/color_transform.h b/chromium/ui/gfx/color_transform.h index 11a56bca404..2bc8d22ea4e 100644 --- a/chromium/ui/gfx/color_transform.h +++ b/chromium/ui/gfx/color_transform.h @@ -8,9 +8,11 @@ #include <memory> #include <string> +#include "third_party/abseil-cpp/absl/types/optional.h" #include "ui/gfx/color_space.h" #include "ui/gfx/color_space_export.h" #include "ui/gfx/geometry/point3_f.h" +#include "ui/gfx/hdr_metadata.h" namespace gfx { @@ -24,10 +26,6 @@ class COLOR_SPACE_EXPORT ColorTransform { uint32_t src_bit_depth = kDefaultBitDepth; uint32_t dst_bit_depth = kDefaultBitDepth; - // If set to true, then PQ and HLG inputs are tone mapped to fit into - // the SDR range. - bool tone_map_pq_and_hlg_to_sdr = false; - // If set to true, then map PQ and HLG imputs such that their maximum // luminance will be `dst_max_luminance_relative`. bool tone_map_pq_and_hlg_to_dst = false; @@ -37,6 +35,9 @@ class COLOR_SPACE_EXPORT ColorTransform { // TODO(https://crbug.com/1286082): Use this value in the transform. float sdr_max_luminance_nits = ColorSpace::kDefaultSDRWhiteLevel; + // Used for tone mapping PQ sources. + absl::optional<gfx::HDRMetadata> src_hdr_metadata; + // The maximum luminance value for the destination, as a multiple of // `sdr_max_luminance_nits` (so this is 1 for SDR displays). // TODO(https://crbug.com/1286076): Use this value for transforming diff --git a/chromium/ui/gfx/color_transform_unittest.cc b/chromium/ui/gfx/color_transform_unittest.cc index b9272c6e3a6..7d77fba128d 100644 --- a/chromium/ui/gfx/color_transform_unittest.cc +++ b/chromium/ui/gfx/color_transform_unittest.cc @@ -901,60 +901,4 @@ TEST(ColorSpaceTest, PiecewiseHDR) { } } -TEST(ColorSpaceTest, HLGHDRToSDR) { - ColorSpace hlg_cs(ColorSpace::PrimaryID::BT709, ColorSpace::TransferID::HLG); - ColorSpace dest_sdr_cs(ColorSpace::PrimaryID::BT709, - ColorSpace::TransferID::LINEAR); - gfx::ColorTransform::Options sdr_options; - sdr_options.tone_map_pq_and_hlg_to_sdr = true; - auto sdr_transform = - ColorTransform::NewColorTransform(hlg_cs, dest_sdr_cs, sdr_options); - - // HLG conversion will produce values above 1 w/o intervention. - ColorTransform::TriStim sdr_val = {1, 1, 1}; - sdr_transform->Transform(&sdr_val, 1); - EXPECT_FLOAT_EQ(sdr_val.x(), 1); - EXPECT_FLOAT_EQ(sdr_val.y(), 1); - EXPECT_FLOAT_EQ(sdr_val.z(), 1); - - ColorSpace dest_hdr_cs(ColorSpace::PrimaryID::BT709, - ColorSpace::TransferID::LINEAR_HDR); - gfx::ColorTransform::Options hdr_options; - hdr_options.tone_map_pq_and_hlg_to_sdr = false; - auto hdr_transform = - ColorTransform::NewColorTransform(hlg_cs, dest_hdr_cs, hdr_options); - - ColorTransform::TriStim hdr_val = {1, 1, 1}; - hdr_transform->Transform(&hdr_val, 1); - EXPECT_NE(sdr_val, hdr_val); -} - -TEST(ColorSpaceTest, PQHDRToSDR) { - ColorSpace pq_cs(ColorSpace::PrimaryID::BT709, ColorSpace::TransferID::PQ); - ColorSpace dest_sdr_cs(ColorSpace::PrimaryID::BT709, - ColorSpace::TransferID::LINEAR); - gfx::ColorTransform::Options sdr_options; - sdr_options.tone_map_pq_and_hlg_to_sdr = true; - auto sdr_transform = - ColorTransform::NewColorTransform(pq_cs, dest_sdr_cs, sdr_options); - - // PQ conversion will produce values above 1 w/o intervention. - ColorTransform::TriStim sdr_val = {1, 1, 1}; - sdr_transform->Transform(&sdr_val, 1); - EXPECT_FLOAT_EQ(sdr_val.x(), 1); - EXPECT_FLOAT_EQ(sdr_val.y(), 1); - EXPECT_FLOAT_EQ(sdr_val.z(), 1); - - ColorSpace dest_hdr_cs(ColorSpace::PrimaryID::BT709, - ColorSpace::TransferID::LINEAR_HDR); - gfx::ColorTransform::Options hdr_options; - hdr_options.tone_map_pq_and_hlg_to_sdr = false; - auto hdr_transform = - ColorTransform::NewColorTransform(pq_cs, dest_hdr_cs, hdr_options); - - ColorTransform::TriStim hdr_val = {1, 1, 1}; - hdr_transform->Transform(&hdr_val, 1); - EXPECT_NE(sdr_val, hdr_val); -} - } // namespace gfx diff --git a/chromium/ui/gfx/delegated_ink_metadata.h b/chromium/ui/gfx/delegated_ink_metadata.h index 3952ec973b9..c9b9c2148a9 100644 --- a/chromium/ui/gfx/delegated_ink_metadata.h +++ b/chromium/ui/gfx/delegated_ink_metadata.h @@ -66,7 +66,8 @@ class GFX_EXPORT DelegatedInkMetadata { // Use mask to distinguish from DelegatedInkPoint::trace_id(). // Using microseconds provides uniqueness of trace_id per // DelegatedInkMetadata. - return timestamp_.since_origin().InMicroseconds() | (uint64_t{1} << 63); + return static_cast<uint64_t>(timestamp_.since_origin().InMicroseconds()) | + (uint64_t{1} << 63); } std::string ToString() const; diff --git a/chromium/ui/gfx/display_color_spaces.cc b/chromium/ui/gfx/display_color_spaces.cc index 0a3556fdf75..48e13ef042a 100644 --- a/chromium/ui/gfx/display_color_spaces.cc +++ b/chromium/ui/gfx/display_color_spaces.cc @@ -6,6 +6,7 @@ #include "build/build_config.h" #include "build/chromeos_buildflags.h" +#include "third_party/skia/include/core/SkColorSpace.h" namespace gfx { @@ -120,6 +121,12 @@ bool DisplayColorSpaces::SupportsHDR() const { GetOutputColorSpace(ContentColorUsage::kHDR, true).IsHDR(); } +SkColorSpacePrimaries DisplayColorSpaces::GetPrimaries() const { + // TODO(https://crbug.com/1274220): Store this directly, rather than inferring + // it from the raster color space. + return GetRasterColorSpace().GetColorSpacePrimaries(); +} + ColorSpace DisplayColorSpaces::GetScreenInfoColorSpace() const { return GetOutputColorSpace(ContentColorUsage::kHDR, false /* needs_alpha */); } diff --git a/chromium/ui/gfx/display_color_spaces.h b/chromium/ui/gfx/display_color_spaces.h index 7a7fbd73fae..5253f9cb82b 100644 --- a/chromium/ui/gfx/display_color_spaces.h +++ b/chromium/ui/gfx/display_color_spaces.h @@ -112,6 +112,9 @@ class COLOR_SPACE_EXPORT DisplayColorSpaces { // Return true if the HDR color spaces are, indeed, HDR. bool SupportsHDR() const; + // Return the primaries that define the color gamut of the display. + SkColorSpacePrimaries GetPrimaries() const; + // Output as a vector of strings. This is a helper function for printing in // about:gpu. All output vectors will be the same length. Each entry will be // the configuration name, its buffer format, and its color space. diff --git a/chromium/ui/gfx/font_fallback_linux.cc b/chromium/ui/gfx/font_fallback_linux.cc index a172655c886..5fcad63e26e 100644 --- a/chromium/ui/gfx/font_fallback_linux.cc +++ b/chromium/ui/gfx/font_fallback_linux.cc @@ -14,6 +14,7 @@ #include "base/files/file_path.h" #include "base/lazy_instance.h" #include "base/memory/ptr_util.h" +#include "base/memory/raw_ptr.h" #include "base/no_destructor.h" #include "base/strings/string_piece.h" #include "base/trace_event/trace_event.h" @@ -176,7 +177,7 @@ class FallbackFontEntry { FontRenderParams font_params_; // Font code points coverage. - FcCharSet* charset_; + raw_ptr<FcCharSet> charset_; }; using FallbackFontEntries = std::vector<FallbackFontEntry>; @@ -415,7 +416,7 @@ class CachedFont { FallbackFontData fallback_font_; // supported_characters_ is owned by the parent // FcFontSet and should never be freed. - FcCharSet* supported_characters_; + raw_ptr<FcCharSet> supported_characters_; }; class CachedFontSet { @@ -502,7 +503,7 @@ class CachedFontSet { } } - FcFontSet* font_set_; // Owned by this object. + raw_ptr<FcFontSet> font_set_; // Owned by this object. // CachedFont has a FcCharset* which points into the FcFontSet. // If the FcFontSet is ever destroyed, the fallback list // must be cleared first. diff --git a/chromium/ui/gfx/font_render_params_linux.cc b/chromium/ui/gfx/font_render_params_linux.cc index 42bb770bf44..81684678751 100644 --- a/chromium/ui/gfx/font_render_params_linux.cc +++ b/chromium/ui/gfx/font_render_params_linux.cc @@ -23,9 +23,12 @@ #include "ui/gfx/font.h" #include "ui/gfx/font_render_params_linux.h" #include "ui/gfx/linux/fontconfig_util.h" -#include "ui/gfx/skia_font_delegate.h" #include "ui/gfx/switches.h" +#if BUILDFLAG(IS_LINUX) +#include "ui/linux/linux_ui.h" +#endif + namespace gfx { namespace { @@ -209,9 +212,10 @@ FontRenderParams GetFontRenderParams(const FontRenderParamsQuery& query, // Start with the delegate's settings, but let Fontconfig have the final say. FontRenderParams params; - const SkiaFontDelegate* delegate = SkiaFontDelegate::instance(); - if (delegate) - params = delegate->GetDefaultFontRenderParams(); +#if BUILDFLAG(IS_LINUX) + if (const auto* linux_ui = ui::LinuxUi::instance()) + params = linux_ui->GetDefaultFontRenderParams(); +#endif QueryFontconfig(actual_query, ¶ms, family_out); if (!params.antialiasing) { // Cairo forces full hinting when antialiasing is disabled, since anything diff --git a/chromium/ui/gfx/font_render_params_linux_unittest.cc b/chromium/ui/gfx/font_render_params_linux_unittest.cc index bd81696b313..50e80353fdd 100644 --- a/chromium/ui/gfx/font_render_params_linux_unittest.cc +++ b/chromium/ui/gfx/font_render_params_linux_unittest.cc @@ -9,6 +9,7 @@ #include "base/check_op.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" +#include "base/memory/raw_ptr.h" #include "base/notreached.h" #include "base/strings/stringprintf.h" #include "build/build_config.h" @@ -17,7 +18,7 @@ #include "third_party/test_fonts/fontconfig/fontconfig_util_linux.h" #include "ui/gfx/font.h" #include "ui/gfx/linux/fontconfig_util.h" -#include "ui/gfx/skia_font_delegate.h" +#include "ui/linux/fake_linux_ui.h" namespace gfx { @@ -35,16 +36,16 @@ const char kFontconfigMatchFontHeader[] = " <match target=\"font\">\n"; const char kFontconfigMatchPatternHeader[] = " <match target=\"pattern\">\n"; const char kFontconfigMatchFooter[] = " </match>\n"; -// Implementation of SkiaFontDelegate that returns a canned FontRenderParams +// Implementation of LinuxUi that returns a canned FontRenderParams // struct. This is used to isolate tests from the system's local configuration. -class TestFontDelegate : public SkiaFontDelegate { +class TestFontDelegate : public ui::FakeLinuxUi { public: - TestFontDelegate() {} + TestFontDelegate() = default; TestFontDelegate(const TestFontDelegate&) = delete; TestFontDelegate& operator=(const TestFontDelegate&) = delete; - ~TestFontDelegate() override {} + ~TestFontDelegate() override = default; void set_params(const FontRenderParams& params) { params_ = params; } @@ -54,7 +55,7 @@ class TestFontDelegate : public SkiaFontDelegate { void GetDefaultFontDescription(std::string* family_out, int* size_pixels_out, int* style_out, - Font::Weight* weight_out, + int* weight_out, FontRenderParams* params_out) const override { NOTIMPLEMENTED(); } @@ -110,8 +111,9 @@ std::string CreateFontconfigAliasStanza(const std::string& original_family, class FontRenderParamsTest : public testing::Test { public: FontRenderParamsTest() { - original_font_delegate_ = SkiaFontDelegate::instance(); - SkiaFontDelegate::SetInstance(&test_font_delegate_); + auto test_font_delegate = std::make_unique<TestFontDelegate>(); + test_font_delegate_ = test_font_delegate.get(); + ui::LinuxUi::SetInstance(std::move(test_font_delegate)); ClearFontRenderParamsCacheForTest(); // Create a new fontconfig configuration and load the default fonts @@ -136,57 +138,54 @@ class FontRenderParamsTest : public testing::Test { OverrideGlobalFontConfigForTesting(original_config_); FcConfigDestroy(override_config_); - SkiaFontDelegate::SetInstance( - const_cast<SkiaFontDelegate*>(original_font_delegate_)); + ui::LinuxUi::SetInstance(nullptr); + test_font_delegate_ = nullptr; } protected: - const SkiaFontDelegate* original_font_delegate_; - TestFontDelegate test_font_delegate_; + raw_ptr<TestFontDelegate> test_font_delegate_; - FcConfig* override_config_ = nullptr; - FcConfig* original_config_ = nullptr; + raw_ptr<FcConfig> override_config_ = nullptr; + raw_ptr<FcConfig> original_config_ = nullptr; }; TEST_F(FontRenderParamsTest, Default) { ASSERT_TRUE(LoadConfigDataIntoFontconfig( std::string(kFontconfigFileHeader) + - // Specify the desired defaults via a font match rather than a pattern - // match (since this is the style generally used in - // /etc/fonts/conf.d). - kFontconfigMatchFontHeader + - CreateFontconfigEditStanza("antialias", "bool", "true") + - CreateFontconfigEditStanza("autohint", "bool", "true") + - CreateFontconfigEditStanza("hinting", "bool", "true") + - CreateFontconfigEditStanza("hintstyle", "const", "hintslight") + - CreateFontconfigEditStanza("rgba", "const", "rgb") + - kFontconfigMatchFooter + - // Add a font match for Arimo. Since it specifies a family, it - // shouldn't take effect when querying default settings. - kFontconfigMatchFontHeader + - CreateFontconfigTestStanza("family", "eq", "string", "Arimo") + - CreateFontconfigEditStanza("antialias", "bool", "true") + - CreateFontconfigEditStanza("autohint", "bool", "false") + - CreateFontconfigEditStanza("hinting", "bool", "true") + - CreateFontconfigEditStanza("hintstyle", "const", "hintfull") + - CreateFontconfigEditStanza("rgba", "const", "none") + - kFontconfigMatchFooter + - // Add font matches for fonts between 10 and 20 points or pixels. - // Since they specify sizes, they also should not affect the defaults. - kFontconfigMatchFontHeader + - CreateFontconfigTestStanza("size", "more_eq", "double", "10.0") + - CreateFontconfigTestStanza("size", "less_eq", "double", "20.0") + - CreateFontconfigEditStanza("antialias", "bool", "false") + - kFontconfigMatchFooter + kFontconfigMatchFontHeader + - CreateFontconfigTestStanza("pixel_size", "more_eq", "double", - "10.0") + - CreateFontconfigTestStanza("pixel_size", "less_eq", "double", - "20.0") + - CreateFontconfigEditStanza("antialias", "bool", "false") + - kFontconfigMatchFooter + kFontconfigFileFooter)); - - FontRenderParams params = GetFontRenderParams( - FontRenderParamsQuery(), NULL); + // Specify the desired defaults via a font match rather than a pattern + // match (since this is the style generally used in + // /etc/fonts/conf.d). + kFontconfigMatchFontHeader + + CreateFontconfigEditStanza("antialias", "bool", "true") + + CreateFontconfigEditStanza("autohint", "bool", "true") + + CreateFontconfigEditStanza("hinting", "bool", "true") + + CreateFontconfigEditStanza("hintstyle", "const", "hintslight") + + CreateFontconfigEditStanza("rgba", "const", "rgb") + + kFontconfigMatchFooter + + // Add a font match for Arimo. Since it specifies a family, it + // shouldn't take effect when querying default settings. + kFontconfigMatchFontHeader + + CreateFontconfigTestStanza("family", "eq", "string", "Arimo") + + CreateFontconfigEditStanza("antialias", "bool", "true") + + CreateFontconfigEditStanza("autohint", "bool", "false") + + CreateFontconfigEditStanza("hinting", "bool", "true") + + CreateFontconfigEditStanza("hintstyle", "const", "hintfull") + + CreateFontconfigEditStanza("rgba", "const", "none") + + kFontconfigMatchFooter + + // Add font matches for fonts between 10 and 20 points or pixels. + // Since they specify sizes, they also should not affect the defaults. + kFontconfigMatchFontHeader + + CreateFontconfigTestStanza("size", "more_eq", "double", "10.0") + + CreateFontconfigTestStanza("size", "less_eq", "double", "20.0") + + CreateFontconfigEditStanza("antialias", "bool", "false") + + kFontconfigMatchFooter + kFontconfigMatchFontHeader + + CreateFontconfigTestStanza("pixel_size", "more_eq", "double", "10.0") + + CreateFontconfigTestStanza("pixel_size", "less_eq", "double", "20.0") + + CreateFontconfigEditStanza("antialias", "bool", "false") + + kFontconfigMatchFooter + kFontconfigFileFooter)); + + FontRenderParams params = + GetFontRenderParams(FontRenderParamsQuery(), nullptr); EXPECT_TRUE(params.antialiasing); EXPECT_TRUE(params.autohinter); EXPECT_TRUE(params.use_bitmaps); @@ -199,31 +198,31 @@ TEST_F(FontRenderParamsTest, Default) { TEST_F(FontRenderParamsTest, Size) { ASSERT_TRUE(LoadConfigDataIntoFontconfig( std::string(kFontconfigFileHeader) + kFontconfigMatchPatternHeader + - CreateFontconfigEditStanza("antialias", "bool", "true") + - CreateFontconfigEditStanza("hinting", "bool", "true") + - CreateFontconfigEditStanza("hintstyle", "const", "hintfull") + - CreateFontconfigEditStanza("rgba", "const", "none") + - kFontconfigMatchFooter + kFontconfigMatchPatternHeader + - CreateFontconfigTestStanza("pixelsize", "less_eq", "double", "10") + - CreateFontconfigEditStanza("antialias", "bool", "false") + - kFontconfigMatchFooter + kFontconfigMatchPatternHeader + - CreateFontconfigTestStanza("size", "more_eq", "double", "20") + - CreateFontconfigEditStanza("hintstyle", "const", "hintslight") + - CreateFontconfigEditStanza("rgba", "const", "rgb") + - kFontconfigMatchFooter + kFontconfigFileFooter)); + CreateFontconfigEditStanza("antialias", "bool", "true") + + CreateFontconfigEditStanza("hinting", "bool", "true") + + CreateFontconfigEditStanza("hintstyle", "const", "hintfull") + + CreateFontconfigEditStanza("rgba", "const", "none") + + kFontconfigMatchFooter + kFontconfigMatchPatternHeader + + CreateFontconfigTestStanza("pixelsize", "less_eq", "double", "10") + + CreateFontconfigEditStanza("antialias", "bool", "false") + + kFontconfigMatchFooter + kFontconfigMatchPatternHeader + + CreateFontconfigTestStanza("size", "more_eq", "double", "20") + + CreateFontconfigEditStanza("hintstyle", "const", "hintslight") + + CreateFontconfigEditStanza("rgba", "const", "rgb") + + kFontconfigMatchFooter + kFontconfigFileFooter)); // The defaults should be used when the supplied size isn't matched by the // second or third blocks. FontRenderParamsQuery query; query.pixel_size = 12; - FontRenderParams params = GetFontRenderParams(query, NULL); + FontRenderParams params = GetFontRenderParams(query, nullptr); EXPECT_TRUE(params.antialiasing); EXPECT_EQ(FontRenderParams::HINTING_FULL, params.hinting); EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_NONE, params.subpixel_rendering); query.pixel_size = 10; - params = GetFontRenderParams(query, NULL); + params = GetFontRenderParams(query, nullptr); EXPECT_FALSE(params.antialiasing); EXPECT_EQ(FontRenderParams::HINTING_FULL, params.hinting); EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_NONE, @@ -231,7 +230,7 @@ TEST_F(FontRenderParamsTest, Size) { query.pixel_size = 0; query.point_size = 20; - params = GetFontRenderParams(query, NULL); + params = GetFontRenderParams(query, nullptr); EXPECT_TRUE(params.antialiasing); EXPECT_EQ(FontRenderParams::HINTING_SLIGHT, params.hinting); EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_RGB, @@ -243,41 +242,41 @@ TEST_F(FontRenderParamsTest, Style) { // hinting for italic text. ASSERT_TRUE(LoadConfigDataIntoFontconfig( std::string(kFontconfigFileHeader) + kFontconfigMatchPatternHeader + - CreateFontconfigEditStanza("antialias", "bool", "true") + - CreateFontconfigEditStanza("hinting", "bool", "true") + - CreateFontconfigEditStanza("hintstyle", "const", "hintslight") + - CreateFontconfigEditStanza("rgba", "const", "rgb") + - kFontconfigMatchFooter + kFontconfigMatchPatternHeader + - CreateFontconfigTestStanza("weight", "eq", "const", "bold") + - CreateFontconfigEditStanza("rgba", "const", "none") + - kFontconfigMatchFooter + kFontconfigMatchPatternHeader + - CreateFontconfigTestStanza("slant", "eq", "const", "italic") + - CreateFontconfigEditStanza("hinting", "bool", "false") + - kFontconfigMatchFooter + kFontconfigFileFooter)); + CreateFontconfigEditStanza("antialias", "bool", "true") + + CreateFontconfigEditStanza("hinting", "bool", "true") + + CreateFontconfigEditStanza("hintstyle", "const", "hintslight") + + CreateFontconfigEditStanza("rgba", "const", "rgb") + + kFontconfigMatchFooter + kFontconfigMatchPatternHeader + + CreateFontconfigTestStanza("weight", "eq", "const", "bold") + + CreateFontconfigEditStanza("rgba", "const", "none") + + kFontconfigMatchFooter + kFontconfigMatchPatternHeader + + CreateFontconfigTestStanza("slant", "eq", "const", "italic") + + CreateFontconfigEditStanza("hinting", "bool", "false") + + kFontconfigMatchFooter + kFontconfigFileFooter)); FontRenderParamsQuery query; query.style = Font::NORMAL; - FontRenderParams params = GetFontRenderParams(query, NULL); + FontRenderParams params = GetFontRenderParams(query, nullptr); EXPECT_EQ(FontRenderParams::HINTING_SLIGHT, params.hinting); EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_RGB, params.subpixel_rendering); query.weight = Font::Weight::BOLD; - params = GetFontRenderParams(query, NULL); + params = GetFontRenderParams(query, nullptr); EXPECT_EQ(FontRenderParams::HINTING_SLIGHT, params.hinting); EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_NONE, params.subpixel_rendering); query.weight = Font::Weight::NORMAL; query.style = Font::ITALIC; - params = GetFontRenderParams(query, NULL); + params = GetFontRenderParams(query, nullptr); EXPECT_EQ(FontRenderParams::HINTING_NONE, params.hinting); EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_RGB, params.subpixel_rendering); query.weight = Font::Weight::BOLD; query.style = Font::ITALIC; - params = GetFontRenderParams(query, NULL); + params = GetFontRenderParams(query, nullptr); EXPECT_EQ(FontRenderParams::HINTING_NONE, params.hinting); EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_NONE, params.subpixel_rendering); @@ -287,15 +286,15 @@ TEST_F(FontRenderParamsTest, Scalable) { // Load a config that only enables antialiasing for scalable fonts. ASSERT_TRUE(LoadConfigDataIntoFontconfig( std::string(kFontconfigFileHeader) + kFontconfigMatchPatternHeader + - CreateFontconfigEditStanza("antialias", "bool", "false") + - kFontconfigMatchFooter + kFontconfigMatchPatternHeader + - CreateFontconfigTestStanza("scalable", "eq", "bool", "true") + - CreateFontconfigEditStanza("antialias", "bool", "true") + - kFontconfigMatchFooter + kFontconfigFileFooter)); + CreateFontconfigEditStanza("antialias", "bool", "false") + + kFontconfigMatchFooter + kFontconfigMatchPatternHeader + + CreateFontconfigTestStanza("scalable", "eq", "bool", "true") + + CreateFontconfigEditStanza("antialias", "bool", "true") + + kFontconfigMatchFooter + kFontconfigFileFooter)); // Check that we specifically ask how scalable fonts should be rendered. - FontRenderParams params = GetFontRenderParams( - FontRenderParamsQuery(), NULL); + FontRenderParams params = + GetFontRenderParams(FontRenderParamsQuery(), nullptr); EXPECT_TRUE(params.antialiasing); } @@ -303,18 +302,18 @@ TEST_F(FontRenderParamsTest, UseBitmaps) { // Load a config that enables embedded bitmaps for fonts <= 10 pixels. ASSERT_TRUE(LoadConfigDataIntoFontconfig( std::string(kFontconfigFileHeader) + kFontconfigMatchPatternHeader + - CreateFontconfigEditStanza("embeddedbitmap", "bool", "false") + - kFontconfigMatchFooter + kFontconfigMatchPatternHeader + - CreateFontconfigTestStanza("pixelsize", "less_eq", "double", "10") + - CreateFontconfigEditStanza("embeddedbitmap", "bool", "true") + - kFontconfigMatchFooter + kFontconfigFileFooter)); + CreateFontconfigEditStanza("embeddedbitmap", "bool", "false") + + kFontconfigMatchFooter + kFontconfigMatchPatternHeader + + CreateFontconfigTestStanza("pixelsize", "less_eq", "double", "10") + + CreateFontconfigEditStanza("embeddedbitmap", "bool", "true") + + kFontconfigMatchFooter + kFontconfigFileFooter)); FontRenderParamsQuery query; - FontRenderParams params = GetFontRenderParams(query, NULL); + FontRenderParams params = GetFontRenderParams(query, nullptr); EXPECT_FALSE(params.use_bitmaps); query.pixel_size = 5; - params = GetFontRenderParams(query, NULL); + params = GetFontRenderParams(query, nullptr); EXPECT_TRUE(params.use_bitmaps); } @@ -323,16 +322,16 @@ TEST_F(FontRenderParamsTest, ForceFullHintingWhenAntialiasingIsDisabled) { // subpixel rendering. ASSERT_TRUE(LoadConfigDataIntoFontconfig( std::string(kFontconfigFileHeader) + kFontconfigMatchPatternHeader + - CreateFontconfigEditStanza("antialias", "bool", "false") + - CreateFontconfigEditStanza("hinting", "bool", "false") + - CreateFontconfigEditStanza("hintstyle", "const", "hintnone") + - CreateFontconfigEditStanza("rgba", "const", "rgb") + - kFontconfigMatchFooter + kFontconfigFileFooter)); + CreateFontconfigEditStanza("antialias", "bool", "false") + + CreateFontconfigEditStanza("hinting", "bool", "false") + + CreateFontconfigEditStanza("hintstyle", "const", "hintnone") + + CreateFontconfigEditStanza("rgba", "const", "rgb") + + kFontconfigMatchFooter + kFontconfigFileFooter)); // Full hinting should be forced. See the comment in GetFontRenderParams() for // more information. - FontRenderParams params = GetFontRenderParams( - FontRenderParamsQuery(), NULL); + FontRenderParams params = + GetFontRenderParams(FontRenderParamsQuery(), nullptr); EXPECT_FALSE(params.antialiasing); EXPECT_EQ(FontRenderParams::HINTING_FULL, params.hinting); EXPECT_EQ(FontRenderParams::SUBPIXEL_RENDERING_NONE, @@ -343,7 +342,7 @@ TEST_F(FontRenderParamsTest, ForceFullHintingWhenAntialiasingIsDisabled) { TEST_F(FontRenderParamsTest, ForceSubpixelPositioning) { { FontRenderParams params = - GetFontRenderParams(FontRenderParamsQuery(), NULL); + GetFontRenderParams(FontRenderParamsQuery(), nullptr); EXPECT_TRUE(params.antialiasing); EXPECT_FALSE(params.subpixel_positioning); SetFontRenderParamsDeviceScaleFactor(1.0f); @@ -353,7 +352,7 @@ TEST_F(FontRenderParamsTest, ForceSubpixelPositioning) { // Subpixel positioning should be forced. { FontRenderParams params = - GetFontRenderParams(FontRenderParamsQuery(), NULL); + GetFontRenderParams(FontRenderParamsQuery(), nullptr); EXPECT_TRUE(params.antialiasing); EXPECT_TRUE(params.subpixel_positioning); SetFontRenderParamsDeviceScaleFactor(1.0f); @@ -376,22 +375,21 @@ TEST_F(FontRenderParamsTest, ForceSubpixelPositioning) { } TEST_F(FontRenderParamsTest, OnlySetConfiguredValues) { - // Configure the SkiaFontDelegate (which queries GtkSettings on desktop - // Linux) to request subpixel rendering. + // Configure the LinuxUi to request subpixel rendering. FontRenderParams system_params; system_params.subpixel_rendering = FontRenderParams::SUBPIXEL_RENDERING_RGB; - test_font_delegate_.set_params(system_params); + test_font_delegate_->set_params(system_params); // Load a Fontconfig config that enables antialiasing but doesn't say anything // about subpixel rendering. ASSERT_TRUE(LoadConfigDataIntoFontconfig( std::string(kFontconfigFileHeader) + kFontconfigMatchPatternHeader + - CreateFontconfigEditStanza("antialias", "bool", "true") + - kFontconfigMatchFooter + kFontconfigFileFooter)); + CreateFontconfigEditStanza("antialias", "bool", "true") + + kFontconfigMatchFooter + kFontconfigFileFooter)); // The subpixel rendering setting from the delegate should make it through. - FontRenderParams params = GetFontRenderParams( - FontRenderParamsQuery(), NULL); + FontRenderParams params = + GetFontRenderParams(FontRenderParamsQuery(), nullptr); EXPECT_EQ(system_params.subpixel_rendering, params.subpixel_rendering); } @@ -404,7 +402,7 @@ TEST_F(FontRenderParamsTest, NoFontconfigMatch) { system_params.antialiasing = true; system_params.hinting = FontRenderParams::HINTING_MEDIUM; system_params.subpixel_rendering = FontRenderParams::SUBPIXEL_RENDERING_RGB; - test_font_delegate_.set_params(system_params); + test_font_delegate_->set_params(system_params); FontRenderParamsQuery query; query.families.push_back("Arimo"); @@ -439,11 +437,11 @@ TEST_F(FontRenderParamsTest, SubstituteFamily) { // Configure Fontconfig to use Tinos for both Helvetica and Arimo. ASSERT_TRUE(LoadConfigDataIntoFontconfig( std::string(kFontconfigFileHeader) + - CreateFontconfigAliasStanza("Helvetica", "Tinos") + - kFontconfigMatchPatternHeader + - CreateFontconfigTestStanza("family", "eq", "string", "Arimo") + - CreateFontconfigEditStanza("family", "string", "Tinos") + - kFontconfigMatchFooter + kFontconfigFileFooter)); + CreateFontconfigAliasStanza("Helvetica", "Tinos") + + kFontconfigMatchPatternHeader + + CreateFontconfigTestStanza("family", "eq", "string", "Arimo") + + CreateFontconfigEditStanza("family", "string", "Tinos") + + kFontconfigMatchFooter + kFontconfigFileFooter)); FontRenderParamsQuery query; query.families.push_back("Helvetica"); diff --git a/chromium/ui/gfx/geometry/linear_gradient.cc b/chromium/ui/gfx/geometry/linear_gradient.cc index ea769b35db8..ef7ca2606c7 100644 --- a/chromium/ui/gfx/geometry/linear_gradient.cc +++ b/chromium/ui/gfx/geometry/linear_gradient.cc @@ -28,16 +28,16 @@ LinearGradient::LinearGradient(int16_t angle) : angle_(angle) {} LinearGradient::LinearGradient(const LinearGradient& copy) = default; -void LinearGradient::AddStep(float percent, uint8_t alpha) { +void LinearGradient::AddStep(float fraction, uint8_t alpha) { DCHECK_LT(step_count_, kMaxStepSize); - DCHECK_GE(percent, 0); - DCHECK_LE(percent, 100); - // make sure the step's percent is monotonically increasing. - DCHECK(step_count_ ? steps_[step_count_ - 1].percent < percent : true) + DCHECK_GE(fraction, 0); + DCHECK_LE(fraction, 1); + // make sure the step's fraction is monotonically increasing. + DCHECK(step_count_ ? steps_[step_count_ - 1].fraction < fraction : true) << base::StringPrintf("prev[%zu]=%f, next[%zu]=%f", step_count_ - 1, - steps_[step_count_ - 1].percent, step_count_, - steps_[step_count_].percent); - steps_[step_count_].percent = percent; + steps_[step_count_ - 1].fraction, step_count_, + fraction); + steps_[step_count_].fraction = fraction; steps_[step_count_++].alpha = alpha; } @@ -45,10 +45,13 @@ void LinearGradient::ReverseSteps() { std::reverse(steps_.begin(), steps_.end()); std::rotate(steps_.begin(), steps_.end() - step_count_, steps_.end()); for (size_t i = 0; i < step_count_; i++) - steps_[i].percent = 100.f - steps_[i].percent; + steps_[i].fraction = 1.f - steps_[i].fraction; } void LinearGradient::Transform(const gfx::Transform& transform) { + if (transform.IsIdentity()) + return; + gfx::PointF origin, end; float radian = gfx::DegToRad(static_cast<float>(angle_)); float y = -sin(radian); @@ -57,19 +60,17 @@ void LinearGradient::Transform(const gfx::Transform& transform) { transform.TransformPoint(&origin); transform.TransformPoint(&end); gfx::Vector2dF diff = end - origin; - int16_t new_angle = - -static_cast<int16_t>(gfx::RadToDeg(atan2(diff.y(), diff.x()))); - angle_ = new_angle; + float new_angle = gfx::RadToDeg(atan2(diff.y(), diff.x())); + angle_ = -static_cast<int16_t>(std::round(new_angle)); } std::string LinearGradient::ToString() const { std::string result = base::StringPrintf( - "LinearGradient{angle=%u, step_count=%zu [", angle_, step_count_); - for (size_t i = 0; i < step_count_; i++) { + "LinearGradient{angle=%d, step_count=%zu [", angle_, step_count_); + for (size_t i = 0; i < step_count_; ++i) { if (i) result += " - "; - result += base::NumberToString(steps_[i].percent) + ":" + - base::NumberToString(static_cast<int>(steps_[i].alpha)); + result += base::StringPrintf("%f:%u", steps_[i].fraction, steps_[i].alpha); } return result + "]}"; } diff --git a/chromium/ui/gfx/geometry/linear_gradient.h b/chromium/ui/gfx/geometry/linear_gradient.h index 1ad025fec13..aa574512d37 100644 --- a/chromium/ui/gfx/geometry/linear_gradient.h +++ b/chromium/ui/gfx/geometry/linear_gradient.h @@ -26,9 +26,8 @@ class Transform; class GEOMETRY_SKIA_EXPORT LinearGradient { public: struct Step { - constexpr Step() = default; - // Percent that defines a position in diagonal, from 0 to 100. - float percent = 0; + // Fraction that defines a position in diagonal, from 0 to 1. + float fraction = 0; // Alpha, from 0 to 255. uint8_t alpha = 0; }; @@ -45,7 +44,7 @@ class GEOMETRY_SKIA_EXPORT LinearGradient { bool IsEmpty() const { return !step_count_; } // Add a new step. Adding more than 6 results in DCHECK or ignored. - void AddStep(float percent, uint8_t alpha); + void AddStep(float fraction, uint8_t alpha); // Get step information. const StepArray& steps() const { return steps_; } @@ -54,9 +53,9 @@ class GEOMETRY_SKIA_EXPORT LinearGradient { // Gets/Sets an angle (in degrees). int16_t angle() const { return angle_; } - void set_angle(int16_t degree) { angle_ = degree % 360; } + void set_angle(int16_t degree) { angle_ = degree; } - // Reverse the step 180 degree. + // Reverse the steps. void ReverseSteps(); // Transform the angle. @@ -73,7 +72,7 @@ class GEOMETRY_SKIA_EXPORT LinearGradient { inline bool operator==(const LinearGradient::Step& lhs, const LinearGradient::Step& rhs) { - return lhs.percent == rhs.percent && lhs.alpha == rhs.alpha; + return lhs.fraction == rhs.fraction && lhs.alpha == rhs.alpha; } inline bool operator==(const LinearGradient& lhs, const LinearGradient& rhs) { diff --git a/chromium/ui/gfx/geometry/linear_gradient_unittest.cc b/chromium/ui/gfx/geometry/linear_gradient_unittest.cc index 79c6ffb6a4b..bf29ee52ec4 100644 --- a/chromium/ui/gfx/geometry/linear_gradient_unittest.cc +++ b/chromium/ui/gfx/geometry/linear_gradient_unittest.cc @@ -15,31 +15,31 @@ TEST(LinearGradientTest, Basic) { LinearGradient gradient(45); EXPECT_TRUE(gradient.IsEmpty()); - gradient.AddStep(10, 0); - gradient.AddStep(50, 50); - gradient.AddStep(80, 1); + gradient.AddStep(.1, 0); + gradient.AddStep(.5, 50); + gradient.AddStep(.8, 1); EXPECT_FALSE(gradient.IsEmpty()); EXPECT_EQ(45, gradient.angle()); EXPECT_EQ(3u, gradient.step_count()); - EXPECT_EQ(gradient.steps()[0].percent, 10); + EXPECT_FLOAT_EQ(gradient.steps()[0].fraction, .1); EXPECT_EQ(gradient.steps()[0].alpha, 0); - EXPECT_EQ(gradient.steps()[1].percent, 50); + EXPECT_FLOAT_EQ(gradient.steps()[1].fraction, .5); EXPECT_EQ(gradient.steps()[1].alpha, 50); - EXPECT_EQ(gradient.steps()[2].percent, 80); + EXPECT_FLOAT_EQ(gradient.steps()[2].fraction, .8); EXPECT_EQ(gradient.steps()[2].alpha, 1); LinearGradient gradient2(90); - gradient2.AddStep(10, 0); - gradient2.AddStep(50, 50); - gradient2.AddStep(80, 1); + gradient2.AddStep(.1, 0); + gradient2.AddStep(.5, 50); + gradient2.AddStep(.8, 1); EXPECT_NE(gradient, gradient2); gradient2.set_angle(45); EXPECT_EQ(gradient, gradient2); - gradient2.AddStep(90, 0); + gradient2.AddStep(.9, 0); EXPECT_NE(gradient, gradient2); } @@ -48,20 +48,20 @@ TEST(LinearGradientTest, Reverse) { // Make sure reversing an empty LinearGradient doesn't cause an issue. gradient.ReverseSteps(); - gradient.AddStep(10, 0); - gradient.AddStep(50, 50); - gradient.AddStep(80, 1); + gradient.AddStep(.1, 0); + gradient.AddStep(.5, 50); + gradient.AddStep(.8, 1); gradient.ReverseSteps(); EXPECT_EQ(45, gradient.angle()); EXPECT_EQ(3u, gradient.step_count()); - EXPECT_EQ(gradient.steps()[0].percent, 20); + EXPECT_FLOAT_EQ(gradient.steps()[0].fraction, .2); EXPECT_EQ(gradient.steps()[0].alpha, 1); - EXPECT_EQ(gradient.steps()[1].percent, 50); + EXPECT_FLOAT_EQ(gradient.steps()[1].fraction, .5); EXPECT_EQ(gradient.steps()[1].alpha, 50); - EXPECT_EQ(gradient.steps()[2].percent, 90); + EXPECT_FLOAT_EQ(gradient.steps()[2].fraction, .9); EXPECT_EQ(gradient.steps()[2].alpha, 0); } diff --git a/chromium/ui/gfx/geometry/mask_filter_info.cc b/chromium/ui/gfx/geometry/mask_filter_info.cc index 77621089d25..dd56b66ae68 100644 --- a/chromium/ui/gfx/geometry/mask_filter_info.cc +++ b/chromium/ui/gfx/geometry/mask_filter_info.cc @@ -17,15 +17,19 @@ bool MaskFilterInfo::Transform(const gfx::Transform& transform) { if (!transform.TransformRRectF(&rounded_corner_bounds_)) return false; - if (!gradient_mask_.IsEmpty()) - gradient_mask_.Transform(transform); + if (gradient_mask_ && !gradient_mask_->IsEmpty()) + gradient_mask_->Transform(transform); return true; } std::string MaskFilterInfo::ToString() const { - return "MaskFilterInfo{" + rounded_corner_bounds_.ToString() + - ", gradient_mask=" + gradient_mask_.ToString() + "}"; + std::string result = "MaskFilterInfo{" + rounded_corner_bounds_.ToString(); + + if (gradient_mask_) + result += ", gradient_mask=" + gradient_mask_->ToString() + "}"; + + return result; } } // namespace gfx diff --git a/chromium/ui/gfx/geometry/mask_filter_info.h b/chromium/ui/gfx/geometry/mask_filter_info.h index 6c33e8c40ba..22cc295cd24 100644 --- a/chromium/ui/gfx/geometry/mask_filter_info.h +++ b/chromium/ui/gfx/geometry/mask_filter_info.h @@ -5,6 +5,7 @@ #ifndef UI_GFX_GEOMETRY_MASK_FILTER_INFO_H_ #define UI_GFX_GEOMETRY_MASK_FILTER_INFO_H_ +#include "third_party/abseil-cpp/absl/types/optional.h" #include "ui/gfx/geometry/geometry_skia_export.h" #include "ui/gfx/geometry/linear_gradient.h" #include "ui/gfx/geometry/rect_f.h" @@ -41,11 +42,16 @@ class GEOMETRY_SKIA_EXPORT MaskFilterInfo { rounded_corner_bounds_.GetType() != RRectF::Type::kRect; } - const gfx::LinearGradient& gradient_mask() const { return gradient_mask_; } + const absl::optional<gfx::LinearGradient>& gradient_mask() const { + return gradient_mask_; + } // True if this contains an effective gradient mask (requires filter bounds). bool HasGradientMask() const { - return !rounded_corner_bounds_.IsEmpty() && !gradient_mask_.IsEmpty(); + if (rounded_corner_bounds_.IsEmpty()) + return false; + + return gradient_mask_ && !gradient_mask_->IsEmpty(); } // True if this contains no effective mask information. @@ -63,11 +69,12 @@ class GEOMETRY_SKIA_EXPORT MaskFilterInfo { RRectF rounded_corner_bounds_; // Shader based linear gradient mask to be applied to a layer. - gfx::LinearGradient gradient_mask_ = gfx::LinearGradient::GetEmpty(); + absl::optional<gfx::LinearGradient> gradient_mask_; }; inline bool operator==(const MaskFilterInfo& lhs, const MaskFilterInfo& rhs) { - return lhs.rounded_corner_bounds() == rhs.rounded_corner_bounds(); + return (lhs.rounded_corner_bounds() == rhs.rounded_corner_bounds()) && + (lhs.gradient_mask() == rhs.gradient_mask()); } inline bool operator!=(const MaskFilterInfo& lhs, const MaskFilterInfo& rhs) { diff --git a/chromium/ui/gfx/geometry/matrix44.cc b/chromium/ui/gfx/geometry/matrix44.cc index 000ce8f6d40..a0f04f3d3f5 100644 --- a/chromium/ui/gfx/geometry/matrix44.cc +++ b/chromium/ui/gfx/geometry/matrix44.cc @@ -727,10 +727,6 @@ typedef void (*Map2Procf)(const SkScalar mat[][4], const float src2[], int count, float dst4[]); -typedef void (*Map2Procd)(const SkScalar mat[][4], - const double src2[], - int count, - double dst4[]); static void map2_if(const SkScalar mat[][4], const float* SK_RESTRICT src2, @@ -746,20 +742,6 @@ static void map2_if(const SkScalar mat[][4], } } -static void map2_id(const SkScalar mat[][4], - const double* SK_RESTRICT src2, - int count, - double* SK_RESTRICT dst4) { - for (int i = 0; i < count; ++i) { - dst4[0] = src2[0]; - dst4[1] = src2[1]; - dst4[2] = 0; - dst4[3] = 1; - src2 += 2; - dst4 += 4; - } -} - static void map2_tf(const SkScalar mat[][4], const float* SK_RESTRICT src2, int count, @@ -777,20 +759,6 @@ static void map2_tf(const SkScalar mat[][4], } } -static void map2_td(const SkScalar mat[][4], - const double* SK_RESTRICT src2, - int count, - double* SK_RESTRICT dst4) { - for (int n = 0; n < count; ++n) { - dst4[0] = src2[0] + mat[3][0]; - dst4[1] = src2[1] + mat[3][1]; - dst4[2] = mat[3][2]; - dst4[3] = 1; - src2 += 2; - dst4 += 4; - } -} - static void map2_sf(const SkScalar mat[][4], const float* SK_RESTRICT src2, int count, @@ -806,20 +774,6 @@ static void map2_sf(const SkScalar mat[][4], } } -static void map2_sd(const SkScalar mat[][4], - const double* SK_RESTRICT src2, - int count, - double* SK_RESTRICT dst4) { - for (int n = 0; n < count; ++n) { - dst4[0] = mat[0][0] * src2[0] + mat[3][0]; - dst4[1] = mat[1][1] * src2[1] + mat[3][1]; - dst4[2] = mat[3][2]; - dst4[3] = 1; - src2 += 2; - dst4 += 4; - } -} - static void map2_af(const SkScalar mat[][4], const float* SK_RESTRICT src2, int count, @@ -840,22 +794,6 @@ static void map2_af(const SkScalar mat[][4], } } -static void map2_ad(const SkScalar mat[][4], - const double* SK_RESTRICT src2, - int count, - double* SK_RESTRICT dst4) { - for (int n = 0; n < count; ++n) { - double sx = src2[0]; - double sy = src2[1]; - dst4[0] = mat[0][0] * sx + mat[1][0] * sy + mat[3][0]; - dst4[1] = mat[0][1] * sx + mat[1][1] * sy + mat[3][1]; - dst4[2] = mat[0][2] * sx + mat[1][2] * sy + mat[3][2]; - dst4[3] = 1; - src2 += 2; - dst4 += 4; - } -} - static void map2_pf(const SkScalar mat[][4], const float* SK_RESTRICT src2, int count, @@ -873,21 +811,6 @@ static void map2_pf(const SkScalar mat[][4], } } -static void map2_pd(const SkScalar mat[][4], - const double* SK_RESTRICT src2, - int count, - double* SK_RESTRICT dst4) { - for (int n = 0; n < count; ++n) { - double sx = src2[0]; - double sy = src2[1]; - for (int i = 0; i < 4; i++) { - dst4[i] = mat[0][i] * sx + mat[1][i] * sy + mat[3][i]; - } - src2 += 2; - dst4 += 4; - } -} - void Matrix44::map2(const float src2[], int count, float dst4[]) const { static const Map2Procf gProc[] = {map2_if, map2_tf, map2_sf, map2_sf, map2_af, map2_af, map2_af, map2_af}; @@ -897,55 +820,6 @@ void Matrix44::map2(const float src2[], int count, float dst4[]) const { proc(fMat, src2, count, dst4); } -void Matrix44::map2(const double src2[], int count, double dst4[]) const { - static const Map2Procd gProc[] = {map2_id, map2_td, map2_sd, map2_sd, - map2_ad, map2_ad, map2_ad, map2_ad}; - - TypeMask mask = this->getType(); - Map2Procd proc = (mask & kPerspective_Mask) ? map2_pd : gProc[mask]; - proc(fMat, src2, count, dst4); -} - -bool Matrix44::preserves2dAxisAlignment(SkScalar epsilon) const { - // Can't check (mask & kPerspective_Mask) because Z isn't relevant here. - if (0 != perspX() || 0 != perspY()) - return false; - - // A matrix with two non-zeroish values in any of the upper right - // rows or columns will skew. If only one value in each row or - // column is non-zeroish, we get a scale plus perhaps a 90-degree - // rotation. - int col0 = 0; - int col1 = 0; - int row0 = 0; - int row1 = 0; - - // Must test against epsilon, not 0, because we can get values - // around 6e-17 in the matrix that "should" be 0. - - if (SkScalarAbs(fMat[0][0]) > epsilon) { - col0++; - row0++; - } - if (SkScalarAbs(fMat[0][1]) > epsilon) { - col1++; - row0++; - } - if (SkScalarAbs(fMat[1][0]) > epsilon) { - col0++; - row1++; - } - if (SkScalarAbs(fMat[1][1]) > epsilon) { - col1++; - row1++; - } - if (col0 > 1 || col1 > 1 || row0 > 1 || row1 > 1) { - return false; - } - - return true; -} - /////////////////////////////////////////////////////////////////////////////// Matrix44::Matrix44(const SkMatrix& src) { diff --git a/chromium/ui/gfx/geometry/matrix44.h b/chromium/ui/gfx/geometry/matrix44.h index 223031d51e9..21885f9ba00 100644 --- a/chromium/ui/gfx/geometry/matrix44.h +++ b/chromium/ui/gfx/geometry/matrix44.h @@ -18,40 +18,6 @@ struct CATransform3D; namespace gfx { -struct Vector4 { - SkScalar fData[4]; - - Vector4() { this->set(0, 0, 0, 1); } - Vector4(const Vector4& src) { memcpy(fData, src.fData, sizeof(fData)); } - Vector4(SkScalar x, SkScalar y, SkScalar z, SkScalar w = SK_Scalar1) { - fData[0] = x; - fData[1] = y; - fData[2] = z; - fData[3] = w; - } - - Vector4& operator=(const Vector4& src) { - memcpy(fData, src.fData, sizeof(fData)); - return *this; - } - - bool operator==(const Vector4& v) const { - return fData[0] == v.fData[0] && fData[1] == v.fData[1] && - fData[2] == v.fData[2] && fData[3] == v.fData[3]; - } - bool operator!=(const Vector4& v) const { return !(*this == v); } - bool equals(SkScalar x, SkScalar y, SkScalar z, SkScalar w = SK_Scalar1) { - return fData[0] == x && fData[1] == y && fData[2] == z && fData[3] == w; - } - - void set(SkScalar x, SkScalar y, SkScalar z, SkScalar w = SK_Scalar1) { - fData[0] = x; - fData[1] = y; - fData[2] = z; - fData[3] = w; - } -}; - // This is the underlying data structure of Transform. Don't use this type // directly. The public methods can be called through Transform::matrix(). class GEOMETRY_SKIA_EXPORT Matrix44 { @@ -217,16 +183,6 @@ class GEOMETRY_SKIA_EXPORT Matrix44 { Matrix44& preScale(SkScalar sx, SkScalar sy, SkScalar sz); Matrix44& postScale(SkScalar sx, SkScalar sy, SkScalar sz); - inline Matrix44& setScale(SkScalar scale) { - return this->setScale(scale, scale, scale); - } - inline Matrix44& preScale(SkScalar scale) { - return this->preScale(scale, scale, scale); - } - inline Matrix44& postScale(SkScalar scale) { - return this->postScale(scale, scale, scale); - } - // Sets this matrix to rotate about the specified unit-length axis vector, // by an angle specified by its sin() and cos(). This does not attempt to // verify that axis(x, y, z).length() == 1 or that the sin, cos values are @@ -265,12 +221,6 @@ class GEOMETRY_SKIA_EXPORT Matrix44 { void mapScalars(const SkScalar src[4], SkScalar dst[4]) const; inline void mapScalars(SkScalar vec[4]) const { this->mapScalars(vec, vec); } - friend Vector4 operator*(const Matrix44& m, const Vector4& src) { - Vector4 dst; - m.mapScalars(src.fData, dst.fData); - return dst; - } - /** * map an array of [x, y, 0, 1] through the matrix, returning an array * of [x', y', z', w']. @@ -280,19 +230,6 @@ class GEOMETRY_SKIA_EXPORT Matrix44 { * @param dst4 array of [x', y', z', w'] quads as the output. */ void map2(const float src2[], int count, float dst4[]) const; - void map2(const double src2[], int count, double dst4[]) const; - - /** Returns true if transformating an axis-aligned square in 2d by this matrix - will produce another 2d axis-aligned square; typically means the matrix - is a scale with perhaps a 90-degree rotation. A 3d rotation through 90 - degrees into a perpendicular plane collapses a square to a line, but - is still considered to be axis-aligned. - - By default, tolerates very slight error due to float imprecisions; - a 90-degree rotation can still end up with 10^-17 of - "non-axis-aligned" result. - */ - bool preserves2dAxisAlignment(SkScalar epsilon = SK_ScalarNearlyZero) const; double determinant() const; diff --git a/chromium/ui/gfx/geometry/rect_f.cc b/chromium/ui/gfx/geometry/rect_f.cc index c9084cff393..cb4d68475f6 100644 --- a/chromium/ui/gfx/geometry/rect_f.cc +++ b/chromium/ui/gfx/geometry/rect_f.cc @@ -8,6 +8,7 @@ #include <limits> #include "base/check.h" +#include "base/check_op.h" #include "base/numerics/safe_conversions.h" #include "base/strings/stringprintf.h" #include "build/build_config.h" @@ -148,6 +149,19 @@ void RectF::UnionEvenIfEmpty(const RectF& rect) { float rb = std::max(bottom(), rect.bottom()); SetRect(rx, ry, rr - rx, rb - ry); + + // Due to floating errors and SizeF::clamp(), the new rect may not fully + // contain the original rects at the right/bottom side. Expand the rect in + // the case. + constexpr auto kFloatMax = std::numeric_limits<float>::max(); + if (UNLIKELY(right() < rr && width() < kFloatMax)) { + size_.SetToNextWidth(); + DCHECK_GE(right(), rr); + } + if (UNLIKELY(bottom() < rb && height() < kFloatMax)) { + size_.SetToNextHeight(); + DCHECK_GE(bottom(), rb); + } } void RectF::Subtract(const RectF& rect) { diff --git a/chromium/ui/gfx/geometry/rect_f_unittest.cc b/chromium/ui/gfx/geometry/rect_f_unittest.cc index b30d275325d..b6b9f459126 100644 --- a/chromium/ui/gfx/geometry/rect_f_unittest.cc +++ b/chromium/ui/gfx/geometry/rect_f_unittest.cc @@ -159,6 +159,35 @@ TEST(RectFTest, UnionEvenIfEmpty) { RectF(8.8f, 9.9f, 2.2f, 0))); } +TEST(RectFTest, UnionEnsuresContainWithFloatingError) { + for (float f = 0.1f; f < 5; f += 0.1f) { + RectF r1(1, 2, 3, 4); + r1.Scale(f, f + 0.05f); + RectF r2 = r1 + Vector2dF(10.f + f, f - 10.f); + RectF r3 = UnionRects(r1, r2); + EXPECT_TRUE(r3.Contains(r1)); + EXPECT_TRUE(r3.Contains(r2)); + } +} + +TEST(RectFTest, UnionIfEmptyResultTinySize) { + RectF r1(1e-15f, 0, 0, 0); + RectF r2(0, 1e-15f, 0, 0); + RectF r3 = UnionRectsEvenIfEmpty(r1, r2); + EXPECT_FALSE(r3.IsEmpty()); + EXPECT_TRUE(r3.Contains(r1)); + EXPECT_TRUE(r3.Contains(r2)); +} + +TEST(RectFTest, UnionMaxRects) { + constexpr float kMaxFloat = std::numeric_limits<float>::max(); + constexpr float kMinFloat = std::numeric_limits<float>::min(); + gfx::RectF r1(kMinFloat, 0, kMaxFloat, kMaxFloat); + gfx::RectF r2(0, kMinFloat, kMaxFloat, kMaxFloat); + // This should not trigger DCHECK failure. + r1.Union(r2); +} + TEST(RectFTest, CenterPoint) { PointF center; diff --git a/chromium/ui/gfx/geometry/resize_utils.cc b/chromium/ui/gfx/geometry/resize_utils.cc index e3a70eb9d1a..e6a2ababcf4 100644 --- a/chromium/ui/gfx/geometry/resize_utils.cc +++ b/chromium/ui/gfx/geometry/resize_utils.cc @@ -35,34 +35,47 @@ bool IsResizingHorizontally(ResizeEdge resize_edge) { void SizeRectToAspectRatio(ResizeEdge resize_edge, float aspect_ratio, const Size& min_window_size, - const Size& max_window_size, + absl::optional<Size> max_window_size, Rect* rect) { DCHECK_GT(aspect_ratio, 0.0f); - DCHECK_GE(max_window_size.width(), min_window_size.width()); - DCHECK_GE(max_window_size.height(), min_window_size.height()); + if (max_window_size.has_value()) { + DCHECK_GE(max_window_size->width(), min_window_size.width()); + DCHECK_GE(max_window_size->height(), min_window_size.height()); + DCHECK(Rect(rect->origin(), *max_window_size).Contains(*rect)) + << rect->ToString() << " is larger than the maximum size " + << max_window_size->ToString(); + } DCHECK(rect->Contains(Rect(rect->origin(), min_window_size))) << rect->ToString() << " is smaller than the minimum size " << min_window_size.ToString(); - DCHECK(Rect(rect->origin(), max_window_size).Contains(*rect)) - << rect->ToString() << " is larger than the maximum size " - << max_window_size.ToString(); Size new_size = rect->size(); if (IsResizingHorizontally(resize_edge)) { new_size.set_height(base::ClampRound(new_size.width() / aspect_ratio)); if (min_window_size.height() > new_size.height() || - new_size.height() > max_window_size.height()) { - new_size.set_height(base::clamp(new_size.height(), - min_window_size.height(), - max_window_size.height())); + (max_window_size.has_value() && + new_size.height() > max_window_size->height())) { + if (max_window_size.has_value()) { + new_size.set_height(base::clamp(new_size.height(), + min_window_size.height(), + max_window_size->height())); + } else { + new_size.set_height(min_window_size.height()); + } new_size.set_width(base::ClampRound(new_size.height() * aspect_ratio)); } } else { new_size.set_width(base::ClampRound(new_size.height() * aspect_ratio)); if (min_window_size.width() > new_size.width() || - new_size.width() > max_window_size.width()) { - new_size.set_width(base::clamp(new_size.width(), min_window_size.width(), - max_window_size.width())); + (max_window_size.has_value() && + new_size.width() > max_window_size->width())) { + if (max_window_size.has_value()) { + new_size.set_width(base::clamp(new_size.width(), + min_window_size.width(), + max_window_size->width())); + } else { + new_size.set_width(min_window_size.width()); + } new_size.set_height(base::ClampRound(new_size.width() / aspect_ratio)); } } @@ -70,7 +83,9 @@ void SizeRectToAspectRatio(ResizeEdge resize_edge, // The dimensions might still be outside of the allowed ranges at this point. // This happens when the aspect ratio makes it impossible to fit |rect| // within the size limits without letter-/pillarboxing. - new_size.SetToMin(max_window_size); + if (max_window_size.has_value()) + new_size.SetToMin(*max_window_size); + new_size.SetToMax(min_window_size); // |rect| bounds before sizing to aspect ratio. diff --git a/chromium/ui/gfx/geometry/resize_utils.h b/chromium/ui/gfx/geometry/resize_utils.h index 318a31bdb01..ddb0da430c4 100644 --- a/chromium/ui/gfx/geometry/resize_utils.h +++ b/chromium/ui/gfx/geometry/resize_utils.h @@ -5,6 +5,7 @@ #ifndef UI_GFX_GEOMETRY_RESIZE_UTILS_H_ #define UI_GFX_GEOMETRY_RESIZE_UTILS_H_ +#include "third_party/abseil-cpp/absl/types/optional.h" #include "ui/gfx/geometry/geometry_export.h" namespace gfx { @@ -28,12 +29,10 @@ enum class ResizeEdge { // |min_window_size| and |max_window_size| are expected to adhere to the // given aspect ratio. // |aspect_ratio| must be valid and is found using width / height. -// TODO(apacible): |max_window_size| is expected to be non-empty. Handle -// unconstrained max sizes and sizing when windows are maximized. void GEOMETRY_EXPORT SizeRectToAspectRatio(ResizeEdge resize_edge, float aspect_ratio, const Size& min_window_size, - const Size& max_window_size, + absl::optional<Size> max_window_size, Rect* rect); } // namespace gfx diff --git a/chromium/ui/gfx/geometry/resize_utils_unittest.cc b/chromium/ui/gfx/geometry/resize_utils_unittest.cc index bf1e90bcc2c..d7db548b7f5 100644 --- a/chromium/ui/gfx/geometry/resize_utils_unittest.cc +++ b/chromium/ui/gfx/geometry/resize_utils_unittest.cc @@ -53,16 +53,16 @@ struct SizingParams { ResizeEdge resize_edge{}; float aspect_ratio = 0.0f; Size min_size; - Size max_size; + absl::optional<Size> max_size; Rect input_rect; Rect expected_output_rect; std::string ToString() const { - return base::StrCat({HitTestToString(resize_edge), - " ratio=", base::NumberToString(aspect_ratio), " [", - min_size.ToString(), "..", max_size.ToString(), "] ", - input_rect.ToString(), " -> ", - expected_output_rect.ToString()}); + return base::StrCat( + {HitTestToString(resize_edge), " ratio=", + base::NumberToString(aspect_ratio), " [", min_size.ToString(), "..", + max_size.has_value() ? max_size->ToString() : "nullopt", "] ", + input_rect.ToString(), " -> ", expected_output_rect.ToString()}); } }; @@ -121,6 +121,11 @@ const SizingParams kSizeRectToSquareAspectRatioTestCases[] = { kMaxSizeHorizontal, Rect(100, 100, kMaxSizeHorizontal.height(), kMaxSizeHorizontal.height()), Rect(100, 100, kMaxSizeHorizontal.height(), kMaxSizeHorizontal.height())}, + + // Dragging the top-left resizer left. + // No max size specified. + {ResizeEdge::kTopLeft, kAspectRatioSquare, kMinSizeHorizontal, + absl::nullopt, Rect(102, 100, 22, 24), Rect(102, 102, 22, 22)}, }; const SizingParams kSizeRectToHorizontalAspectRatioTestCases[] = { @@ -143,6 +148,11 @@ const SizingParams kSizeRectToHorizontalAspectRatioTestCases[] = { kMaxSizeHorizontal, Rect(100, 100, kMaxSizeHorizontal.width(), kMaxSizeHorizontal.height()), Rect(100, 100, kMaxSizeHorizontal.width(), kMaxSizeHorizontal.height())}, + + // Dragging the left resizer left. + // No max size specified. + {ResizeEdge::kLeft, kAspectRatioHorizontal, kMinSizeHorizontal, + absl::nullopt, Rect(96, 100, 48, 22), Rect(96, 98, 48, 24)}, }; const SizingParams kSizeRectToVerticalAspectRatioTestCases[] = { @@ -163,6 +173,11 @@ const SizingParams kSizeRectToVerticalAspectRatioTestCases[] = { {ResizeEdge::kTop, kAspectRatioVertical, kMinSizeVertical, kMaxSizeVertical, Rect(100, 100, kMaxSizeVertical.width(), kMaxSizeVertical.height()), Rect(100, 100, kMaxSizeVertical.width(), kMaxSizeVertical.height())}, + + // Dragging the right resizer right. + // No max size specified. + {ResizeEdge::kRight, kAspectRatioVertical, kMinSizeVertical, absl::nullopt, + Rect(100, 100, 24, 44), Rect(100, 100, 24, 48)}, }; INSTANTIATE_TEST_SUITE_P( diff --git a/chromium/ui/gfx/geometry/size.h b/chromium/ui/gfx/geometry/size.h index 4358414654d..412968b306a 100644 --- a/chromium/ui/gfx/geometry/size.h +++ b/chromium/ui/gfx/geometry/size.h @@ -52,7 +52,9 @@ class GEOMETRY_EXPORT Size { // Returns a checked numeric representation of the area. base::CheckedNumeric<int> GetCheckedArea() const; - uint64_t Area64() const { return static_cast<uint64_t>(width_) * height_; } + uint64_t Area64() const { + return static_cast<uint64_t>(width_) * static_cast<uint64_t>(height_); + } void SetSize(int width, int height) { set_width(width); diff --git a/chromium/ui/gfx/geometry/size_f.h b/chromium/ui/gfx/geometry/size_f.h index b6acf9e6093..de8955b3ee3 100644 --- a/chromium/ui/gfx/geometry/size_f.h +++ b/chromium/ui/gfx/geometry/size_f.h @@ -66,6 +66,10 @@ class GEOMETRY_EXPORT SizeF { void SetToMin(const SizeF& other); void SetToMax(const SizeF& other); + // Expands width/height to the next representable value. + void SetToNextWidth() { width_ = next(width_); } + void SetToNextHeight() { height_ = next(height_); } + constexpr bool IsEmpty() const { return !width() || !height(); } constexpr bool IsZero() const { return !width() && !height(); } @@ -93,6 +97,11 @@ class GEOMETRY_EXPORT SizeF { static constexpr float clamp(float f) { return f > kTrivial ? f : 0.f; } + static float next(float f) { + return std::nextafter(std::max(kTrivial, f), + std::numeric_limits<float>::max()); + } + float width_; float height_; }; diff --git a/chromium/ui/gfx/geometry/transform_util_unittest.cc b/chromium/ui/gfx/geometry/transform_util_unittest.cc index a504768f329..51defa671e1 100644 --- a/chromium/ui/gfx/geometry/transform_util_unittest.cc +++ b/chromium/ui/gfx/geometry/transform_util_unittest.cc @@ -336,7 +336,7 @@ TEST(TransformUtilTest, TransformBetweenRects) { EXPECT_EQ(dst_rect, dst_in_parent_coordinates); }; - std::vector<const std::pair<const RectF, const RectF>> test_cases{ + std::vector<std::pair<const RectF, const RectF>> test_cases{ {RectF(0.f, 0.f, 2.f, 3.f), RectF(3.f, 5.f, 4.f, 9.f)}, {RectF(10.f, 7.f, 2.f, 6.f), RectF(4.f, 2.f, 1.f, 12.f)}, {RectF(0.f, 0.f, 3.f, 5.f), RectF(0.f, 0.f, 6.f, 2.5f)}}; diff --git a/chromium/ui/gfx/gpu_memory_buffer.cc b/chromium/ui/gfx/gpu_memory_buffer.cc index a49e5bb559f..c8d60c159a5 100644 --- a/chromium/ui/gfx/gpu_memory_buffer.cc +++ b/chromium/ui/gfx/gpu_memory_buffer.cc @@ -69,6 +69,4 @@ GpuMemoryBufferHandle GpuMemoryBufferHandle::Clone() const { void GpuMemoryBuffer::SetColorSpace(const ColorSpace& color_space) {} -void GpuMemoryBuffer::SetHDRMetadata(const HDRMetadata& hdr_metadata) {} - } // namespace gfx diff --git a/chromium/ui/gfx/gpu_memory_buffer.h b/chromium/ui/gfx/gpu_memory_buffer.h index 7bb66fa2ade..1ab6446a4cf 100644 --- a/chromium/ui/gfx/gpu_memory_buffer.h +++ b/chromium/ui/gfx/gpu_memory_buffer.h @@ -14,7 +14,6 @@ #include "ui/gfx/generic_shared_memory_id.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/gfx_export.h" -#include "ui/gfx/hdr_metadata.h" #if defined(USE_OZONE) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) #include "ui/gfx/native_pixmap_handle.h" @@ -28,8 +27,6 @@ #include "base/android/scoped_hardware_buffer_handle.h" #endif -extern "C" typedef struct _ClientBuffer* ClientBuffer; - namespace base { namespace trace_event { class ProcessMemoryDump; @@ -77,7 +74,7 @@ struct GFX_EXPORT GpuMemoryBufferHandle { GpuMemoryBufferId id{0}; base::UnsafeSharedMemoryRegion region; uint32_t offset = 0; - int32_t stride = 0; + uint32_t stride = 0; #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_FUCHSIA) NativePixmapHandle native_pixmap_handle; #elif BUILDFLAG(IS_MAC) @@ -125,10 +122,6 @@ class GFX_EXPORT GpuMemoryBuffer { // as an overlay. Note that this will not impact texturing from the buffer. virtual void SetColorSpace(const ColorSpace& color_space); - // Set the HDR metadata for use when this buffer is used as an overlay. Note - // that this will not impact texturing from the buffer. - virtual void SetHDRMetadata(const HDRMetadata& hdr_metadata); - // Returns a unique identifier associated with buffer. virtual GpuMemoryBufferId GetId() const = 0; @@ -140,9 +133,6 @@ class GFX_EXPORT GpuMemoryBuffer { // caller takes ownership of the returned handle. virtual GpuMemoryBufferHandle CloneHandle() const = 0; - // Type-checking downcast routine. - virtual ClientBuffer AsClientBuffer() = 0; - // Dumps information about the memory backing the GpuMemoryBuffer to |pmd|. // The memory usage is attributed to |buffer_dump_guid|. // |tracing_process_id| uniquely identifies the process owning the memory. diff --git a/chromium/ui/gfx/hdr_metadata.h b/chromium/ui/gfx/hdr_metadata.h index c06f9e2078f..a50da186098 100644 --- a/chromium/ui/gfx/hdr_metadata.h +++ b/chromium/ui/gfx/hdr_metadata.h @@ -5,13 +5,13 @@ #ifndef UI_GFX_HDR_METADATA_H_ #define UI_GFX_HDR_METADATA_H_ +#include "ui/gfx/color_space_export.h" #include "ui/gfx/geometry/point_f.h" -#include "ui/gfx/gfx_export.h" namespace gfx { // SMPTE ST 2086 color volume metadata. -struct GFX_EXPORT ColorVolumeMetadata { +struct COLOR_SPACE_EXPORT ColorVolumeMetadata { using Chromaticity = PointF; Chromaticity primary_r; Chromaticity primary_g; @@ -33,7 +33,7 @@ struct GFX_EXPORT ColorVolumeMetadata { }; // HDR metadata common for HDR10 and WebM/VP9-based HDR formats. -struct GFX_EXPORT HDRMetadata { +struct COLOR_SPACE_EXPORT HDRMetadata { ColorVolumeMetadata color_volume_metadata; // Max content light level (CLL), i.e. maximum brightness level present in the // stream), in nits. diff --git a/chromium/ui/gfx/icc_profile.cc b/chromium/ui/gfx/icc_profile.cc index 59d427267eb..5525e5efd68 100644 --- a/chromium/ui/gfx/icc_profile.cc +++ b/chromium/ui/gfx/icc_profile.cc @@ -13,7 +13,7 @@ #include "base/logging.h" #include "base/synchronization/lock.h" #include "third_party/skia/include/core/SkColorSpace.h" -#include "third_party/skia/include/third_party/skcms/skcms.h" +#include "third_party/skia/modules/skcms/skcms.h" #include "ui/gfx/skia_color_space_util.h" namespace gfx { diff --git a/chromium/ui/gfx/icc_profile.h b/chromium/ui/gfx/icc_profile.h index 542f703fbf9..11ed3276df9 100644 --- a/chromium/ui/gfx/icc_profile.h +++ b/chromium/ui/gfx/icc_profile.h @@ -11,7 +11,7 @@ #include "base/gtest_prod_util.h" #include "base/memory/ref_counted.h" -#include "third_party/skia/include/third_party/skcms/skcms.h" +#include "third_party/skia/modules/skcms/skcms.h" #include "ui/gfx/color_space.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size); diff --git a/chromium/ui/gfx/ipc/gfx_param_traits.cc b/chromium/ui/gfx/ipc/gfx_param_traits.cc index 0499ab32703..3bdf65579dc 100644 --- a/chromium/ui/gfx/ipc/gfx_param_traits.cc +++ b/chromium/ui/gfx/ipc/gfx_param_traits.cc @@ -9,6 +9,7 @@ #include <string> +#include "base/format_macros.h" #include "base/strings/stringprintf.h" #include "build/build_config.h" #include "ui/gfx/ipc/geometry/gfx_param_traits.h" @@ -21,8 +22,8 @@ namespace IPC { void ParamTraits<gfx::Range>::Write(base::Pickle* m, const gfx::Range& r) { - m->WriteUInt32(r.start()); - m->WriteUInt32(r.end()); + m->WriteUInt32(static_cast<uint32_t>(r.start())); + m->WriteUInt32(static_cast<uint32_t>(r.end())); } bool ParamTraits<gfx::Range>::Read(const base::Pickle* m, @@ -37,7 +38,7 @@ bool ParamTraits<gfx::Range>::Read(const base::Pickle* m, } void ParamTraits<gfx::Range>::Log(const gfx::Range& r, std::string* l) { - l->append(base::StringPrintf("(%d, %d)", r.start(), r.end())); + l->append(base::StringPrintf("(%" PRIuS ", %" PRIuS ")", r.start(), r.end())); } #if BUILDFLAG(IS_MAC) diff --git a/chromium/ui/gfx/ipc/skia/gfx_skia_param_traits.cc b/chromium/ui/gfx/ipc/skia/gfx_skia_param_traits.cc index 21a3b7f8ad8..844e357f723 100644 --- a/chromium/ui/gfx/ipc/skia/gfx_skia_param_traits.cc +++ b/chromium/ui/gfx/ipc/skia/gfx_skia_param_traits.cc @@ -65,8 +65,7 @@ void ParamTraits<SkImageInfo>::Log(const SkImageInfo& p, std::string* l) { void ParamTraits<SkBitmap>::Write(base::Pickle* m, const SkBitmap& p) { WriteParam(m, p.info()); size_t pixel_size = p.computeByteSize(); - m->WriteData(reinterpret_cast<const char*>(p.getPixels()), - static_cast<int>(pixel_size)); + m->WriteData(reinterpret_cast<const char*>(p.getPixels()), pixel_size); } bool ParamTraits<SkBitmap>::Read(const base::Pickle* m, @@ -77,15 +76,14 @@ bool ParamTraits<SkBitmap>::Read(const base::Pickle* m, return false; const char* bitmap_data; - int bitmap_data_size = 0; + size_t bitmap_data_size = 0; if (!iter->ReadData(&bitmap_data, &bitmap_data_size)) return false; - // ReadData() only returns true if bitmap_data_size >= 0. if (!r->tryAllocPixels(image_info)) return false; - if (static_cast<size_t>(bitmap_data_size) != r->computeByteSize()) + if (bitmap_data_size != r->computeByteSize()) return false; memcpy(r->getPixels(), bitmap_data, bitmap_data_size); return true; diff --git a/chromium/ui/gfx/linux/client_native_pixmap_dmabuf.h b/chromium/ui/gfx/linux/client_native_pixmap_dmabuf.h index b7e1cb05d24..6154b29e57e 100644 --- a/chromium/ui/gfx/linux/client_native_pixmap_dmabuf.h +++ b/chromium/ui/gfx/linux/client_native_pixmap_dmabuf.h @@ -11,6 +11,7 @@ #include <memory> #include "base/files/scoped_file.h" +#include "base/memory/raw_ptr.h" #include "ui/gfx/buffer_types.h" #include "ui/gfx/client_native_pixmap.h" #include "ui/gfx/geometry/size.h" @@ -51,7 +52,7 @@ class ClientNativePixmapDmaBuf : public gfx::ClientNativePixmap { PlaneInfo(PlaneInfo&& plane_info); ~PlaneInfo(); - void* data = nullptr; + raw_ptr<void> data = nullptr; size_t offset = 0; size_t size = 0; }; diff --git a/chromium/ui/gfx/linux/fontconfig_util.cc b/chromium/ui/gfx/linux/fontconfig_util.cc index 6f877d8fd75..25022a1a1a0 100644 --- a/chromium/ui/gfx/linux/fontconfig_util.cc +++ b/chromium/ui/gfx/linux/fontconfig_util.cc @@ -6,6 +6,7 @@ #include <fontconfig/fontconfig.h> +#include "base/memory/raw_ptr.h" #include "base/no_destructor.h" #include "ui/gfx/font_render_params.h" @@ -65,7 +66,7 @@ class GFX_EXPORT GlobalFontConfig { } private: - FcConfig* fc_config_ = nullptr; + raw_ptr<FcConfig> fc_config_ = nullptr; }; // Converts Fontconfig FC_HINT_STYLE to FontRenderParams::Hinting. diff --git a/chromium/ui/gfx/linux/gbm_wrapper.cc b/chromium/ui/gfx/linux/gbm_wrapper.cc index 4be43d55b37..7546a3327f4 100644 --- a/chromium/ui/gfx/linux/gbm_wrapper.cc +++ b/chromium/ui/gfx/linux/gbm_wrapper.cc @@ -9,6 +9,7 @@ #include <utility> #include "base/logging.h" +#include "base/memory/raw_ptr.h" #include "base/posix/eintr_wrapper.h" #include "skia/ext/legacy_display_globals.h" #include "third_party/skia/include/core/SkSurface.h" @@ -256,7 +257,7 @@ class Buffer final : public ui::GbmBuffer { buffer->mmap_data_ = nullptr; } - gbm_bo* const bo_; + const raw_ptr<gbm_bo> bo_; void* mmap_data_ = nullptr; const uint32_t format_; @@ -399,7 +400,7 @@ class Device final : public ui::GbmDevice { } private: - gbm_device* const device_; + const raw_ptr<gbm_device> device_; }; } // namespace gbm_wrapper diff --git a/chromium/ui/gfx/mac/io_surface.cc b/chromium/ui/gfx/mac/io_surface.cc index e030f01e72d..961b730933d 100644 --- a/chromium/ui/gfx/mac/io_surface.cc +++ b/chromium/ui/gfx/mac/io_surface.cc @@ -53,6 +53,7 @@ int32_t BytesPerElement(gfx::BufferFormat format, int plane) { case gfx::BufferFormat::BGRA_8888: case gfx::BufferFormat::BGRX_8888: case gfx::BufferFormat::RGBA_8888: + case gfx::BufferFormat::RGBX_8888: case gfx::BufferFormat::BGRA_1010102: DCHECK_EQ(plane, 0); return 4; @@ -71,7 +72,6 @@ int32_t BytesPerElement(gfx::BufferFormat format, int plane) { } case gfx::BufferFormat::BGR_565: case gfx::BufferFormat::RGBA_4444: - case gfx::BufferFormat::RGBX_8888: case gfx::BufferFormat::RGBA_1010102: case gfx::BufferFormat::YVU_420: NOTREACHED(); @@ -99,6 +99,7 @@ uint32_t BufferFormatToIOSurfacePixelFormat(gfx::BufferFormat format) { case gfx::BufferFormat::BGRA_8888: case gfx::BufferFormat::BGRX_8888: case gfx::BufferFormat::RGBA_8888: + case gfx::BufferFormat::RGBX_8888: return 'BGRA'; case gfx::BufferFormat::RGBA_F16: return 'RGhA'; @@ -108,7 +109,6 @@ uint32_t BufferFormatToIOSurfacePixelFormat(gfx::BufferFormat format) { return 'x420'; case gfx::BufferFormat::BGR_565: case gfx::BufferFormat::RGBA_4444: - case gfx::BufferFormat::RGBX_8888: case gfx::BufferFormat::RGBA_1010102: // Technically RGBA_1010102 should be accepted as 'R10k', but then it won't // be supported by CGLTexImageIOSurface2D(), so it's best to reject it here. @@ -253,12 +253,13 @@ IOSurfaceRef CreateIOSurface(const gfx::Size& size, const size_t plane_width = (size.width() + factor - 1) / factor; const size_t plane_height = (size.height() + factor - 1) / factor; const size_t plane_bytes_per_element = BytesPerElement(format, plane); - const size_t plane_bytes_per_row = IOSurfaceAlignProperty( - kIOSurfacePlaneBytesPerRow, - base::bits::AlignUp(plane_width, 2) * plane_bytes_per_element); + const size_t plane_bytes_per_row = + IOSurfaceAlignProperty(kIOSurfacePlaneBytesPerRow, + base::bits::AlignUp(plane_width, size_t{2}) * + plane_bytes_per_element); const size_t plane_bytes_alloc = IOSurfaceAlignProperty( kIOSurfacePlaneSize, - base::bits::AlignUp(plane_height, 2) * plane_bytes_per_row); + base::bits::AlignUp(plane_height, size_t{2}) * plane_bytes_per_row); const size_t plane_offset = IOSurfaceAlignProperty(kIOSurfacePlaneOffset, total_bytes_alloc); diff --git a/chromium/ui/gfx/mac/io_surface_hdr_metadata.cc b/chromium/ui/gfx/mac/io_surface_hdr_metadata.cc deleted file mode 100644 index f4250246550..00000000000 --- a/chromium/ui/gfx/mac/io_surface_hdr_metadata.cc +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2020 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 "ui/gfx/mac/io_surface_hdr_metadata.h" - -#include "base/mac/foundation_util.h" -#include "base/mac/scoped_cftyperef.h" -#include "ui/gfx/mojom/hdr_metadata.mojom.h" - -namespace gfx { - -namespace { - -// The key under which HDR metadata is attached to an IOSurface. -const CFStringRef kCrIOSurfaceHDRMetadataKey = - CFSTR("CrIOSurfaceHDRMetadataKey"); - -} // namespace - -void IOSurfaceSetHDRMetadata(IOSurfaceRef io_surface, - gfx::HDRMetadata hdr_metadata) { - std::vector<uint8_t> std_data = - gfx::mojom::HDRMetadata::Serialize(&hdr_metadata); - base::ScopedCFTypeRef<CFDataRef> cf_data( - CFDataCreate(nullptr, std_data.data(), std_data.size())); - IOSurfaceSetValue(io_surface, kCrIOSurfaceHDRMetadataKey, cf_data); -} - -bool IOSurfaceGetHDRMetadata(IOSurfaceRef io_surface, - gfx::HDRMetadata& hdr_metadata) { - base::ScopedCFTypeRef<CFTypeRef> cf_untyped( - IOSurfaceCopyValue(io_surface, kCrIOSurfaceHDRMetadataKey)); - CFDataRef cf_data = base::mac::CFCast<CFDataRef>(cf_untyped); - if (!cf_data) - return false; - const UInt8* raw_data = CFDataGetBytePtr(cf_data); - std::vector<uint8_t> std_data(raw_data, raw_data + CFDataGetLength(cf_data)); - return gfx::mojom::HDRMetadata::Deserialize(std_data, &hdr_metadata); -} - -} // namespace gfx diff --git a/chromium/ui/gfx/mac/io_surface_hdr_metadata.h b/chromium/ui/gfx/mac/io_surface_hdr_metadata.h deleted file mode 100644 index 1bee4842c19..00000000000 --- a/chromium/ui/gfx/mac/io_surface_hdr_metadata.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2020 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. - -#ifndef UI_GFX_MAC_IO_SURFACE_HDR_METADATA_H_ -#define UI_GFX_MAC_IO_SURFACE_HDR_METADATA_H_ - -#include <IOSurface/IOSurface.h> - -#include "base/component_export.h" - -namespace gfx { - -struct HDRMetadata; - -// Attach |hdr_metadata| to |io_surface|. After this is called, any other -// process that has opened |io_surface| will be able to read |hdr_metadata| -// using the function IOSurfaceGetHDRMetadata. -void COMPONENT_EXPORT(GFX_IO_SURFACE_HDR_METADATA) - IOSurfaceSetHDRMetadata(IOSurfaceRef io_surface, - gfx::HDRMetadata hdr_metadata); - -// Retrieve in |hdr_metadata| the value that was attached to |io_surface|. This -// will return false on failure. -bool COMPONENT_EXPORT(GFX_IO_SURFACE_HDR_METADATA) - IOSurfaceGetHDRMetadata(IOSurfaceRef io_surface, - gfx::HDRMetadata& hdr_metadata); - -} // namespace gfx - -#endif // UI_GFX_MAC_IO_SURFACE_HDR_METADATA_H_ diff --git a/chromium/ui/gfx/mac/io_surface_unittest.cc b/chromium/ui/gfx/mac/io_surface_unittest.cc index 31eef23d755..02603d48218 100644 --- a/chromium/ui/gfx/mac/io_surface_unittest.cc +++ b/chromium/ui/gfx/mac/io_surface_unittest.cc @@ -4,35 +4,11 @@ #include "ui/gfx/mac/io_surface.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/gfx/hdr_metadata.h" -#include "ui/gfx/mac/io_surface_hdr_metadata.h" namespace gfx { namespace { -// Check that empty NSBezierPath is returned for empty SkPath. -TEST(IOSurface, HDRMetadata) { - gfx::HDRMetadata in; - in.color_volume_metadata.primary_r = PointF(1.0, 2.0); - in.color_volume_metadata.primary_g = PointF(4.0, 5.0); - in.color_volume_metadata.primary_b = PointF(7.0, 8.0); - in.color_volume_metadata.white_point = PointF(10.0, 11.0); - in.color_volume_metadata.luminance_max = 13; - in.color_volume_metadata.luminance_min = 14; - in.max_content_light_level = 15; - in.max_frame_average_light_level = 16; - - base::ScopedCFTypeRef<IOSurfaceRef> io_surface( - CreateIOSurface(gfx::Size(100, 100), gfx::BufferFormat::BGRA_8888)); - - gfx::HDRMetadata out; - EXPECT_FALSE(IOSurfaceGetHDRMetadata(io_surface, out)); - IOSurfaceSetHDRMetadata(io_surface, in); - EXPECT_TRUE(IOSurfaceGetHDRMetadata(io_surface, out)); - EXPECT_EQ(in, out); -} - TEST(IOSurface, OddSizeMultiPlanar) { base::ScopedCFTypeRef<IOSurfaceRef> io_surface( CreateIOSurface(gfx::Size(101, 99), gfx::BufferFormat::YUV_420_BIPLANAR)); diff --git a/chromium/ui/gfx/mojom/BUILD.gn b/chromium/ui/gfx/mojom/BUILD.gn index f577092a5e8..40fb1e3be2f 100644 --- a/chromium/ui/gfx/mojom/BUILD.gn +++ b/chromium/ui/gfx/mojom/BUILD.gn @@ -361,6 +361,9 @@ mojom("native_handle_types") { if (is_linux || is_chromeos || use_ozone) { enabled_features = [ "supports_native_pixmap" ] } + if (is_linux || is_chromeos) { + enabled_features += [ "is_linux_or_chromeos_ash" ] + } public_deps = [ "//mojo/public/mojom/base" ] generate_java = true webui_module_path = "chrome://resources/mojo/ui/gfx/mojom" diff --git a/chromium/ui/gfx/mojom/linear_gradient.mojom b/chromium/ui/gfx/mojom/linear_gradient.mojom index c95519c1c51..b535aa19fa3 100644 --- a/chromium/ui/gfx/mojom/linear_gradient.mojom +++ b/chromium/ui/gfx/mojom/linear_gradient.mojom @@ -6,7 +6,7 @@ module gfx.mojom; // See ui/gfx/geometry/linear_gradient.h. struct Step { - float percent; + float fraction; uint8 alpha; }; diff --git a/chromium/ui/gfx/mojom/linear_gradient_mojom_traits.cc b/chromium/ui/gfx/mojom/linear_gradient_mojom_traits.cc index 07d741f655d..25057da6ffe 100644 --- a/chromium/ui/gfx/mojom/linear_gradient_mojom_traits.cc +++ b/chromium/ui/gfx/mojom/linear_gradient_mojom_traits.cc @@ -18,7 +18,7 @@ bool StructTraits<gfx::mojom::LinearGradientDataView, gfx::LinearGradient>:: return false; for (int i = 0; i < data.step_count(); ++i) { - out->AddStep(steps_data[i].percent, steps_data[i].alpha); + out->AddStep(steps_data[i].fraction, steps_data[i].alpha); } out->set_angle(data.angle()); diff --git a/chromium/ui/gfx/mojom/linear_gradient_mojom_traits.h b/chromium/ui/gfx/mojom/linear_gradient_mojom_traits.h index 09412c3907e..1480d0add88 100644 --- a/chromium/ui/gfx/mojom/linear_gradient_mojom_traits.h +++ b/chromium/ui/gfx/mojom/linear_gradient_mojom_traits.h @@ -12,8 +12,8 @@ namespace mojo { template <> struct StructTraits<gfx::mojom::StepDataView, gfx::LinearGradient::Step> { - static float percent(const gfx::LinearGradient::Step& input) { - return input.percent; + static float fraction(const gfx::LinearGradient::Step& input) { + return input.fraction; } static uint8_t alpha(const gfx::LinearGradient::Step& input) { @@ -22,7 +22,7 @@ struct StructTraits<gfx::mojom::StepDataView, gfx::LinearGradient::Step> { static bool Read(gfx::mojom::StepDataView data, gfx::LinearGradient::Step* out) { - out->percent = data.percent(); + out->fraction = data.fraction(); out->alpha = data.alpha(); return true; } diff --git a/chromium/ui/gfx/mojom/mask_filter_info.mojom b/chromium/ui/gfx/mojom/mask_filter_info.mojom index 55bd480ccd7..9d42d6e04eb 100644 --- a/chromium/ui/gfx/mojom/mask_filter_info.mojom +++ b/chromium/ui/gfx/mojom/mask_filter_info.mojom @@ -5,9 +5,10 @@ module gfx.mojom; import "ui/gfx/mojom/rrect_f.mojom"; +import "ui/gfx/mojom/linear_gradient.mojom"; -// See ui/gfx/mask_filter_info.h. +// See ui/gfx/geometry/mask_filter_info.h. struct MaskFilterInfo { gfx.mojom.RRectF rounded_corner_bounds; - // TODO(crbug.com/1039003): add gradient mask field + gfx.mojom.LinearGradient? gradient_mask; }; diff --git a/chromium/ui/gfx/mojom/mask_filter_info_mojom_traits.cc b/chromium/ui/gfx/mojom/mask_filter_info_mojom_traits.cc index 683762ae549..a7d4a7af949 100644 --- a/chromium/ui/gfx/mojom/mask_filter_info_mojom_traits.cc +++ b/chromium/ui/gfx/mojom/mask_filter_info_mojom_traits.cc @@ -12,7 +12,15 @@ bool StructTraits<gfx::mojom::MaskFilterInfoDataView, gfx::MaskFilterInfo>:: gfx::RRectF bounds; if (!data.ReadRoundedCornerBounds(&bounds)) return false; - *out = gfx::MaskFilterInfo(bounds); + + absl::optional<gfx::LinearGradient> gradient_mask; + if (!data.ReadGradientMask(&gradient_mask)) + return false; + + if (gradient_mask && !gradient_mask->IsEmpty()) + *out = gfx::MaskFilterInfo(bounds, gradient_mask.value()); + else + *out = gfx::MaskFilterInfo(bounds); return true; } diff --git a/chromium/ui/gfx/mojom/mask_filter_info_mojom_traits.h b/chromium/ui/gfx/mojom/mask_filter_info_mojom_traits.h index 849742a91ff..0bb53003b0d 100644 --- a/chromium/ui/gfx/mojom/mask_filter_info_mojom_traits.h +++ b/chromium/ui/gfx/mojom/mask_filter_info_mojom_traits.h @@ -5,7 +5,9 @@ #ifndef UI_GFX_MOJOM_MASK_FILTER_INFO_MOJOM_TRAITS_H_ #define UI_GFX_MOJOM_MASK_FILTER_INFO_MOJOM_TRAITS_H_ +#include "ui/gfx/geometry/linear_gradient.h" #include "ui/gfx/geometry/mask_filter_info.h" +#include "ui/gfx/mojom/linear_gradient_mojom_traits.h" #include "ui/gfx/mojom/mask_filter_info.mojom-shared.h" #include "ui/gfx/mojom/rrect_f_mojom_traits.h" @@ -17,6 +19,11 @@ struct StructTraits<gfx::mojom::MaskFilterInfoDataView, gfx::MaskFilterInfo> { return info.rounded_corner_bounds(); } + static const absl::optional<gfx::LinearGradient>& gradient_mask( + const gfx::MaskFilterInfo& info) { + return info.gradient_mask(); + } + static bool Read(gfx::mojom::MaskFilterInfoDataView data, gfx::MaskFilterInfo* out); }; diff --git a/chromium/ui/gfx/mojom/mojom_traits_unittest.cc b/chromium/ui/gfx/mojom/mojom_traits_unittest.cc index 2ba0059d289..40681acf91e 100644 --- a/chromium/ui/gfx/mojom/mojom_traits_unittest.cc +++ b/chromium/ui/gfx/mojom/mojom_traits_unittest.cc @@ -147,7 +147,7 @@ TEST_F(StructTraitsTest, AcceleratedWidget) { TEST_F(StructTraitsTest, GpuMemoryBufferHandle) { const gfx::GpuMemoryBufferId kId(99); const uint32_t kOffset = 126; - const int32_t kStride = 256; + const uint32_t kStride = 256; base::UnsafeSharedMemoryRegion shared_memory_region = base::UnsafeSharedMemoryRegion::Create(1024); ASSERT_TRUE(shared_memory_region.IsValid()); diff --git a/chromium/ui/gfx/mojom/native_handle_types.mojom b/chromium/ui/gfx/mojom/native_handle_types.mojom index d8079b38104..ea664c8e9b4 100644 --- a/chromium/ui/gfx/mojom/native_handle_types.mojom +++ b/chromium/ui/gfx/mojom/native_handle_types.mojom @@ -23,11 +23,12 @@ struct NativePixmapPlane { struct NativePixmapHandle { array<NativePixmapPlane> planes; - [EnableIf=is_linux] - uint64 modifier; - [EnableIf=is_chromeos_ash] + [EnableIf=is_linux_or_chromeos_ash] uint64 modifier; + [EnableIf=is_linux_or_chromeos_ash] + bool supports_zero_copy_webgpu_import; + [EnableIf=is_fuchsia] mojo_base.mojom.UnguessableToken? buffer_collection_id; [EnableIf=is_fuchsia] diff --git a/chromium/ui/gfx/mojom/native_handle_types_mojom_traits.cc b/chromium/ui/gfx/mojom/native_handle_types_mojom_traits.cc index 78cc177333d..a0a320a0137 100644 --- a/chromium/ui/gfx/mojom/native_handle_types_mojom_traits.cc +++ b/chromium/ui/gfx/mojom/native_handle_types_mojom_traits.cc @@ -47,6 +47,8 @@ bool StructTraits< gfx::NativePixmapHandle* out) { #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) out->modifier = data.modifier(); + out->supports_zero_copy_webgpu_import = + data.supports_zero_copy_webgpu_import(); #endif #if BUILDFLAG(IS_FUCHSIA) diff --git a/chromium/ui/gfx/mojom/native_handle_types_mojom_traits.h b/chromium/ui/gfx/mojom/native_handle_types_mojom_traits.h index 7bd369ccbd7..ffeb3b51d7a 100644 --- a/chromium/ui/gfx/mojom/native_handle_types_mojom_traits.h +++ b/chromium/ui/gfx/mojom/native_handle_types_mojom_traits.h @@ -59,6 +59,13 @@ struct COMPONENT_EXPORT(GFX_NATIVE_HANDLE_TYPES_SHARED_MOJOM_TRAITS) } #endif +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) + static bool supports_zero_copy_webgpu_import( + const gfx::NativePixmapHandle& pixmap_handle) { + return pixmap_handle.supports_zero_copy_webgpu_import; + } +#endif + #if BUILDFLAG(IS_FUCHSIA) static const absl::optional<base::UnguessableToken>& buffer_collection_id( const gfx::NativePixmapHandle& pixmap_handle) { diff --git a/chromium/ui/gfx/overlay_plane_data.cc b/chromium/ui/gfx/overlay_plane_data.cc index fb90ed6344a..bfd3d1920e1 100644 --- a/chromium/ui/gfx/overlay_plane_data.cc +++ b/chromium/ui/gfx/overlay_plane_data.cc @@ -20,7 +20,7 @@ OverlayPlaneData::OverlayPlaneData( const gfx::RRectF& rounded_corners, const gfx::ColorSpace& color_space, const absl::optional<HDRMetadata>& hdr_metadata, - absl::optional<SkColor> color, + absl::optional<SkColor4f> color, bool is_solid_color) : z_order(z_order), plane_transform(plane_transform), diff --git a/chromium/ui/gfx/overlay_plane_data.h b/chromium/ui/gfx/overlay_plane_data.h index f9d330333ed..99488b0db14 100644 --- a/chromium/ui/gfx/overlay_plane_data.h +++ b/chromium/ui/gfx/overlay_plane_data.h @@ -31,7 +31,7 @@ struct GFX_EXPORT OverlayPlaneData { const gfx::RRectF& rounded_corners, const gfx::ColorSpace& color_space, const absl::optional<HDRMetadata>& hdr_metadata, - absl::optional<SkColor> color = absl::nullopt, + absl::optional<SkColor4f> color = absl::nullopt, bool is_solid_color = false); ~OverlayPlaneData(); @@ -76,7 +76,7 @@ struct GFX_EXPORT OverlayPlaneData { // Represents either a background of this overlay or a color of a solid color // quad, which can be checked via the |is_solid_color|. - absl::optional<SkColor> color; + absl::optional<SkColor4f> color; // Set if this is a solid color quad. bool is_solid_color; diff --git a/chromium/ui/gfx/platform_font_skia.cc b/chromium/ui/gfx/platform_font_skia.cc index 4a829602b5d..cefc3fe7429 100644 --- a/chromium/ui/gfx/platform_font_skia.cc +++ b/chromium/ui/gfx/platform_font_skia.cc @@ -22,13 +22,16 @@ #include "ui/gfx/font.h" #include "ui/gfx/font_list.h" #include "ui/gfx/font_render_params.h" -#include "ui/gfx/skia_font_delegate.h" #include "ui/gfx/text_utils.h" #if BUILDFLAG(IS_WIN) #include "ui/gfx/system_fonts_win.h" #endif +#if BUILDFLAG(IS_LINUX) +#include "ui/linux/linux_ui.h" +#endif + namespace gfx { namespace { @@ -163,13 +166,17 @@ void PlatformFontSkia::EnsuresDefaultFontIsInitialized() { weight = system_font.GetWeight(); #endif // BUILDFLAG(IS_WIN) - // On Linux, SkiaFontDelegate is used to query the native toolkit (e.g. - // GTK+) for the default UI font. - const SkiaFontDelegate* delegate = SkiaFontDelegate::instance(); - if (delegate) { - delegate->GetDefaultFontDescription(&family, &size_pixels, &style, &weight, - ¶ms); - } else if (default_font_description_) { +#if BUILDFLAG(IS_LINUX) + // On Linux, LinuxUi is used to query the native toolkit (e.g. + // GTK) for the default UI font. + if (const auto* linux_ui = ui::LinuxUi::instance()) { + int weight_int; + linux_ui->GetDefaultFontDescription( + &family, &size_pixels, &style, static_cast<int*>(&weight_int), ¶ms); + weight = static_cast<Font::Weight>(weight_int); + } else +#endif + if (default_font_description_) { #if BUILDFLAG(IS_CHROMEOS) // On ChromeOS, a FontList font description string is stored as a // translatable resource and passed in via SetDefaultFontDescription(). diff --git a/chromium/ui/gfx/platform_font_skia_unittest.cc b/chromium/ui/gfx/platform_font_skia_unittest.cc index d2ad3c7ca47..6060900a2d1 100644 --- a/chromium/ui/gfx/platform_font_skia_unittest.cc +++ b/chromium/ui/gfx/platform_font_skia_unittest.cc @@ -15,17 +15,20 @@ #include "ui/gfx/font.h" #include "ui/gfx/font_names_testing.h" #include "ui/gfx/font_render_params.h" -#include "ui/gfx/skia_font_delegate.h" #if BUILDFLAG(IS_WIN) #include "ui/gfx/system_fonts_win.h" #endif +#if BUILDFLAG(IS_LINUX) +#include "ui/linux/fake_linux_ui.h" +#endif + namespace gfx { -// Implementation of SkiaFontDelegate used to control the default font -// description. -class TestFontDelegate : public SkiaFontDelegate { +#if BUILDFLAG(IS_LINUX) +// Implementation of LinuxUi used to control the default font description. +class TestFontDelegate : public ui::FakeLinuxUi { public: TestFontDelegate() = default; @@ -48,12 +51,12 @@ class TestFontDelegate : public SkiaFontDelegate { void GetDefaultFontDescription(std::string* family_out, int* size_pixels_out, int* style_out, - Font::Weight* weight_out, + int* weight_out, FontRenderParams* params_out) const override { *family_out = family_; *size_pixels_out = size_pixels_; *style_out = style_; - *weight_out = weight_; + *weight_out = static_cast<int>(weight_); *params_out = params_; } @@ -76,36 +79,33 @@ class PlatformFontSkiaTest : public testing::Test { ~PlatformFontSkiaTest() override = default; void SetUp() override { - original_font_delegate_ = SkiaFontDelegate::instance(); - SkiaFontDelegate::SetInstance(&test_font_delegate_); + DCHECK_EQ(ui::LinuxUi::instance(), nullptr); + auto test_font_delegate = std::make_unique<TestFontDelegate>(); + test_font_delegate_ = test_font_delegate.get(); + ui::LinuxUi::SetInstance(std::move(test_font_delegate)); PlatformFontSkia::ReloadDefaultFont(); } void TearDown() override { - DCHECK_EQ(&test_font_delegate_, SkiaFontDelegate::instance()); - SkiaFontDelegate::SetInstance( - const_cast<SkiaFontDelegate*>(original_font_delegate_.get())); + DCHECK_EQ(test_font_delegate_, ui::LinuxUi::instance()); + ui::LinuxUi::SetInstance(nullptr); PlatformFontSkia::ReloadDefaultFont(); } protected: - TestFontDelegate test_font_delegate_; - - private: - // Originally-registered delegate. - raw_ptr<const SkiaFontDelegate> original_font_delegate_; + TestFontDelegate* test_font_delegate_ = nullptr; }; // Test that PlatformFontSkia's default constructor initializes the instance // with the correct parameters. TEST_F(PlatformFontSkiaTest, DefaultFont) { - test_font_delegate_.set_family(kTestFontName); - test_font_delegate_.set_size_pixels(13); - test_font_delegate_.set_style(Font::NORMAL); + test_font_delegate_->set_family(kTestFontName); + test_font_delegate_->set_size_pixels(13); + test_font_delegate_->set_style(Font::NORMAL); FontRenderParams params; params.antialiasing = false; params.hinting = FontRenderParams::HINTING_FULL; - test_font_delegate_.set_params(params); + test_font_delegate_->set_params(params); scoped_refptr<gfx::PlatformFontSkia> font(new gfx::PlatformFontSkia()); EXPECT_EQ(kTestFontName, font->GetFontName()); EXPECT_EQ(13, font->GetFontSize()); @@ -115,10 +115,10 @@ TEST_F(PlatformFontSkiaTest, DefaultFont) { EXPECT_EQ(params.hinting, font->GetFontRenderParams().hinting); // Drop the old default font and check that new settings are loaded. - test_font_delegate_.set_family(kSymbolFontName); - test_font_delegate_.set_size_pixels(15); - test_font_delegate_.set_style(gfx::Font::ITALIC); - test_font_delegate_.set_weight(gfx::Font::Weight::BOLD); + test_font_delegate_->set_family(kSymbolFontName); + test_font_delegate_->set_size_pixels(15); + test_font_delegate_->set_style(gfx::Font::ITALIC); + test_font_delegate_->set_weight(gfx::Font::Weight::BOLD); PlatformFontSkia::ReloadDefaultFont(); scoped_refptr<gfx::PlatformFontSkia> font2(new gfx::PlatformFontSkia()); EXPECT_EQ(kSymbolFontName, font2->GetFontName()); @@ -126,6 +126,7 @@ TEST_F(PlatformFontSkiaTest, DefaultFont) { EXPECT_NE(font2->GetStyle() & Font::ITALIC, 0); EXPECT_EQ(gfx::Font::Weight::BOLD, font2->GetWeight()); } +#endif // BUILDFLAG(IS_LINUX) TEST(PlatformFontSkiaRenderParamsTest, DefaultFontRenderParams) { scoped_refptr<PlatformFontSkia> default_font(new PlatformFontSkia()); diff --git a/chromium/ui/gfx/range/mojom/range_mojom_traits.h b/chromium/ui/gfx/range/mojom/range_mojom_traits.h index 5db4501e6c8..381f0091bb5 100644 --- a/chromium/ui/gfx/range/mojom/range_mojom_traits.h +++ b/chromium/ui/gfx/range/mojom/range_mojom_traits.h @@ -13,8 +13,12 @@ namespace mojo { template <> struct StructTraits<gfx::mojom::RangeDataView, gfx::Range> { - static uint32_t start(const gfx::Range& r) { return r.start(); } - static uint32_t end(const gfx::Range& r) { return r.end(); } + static uint32_t start(const gfx::Range& r) { + return static_cast<uint32_t>(r.start()); + } + static uint32_t end(const gfx::Range& r) { + return static_cast<uint32_t>(r.end()); + } static bool Read(gfx::mojom::RangeDataView data, gfx::Range* out) { out->set_start(data.start()); out->set_end(data.end()); diff --git a/chromium/ui/gfx/range/mojom/range_mojom_traits_unittest.cc b/chromium/ui/gfx/range/mojom/range_mojom_traits_unittest.cc index ba49cb82c2a..31392d66b4c 100644 --- a/chromium/ui/gfx/range/mojom/range_mojom_traits_unittest.cc +++ b/chromium/ui/gfx/range/mojom/range_mojom_traits_unittest.cc @@ -46,14 +46,17 @@ class RangeStructTraitsTest : public testing::Test, } // namespace TEST_F(RangeStructTraitsTest, Range) { - const uint32_t start = 1234; - const uint32_t end = 5678; + const size_t start = 1234; + const size_t end = 5678; gfx::Range input(start, end); mojo::Remote<mojom::RangeTraitsTestService> remote = GetTraitsTestRemote(); gfx::Range output; remote->EchoRange(input, &output); EXPECT_EQ(start, output.start()); EXPECT_EQ(end, output.end()); + + remote->EchoRange(gfx::Range::InvalidRange(), &output); + EXPECT_FALSE(output.IsValid()); } TEST_F(RangeStructTraitsTest, RangeF) { diff --git a/chromium/ui/gfx/range/range.cc b/chromium/ui/gfx/range/range.cc index 699040e7bae..e2a194b6291 100644 --- a/chromium/ui/gfx/range/range.cc +++ b/chromium/ui/gfx/range/range.cc @@ -6,12 +6,13 @@ #include <inttypes.h> +#include "base/format_macros.h" #include "base/strings/stringprintf.h" namespace gfx { std::string Range::ToString() const { - return base::StringPrintf("{%" PRIu32 ",%" PRIu32 "}", start(), end()); + return base::StringPrintf("{%" PRIuS ",%" PRIuS "}", start(), end()); } std::ostream& operator<<(std::ostream& os, const Range& range) { diff --git a/chromium/ui/gfx/range/range.h b/chromium/ui/gfx/range/range.h index b3708e41f7d..c2aceb22241 100644 --- a/chromium/ui/gfx/range/range.h +++ b/chromium/ui/gfx/range/range.h @@ -13,6 +13,7 @@ #include <ostream> #include <string> +#include "base/numerics/safe_conversions.h" #include "build/build_config.h" #include "ui/gfx/range/gfx_range_export.h" @@ -37,10 +38,12 @@ class GFX_RANGE_EXPORT Range { constexpr Range() : Range(0) {} // Initializes the range with a start and end. - constexpr Range(uint32_t start, uint32_t end) : start_(start), end_(end) {} + constexpr Range(size_t start, size_t end) + : start_(base::checked_cast<uint32_t>(start)), + end_(base::checked_cast<uint32_t>(end)) {} // Initializes the range with the same start and end positions. - constexpr explicit Range(uint32_t position) : Range(position, position) {} + constexpr explicit Range(size_t position) : Range(position, position) {} // Platform constructors. #if BUILDFLAG(IS_APPLE) @@ -52,27 +55,28 @@ class GFX_RANGE_EXPORT Range { return Range(std::numeric_limits<uint32_t>::max()); } - // Checks if the range is valid through comparison to InvalidRange(). + // Checks if the range is valid through comparison to InvalidRange(). If this + // is not valid, you must not call start()/end(). constexpr bool IsValid() const { return *this != InvalidRange(); } // Getters and setters. - constexpr uint32_t start() const { return start_; } - void set_start(uint32_t start) { start_ = start; } + constexpr size_t start() const { return start_; } + void set_start(size_t start) { start_ = base::checked_cast<uint32_t>(start); } - constexpr uint32_t end() const { return end_; } - void set_end(uint32_t end) { end_ = end; } + constexpr size_t end() const { return end_; } + void set_end(size_t end) { end_ = base::checked_cast<uint32_t>(end); } // Returns the absolute value of the length. - constexpr uint32_t length() const { return GetMax() - GetMin(); } + constexpr size_t length() const { return GetMax() - GetMin(); } constexpr bool is_reversed() const { return start() > end(); } constexpr bool is_empty() const { return start() == end(); } // Returns the minimum and maximum values. - constexpr uint32_t GetMin() const { + constexpr size_t GetMin() const { return start() < end() ? start() : end(); } - constexpr uint32_t GetMax() const { + constexpr size_t GetMax() const { return start() > end() ? start() : end(); } @@ -109,8 +113,8 @@ class GFX_RANGE_EXPORT Range { // If they don't intersect, it returns an InvalidRange(). // The returned range is always empty or forward (never reversed). constexpr Range Intersect(const Range& range) const { - const uint32_t min = std::max(GetMin(), range.GetMin()); - const uint32_t max = std::min(GetMax(), range.GetMax()); + const size_t min = std::max(GetMin(), range.GetMin()); + const size_t max = std::min(GetMax(), range.GetMax()); return (min < max || Contains(range) || range.Contains(*this)) ? Range(min, max) : InvalidRange(); @@ -129,8 +133,7 @@ class GFX_RANGE_EXPORT Range { private: // Note: we use uint32_t instead of size_t because this struct is sent over - // IPC which could span 32 & 64 bit processes. This is fine since text spans - // shouldn't exceed UINT32_MAX even on 64 bit builds. + // IPC which could span 32 & 64 bit processes. uint32_t start_; uint32_t end_; }; diff --git a/chromium/ui/gfx/range/range_mac.mm b/chromium/ui/gfx/range/range_mac.mm index cc1aa1ee4e2..6818cd5fe3d 100644 --- a/chromium/ui/gfx/range/range_mac.mm +++ b/chromium/ui/gfx/range/range_mac.mm @@ -22,8 +22,6 @@ Range& Range::operator=(const NSRange& range) { *this = InvalidRange(); } else { set_start(range.location); - // Don't overflow |end_|. - DCHECK_LE(range.length, std::numeric_limits<size_t>::max() - start()); set_end(start() + range.length); } return *this; diff --git a/chromium/ui/gfx/render_text.cc b/chromium/ui/gfx/render_text.cc index 7fb46dbdee7..851249f8355 100644 --- a/chromium/ui/gfx/render_text.cc +++ b/chromium/ui/gfx/render_text.cc @@ -144,9 +144,15 @@ sk_sp<cc::PaintShader> CreateFadeShader(const FontList& font_list, const SkPoint points[2] = { PointToSkPoint(text_rect.origin()), PointToSkPoint(text_rect.top_right()) }; + // TODO(crbug/1308932): Remove this helper vector colors4f and make all + // SkColor4f. + std::vector<SkColor4f> colors4f; + colors4f.reserve(colors.size()); + for (auto& c : colors) + colors4f.push_back(SkColor4f::FromColor(c)); return cc::PaintShader::MakeLinearGradient( - &points[0], &colors[0], &positions[0], static_cast<int>(colors.size()), - SkTileMode::kClamp); + &points[0], &colors4f[0], &positions[0], + static_cast<int>(colors4f.size()), SkTileMode::kClamp); } // Converts a FontRenderParams::Hinting value to the corresponding @@ -191,12 +197,14 @@ typename BreakList<T>::const_iterator IncrementBreakListIteratorToPosition( const BreakList<T>& break_list, typename BreakList<T>::const_iterator iter, size_t position) { - for (; iter != break_list.breaks().end(); ++iter) { + DCHECK_LT(position, break_list.max()); + for (;;) { + CHECK(iter != break_list.breaks().end()); const Range range = break_list.GetRange(iter); if (position >= range.start() && position < range.end()) - break; + return iter; + ++iter; } - return iter; } // Replaces the unicode control characters, control characters and PUA (Private @@ -526,7 +534,7 @@ void RenderText::SetText(const std::u16string& text) { if (directionality_mode_ == DIRECTIONALITY_FROM_TEXT) text_direction_ = base::i18n::UNKNOWN_DIRECTION; - obscured_reveal_index_ = -1; + obscured_reveal_index_ = absl::nullopt; OnTextAttributeChanged(); } @@ -534,7 +542,7 @@ void RenderText::AppendText(const std::u16string& text) { text_ += text; UpdateStyleLengths(); cached_bounds_and_offset_valid_ = false; - obscured_reveal_index_ = -1; + obscured_reveal_index_ = absl::nullopt; // Invalidate the cached text direction if it depends on the text contents. if (directionality_mode_ == DIRECTIONALITY_FROM_TEXT) @@ -572,20 +580,22 @@ void RenderText::SetFontList(const FontList& font_list) { } void RenderText::SetCursorEnabled(bool cursor_enabled) { - cursor_enabled_ = cursor_enabled; - cached_bounds_and_offset_valid_ = false; + if (cursor_enabled_ != cursor_enabled) { + cursor_enabled_ = cursor_enabled; + cached_bounds_and_offset_valid_ = false; + } } void RenderText::SetObscured(bool obscured) { if (obscured != obscured_) { obscured_ = obscured; - obscured_reveal_index_ = -1; + obscured_reveal_index_ = absl::nullopt; cached_bounds_and_offset_valid_ = false; OnTextAttributeChanged(); } } -void RenderText::SetObscuredRevealIndex(int index) { +void RenderText::SetObscuredRevealIndex(absl::optional<size_t> index) { if (obscured_reveal_index_ != index) { obscured_reveal_index_ = index; cached_bounds_and_offset_valid_ = false; @@ -609,8 +619,10 @@ void RenderText::SetMultiline(bool multiline) { } void RenderText::SetMaxLines(size_t max_lines) { - max_lines_ = max_lines; - OnDisplayTextAttributeChanged(); + if (max_lines_ != max_lines) { + max_lines_ = max_lines; + OnDisplayTextAttributeChanged(); + } } size_t RenderText::GetNumLines() { @@ -778,7 +790,7 @@ void RenderText::MoveCursor(BreakType break_type, bool RenderText::SetSelection(const SelectionModel& model) { // Enforce valid selection model components. - uint32_t text_length = static_cast<uint32_t>(text().length()); + size_t text_length = text().length(); std::vector<Range> ranges = model.GetAllSelections(); for (auto& range : ranges) { range = {std::min(range.start(), text_length), @@ -804,7 +816,7 @@ bool RenderText::MoveCursorToPoint(const Point& point, } bool RenderText::SelectRange(const Range& range, bool primary) { - uint32_t text_length = static_cast<uint32_t>(text().length()); + size_t text_length = text().length(); Range sel(std::min(range.start(), text_length), std::min(range.end(), text_length)); // Allow selection bounds at valid indices amid multi-character graphemes. @@ -854,61 +866,61 @@ void RenderText::SetCompositionRange(const Range& composition_range) { } void RenderText::SetColor(SkColor value) { - colors_.SetValue(value); - OnLayoutTextAttributeChanged(false); + if (colors_.SetValue(value)) + OnLayoutTextAttributeChanged(false); } void RenderText::ApplyColor(SkColor value, const Range& range) { - colors_.ApplyValue(value, range); - OnLayoutTextAttributeChanged(false); + if (colors_.ApplyValue(value, range)) + OnLayoutTextAttributeChanged(false); } void RenderText::SetBaselineStyle(BaselineStyle value) { - baselines_.SetValue(value); - OnLayoutTextAttributeChanged(false); + if (baselines_.SetValue(value)) + OnLayoutTextAttributeChanged(false); } void RenderText::ApplyBaselineStyle(BaselineStyle value, const Range& range) { - baselines_.ApplyValue(value, range); - OnLayoutTextAttributeChanged(false); + if (baselines_.ApplyValue(value, range)) + OnLayoutTextAttributeChanged(false); } void RenderText::ApplyFontSizeOverride(int font_size_override, const Range& range) { - font_size_overrides_.ApplyValue(font_size_override, range); - OnLayoutTextAttributeChanged(false); + if (font_size_overrides_.ApplyValue(font_size_override, range)) + OnLayoutTextAttributeChanged(false); } void RenderText::SetStyle(TextStyle style, bool value) { - styles_[style].SetValue(value); - - cached_bounds_and_offset_valid_ = false; - // TODO(oshima|msw): Not all style change requires layout changes. - // Consider optimizing based on the type of change. - OnLayoutTextAttributeChanged(false); + if (styles_[style].SetValue(value)) { + cached_bounds_and_offset_valid_ = false; + // TODO(oshima|msw): Not all style change requires layout changes. + // Consider optimizing based on the type of change. + OnLayoutTextAttributeChanged(false); + } } void RenderText::ApplyStyle(TextStyle style, bool value, const Range& range) { - styles_[style].ApplyValue(value, range); - - cached_bounds_and_offset_valid_ = false; - // TODO(oshima|msw): Not all style change requires layout changes. - // Consider optimizing based on the type of change. - OnLayoutTextAttributeChanged(false); + if (styles_[style].ApplyValue(value, range)) { + cached_bounds_and_offset_valid_ = false; + // TODO(oshima|msw): Not all style change requires layout changes. + // Consider optimizing based on the type of change. + OnLayoutTextAttributeChanged(false); + } } void RenderText::SetWeight(Font::Weight weight) { - weights_.SetValue(weight); - - cached_bounds_and_offset_valid_ = false; - OnLayoutTextAttributeChanged(false); + if (weights_.SetValue(weight)) { + cached_bounds_and_offset_valid_ = false; + OnLayoutTextAttributeChanged(false); + } } void RenderText::ApplyWeight(Font::Weight weight, const Range& range) { - weights_.ApplyValue(weight, range); - - cached_bounds_and_offset_valid_ = false; - OnLayoutTextAttributeChanged(false); + if (weights_.ApplyValue(weight, range)) { + cached_bounds_and_offset_valid_ = false; + OnLayoutTextAttributeChanged(false); + } } bool RenderText::GetStyle(TextStyle style) const { @@ -1538,8 +1550,8 @@ void RenderText::EnsureLayoutTextUpdated() const { // Ensures the reveal index is at a codepoint boundary (e.g. not in a middle // of a surrogate pairs). size_t reveal_index = text_.size(); - if (obscured_reveal_index_ != -1) { - reveal_index = base::checked_cast<size_t>(obscured_reveal_index_); + if (obscured_reveal_index_.has_value()) { + reveal_index = obscured_reveal_index_.value(); // Move |reveal_index| to the beginning of the surrogate pair, if needed. if (reveal_index < text_.size()) U16_SET_CP_START(text_.data(), 0, reveal_index); @@ -1680,7 +1692,6 @@ void RenderText::UpdateDisplayText(float text_width) { static_cast<float>(display_rect_.width()), elide_behavior_)); } else { - bool was_elided = text_elided_; text_elided_ = false; display_text_.clear(); @@ -1705,12 +1716,7 @@ void RenderText::UpdateDisplayText(float text_width) { Elide(text_to_elide, 0, static_cast<float>(display_rect_.width()), ELIDE_TAIL)); - // Have GetLineBreaks() re-calculate. - line_breaks_.SetMax(0); } else { - // If elision changed, re-calculate. - if (was_elided) - line_breaks_.SetMax(0); // Initial state above is fine. return; } @@ -1720,26 +1726,6 @@ void RenderText::UpdateDisplayText(float text_width) { display_text_.clear(); } -const BreakList<size_t>& RenderText::GetLineBreaks() { - if (line_breaks_.max() != 0) - return line_breaks_; - - const std::u16string& layout_text = GetDisplayText(); - const size_t text_length = layout_text.length(); - line_breaks_.SetValue(0); - line_breaks_.SetMax(text_length); - base::i18n::BreakIterator iter(layout_text, - base::i18n::BreakIterator::BREAK_LINE); - const bool success = iter.Init(); - DCHECK(success); - if (success) { - do { - line_breaks_.ApplyValue(iter.pos(), Range(iter.pos(), text_length)); - } while (iter.Advance()); - } - return line_breaks_; -} - Point RenderText::ToViewPoint(const PointF& point, size_t line) { if (GetNumLines() == 1) { return Point(base::ClampCeil(Clamp(point.x())), @@ -1939,7 +1925,8 @@ int RenderText::GetLineContainingYCoord(float text_y) { bool RenderText::RangeContainsCaret(const Range& range, size_t caret_pos, LogicalCursorDirection caret_affinity) { - // NB: exploits unsigned wraparound (WG14/N1124 section 6.2.5 paragraph 9). + if (caret_pos == 0 && caret_affinity == CURSOR_BACKWARD) + return false; size_t adjacent = (caret_affinity == CURSOR_BACKWARD) ? caret_pos - 1 : caret_pos + 1; return range.Contains(Range(caret_pos, adjacent)); @@ -2011,7 +1998,6 @@ void RenderText::OnTextAttributeChanged() { layout_text_.clear(); display_text_.clear(); text_elided_ = false; - line_breaks_.SetMax(0); layout_text_up_to_date_ = false; diff --git a/chromium/ui/gfx/render_text.h b/chromium/ui/gfx/render_text.h index 983cba19002..d6e7a79fb9d 100644 --- a/chromium/ui/gfx/render_text.h +++ b/chromium/ui/gfx/render_text.h @@ -297,10 +297,10 @@ class GFX_EXPORT RenderText { // Makes a char in obscured text at |index| to be revealed. |index| should be // a UTF16 text index. If there is a previous revealed index, the previous one - // is cleared and only the last set index will be revealed. If |index| is -1 - // or out of range, no char will be revealed. The revealed index is also - // cleared when SetText or SetObscured is called. - void SetObscuredRevealIndex(int index); + // is cleared and only the last set index will be revealed. If |index| is + // nullopt or out of range, no char will be revealed. The revealed index is + // also cleared when SetText or SetObscured is called. + void SetObscuredRevealIndex(absl::optional<size_t> index); // For obscured (password) fields, the extra spacing between glyphs. int obscured_glyph_spacing() const { return obscured_glyph_spacing_; } @@ -768,9 +768,6 @@ class GFX_EXPORT RenderText { // Update the display text. void UpdateDisplayText(float text_width); - // Returns display text positions that are suitable for breaking lines. - const BreakList<size_t>& GetLineBreaks(); - // Convert points from the text space to the view space. Handles the display // area, display offset, application LTR/RTL mode and multiline. |line| is the // index of the line in which |point| is found, and is required to be passed @@ -971,7 +968,7 @@ class GFX_EXPORT RenderText { // A flag to obscure actual text with asterisks for password fields. bool obscured_ = false; // The index at which the char should be revealed in the obscured text. - int obscured_reveal_index_ = -1; + absl::optional<size_t> obscured_reveal_index_; // The maximum length of text to display, 0 forgoes a hard limit. size_t truncate_length_ = 0; @@ -1038,9 +1035,6 @@ class GFX_EXPORT RenderText { // Text shadows to be drawn. ShadowValues shadows_; - // A list of valid display text line break positions. - BreakList<size_t> line_breaks_; - // Text shaping computed by EnsureLayout. This should be invalidated upon // OnLayoutTextAttributeChanged and OnDisplayTextAttributeChanged calls. std::unique_ptr<internal::ShapedText> shaped_text_; diff --git a/chromium/ui/gfx/render_text_api_fuzzer.cc b/chromium/ui/gfx/render_text_api_fuzzer.cc index 02a238b692f..38f7a3bf6e3 100644 --- a/chromium/ui/gfx/render_text_api_fuzzer.cc +++ b/chromium/ui/gfx/render_text_api_fuzzer.cc @@ -12,17 +12,16 @@ #include "base/logging.h" #include "base/strings/utf_string_conversions.h" #include "base/test/task_environment.h" +#include "base/test/test_discardable_memory_allocator.h" #include "base/test/test_timeouts.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" #include "ui/gfx/canvas.h" +#include "ui/gfx/font_util.h" #include "ui/gfx/render_text.h" -// TODO(crbug.com/1052397): Revisit once build flag switch of lacros-chrome is -// complete. -#if BUILDFLAG(IS_ANDROID) || \ - (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) -#include "base/test/test_discardable_memory_allocator.h" +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) +#include "third_party/test_fonts/fontconfig/fontconfig_util_linux.h" #endif namespace { @@ -41,25 +40,21 @@ struct Environment { TestTimeouts::Initialize(), base::test::TaskEnvironment::MainThreadType::UI)) { logging::SetMinLogLevel(logging::LOG_FATAL); -// TODO(crbug.com/1052397): Revisit once build flag switch of lacros-chrome is -// complete. -#if BUILDFLAG(IS_ANDROID) || \ - (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) + // Some platforms require discardable memory to use bitmap fonts. base::DiscardableMemoryAllocator::SetInstance( &discardable_memory_allocator); -#endif + CHECK(base::i18n::InitializeICU()); + +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) + test_fonts::SetUpFontconfig(); +#endif + gfx::InitializeFonts(); gfx::FontList::SetDefaultFontDescription(kFontDescription); } -// TODO(crbug.com/1052397): Revisit once build flag switch of lacros-chrome is -// complete. -#if BUILDFLAG(IS_ANDROID) || \ - (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) base::TestDiscardableMemoryAllocator discardable_memory_allocator; -#endif - base::AtExitManager at_exit_manager; base::test::TaskEnvironment task_environment; }; @@ -164,24 +159,44 @@ gfx::WordWrapBehavior ConsumeWordWrap(FuzzedDataProvider* fdp) { } } -gfx::ElideBehavior ConsumeElideBehavior(FuzzedDataProvider* fdp) { - switch (fdp->ConsumeIntegralInRange(0, 7)) { - case 0: - return gfx::NO_ELIDE; - case 1: - return gfx::TRUNCATE; - case 2: - return gfx::ELIDE_HEAD; - case 3: - return gfx::ELIDE_MIDDLE; - case 4: - return gfx::ELIDE_TAIL; - case 5: - return gfx::ELIDE_EMAIL; - case 6: - return gfx::FADE_TAIL; - default: - return gfx::NO_ELIDE; +gfx::ElideBehavior ConsumeElideBehavior(FuzzedDataProvider* fdp, + bool generate_only_homogeneous_styles) { + if (generate_only_homogeneous_styles) { + // The styles are guaranteed to be homogenous and it is safe to generate + // any eliding behavior. + switch (fdp->ConsumeIntegralInRange(0, 7)) { + case 0: + return gfx::NO_ELIDE; + case 1: + return gfx::TRUNCATE; + case 2: + return gfx::ELIDE_HEAD; + case 3: + return gfx::ELIDE_MIDDLE; + case 4: + return gfx::ELIDE_TAIL; + case 5: + return gfx::ELIDE_EMAIL; + case 6: + return gfx::FADE_TAIL; + default: + return gfx::NO_ELIDE; + } + } else { + // Only generate eliding behaviors that are compatible with non homogeneous + // text. Remove this when http://crbug.com/1085014 is fixed. + switch (fdp->ConsumeIntegralInRange(0, 4)) { + case 0: + return gfx::NO_ELIDE; + case 1: + return gfx::TRUNCATE; + case 2: + return gfx::ELIDE_TAIL; + case 3: + return gfx::FADE_TAIL; + default: + return gfx::NO_ELIDE; + } } } @@ -211,6 +226,16 @@ gfx::Range ConsumeRange(FuzzedDataProvider* fdp, size_t max) { return gfx::Range(start, end); } +// Eliding behaviors are not all fully supported by RenderText. Ignore +// unsupported cases. This is causing clusterfuzz to fail with invalid +// tests (http://crbug.com/1185542). Remove when https://crbug.com/1085014 is +// fixed. +bool DoesDisplayRangeSupportElideBehavior(const gfx::RenderText* render_text) { + const gfx::ElideBehavior behavior = render_text->elide_behavior(); + return behavior != gfx::ELIDE_HEAD && behavior != gfx::ELIDE_MIDDLE && + behavior != gfx::ELIDE_EMAIL; +} + const int kMaxStringLength = 128; } // anonymous namespace @@ -223,6 +248,14 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { gfx::Canvas canvas; FuzzedDataProvider fdp(data, size); + if (size == 0) + return 0; + + // Eliding and Styles are not well supported by RenderText. DCHECKs are + // present in RenderText code to avoid any incorrect uses but the fuzzer + // should not generate them until full support (http://crbug.com/1283159). + const bool generate_only_homogeneous_styles = fdp.ConsumeBool(); + while (fdp.remaining_bytes() != 0) { const RenderTextAPI command = fdp.ConsumeEnum<RenderTextAPI>(); switch (command) { @@ -283,7 +316,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { break; case RenderTextAPI::kSetMultiline: - render_text->SetMultiline(fdp.ConsumeBool()); + if (generate_only_homogeneous_styles) { + render_text->SetMultiline(fdp.ConsumeBool()); + } break; case RenderTextAPI::kSetMaxLines: @@ -307,9 +342,11 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { break; case RenderTextAPI::kApplyColor: - render_text->ApplyColor( - ConsumeSkColor(&fdp), - ConsumeRange(&fdp, render_text->text().length())); + if (!generate_only_homogeneous_styles) { + render_text->ApplyColor( + ConsumeSkColor(&fdp), + ConsumeRange(&fdp, render_text->text().length())); + } break; case RenderTextAPI::kSetStyle: @@ -317,9 +354,11 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { break; case RenderTextAPI::kApplyStyle: - render_text->ApplyStyle( - ConsumeStyle(&fdp), fdp.ConsumeBool(), - ConsumeRange(&fdp, render_text->text().length())); + if (!generate_only_homogeneous_styles) { + render_text->ApplyStyle( + ConsumeStyle(&fdp), fdp.ConsumeBool(), + ConsumeRange(&fdp, render_text->text().length())); + } break; case RenderTextAPI::kSetWeight: @@ -327,9 +366,11 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { break; case RenderTextAPI::kApplyWeight: - render_text->ApplyWeight( - ConsumeWeight(&fdp), - ConsumeRange(&fdp, render_text->text().length())); + if (!generate_only_homogeneous_styles) { + render_text->ApplyWeight( + ConsumeWeight(&fdp), + ConsumeRange(&fdp, render_text->text().length())); + } break; case RenderTextAPI::kSetDirectionalityMode: @@ -337,7 +378,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { break; case RenderTextAPI::kSetElideBehavior: - render_text->SetElideBehavior(ConsumeElideBehavior(&fdp)); + render_text->SetElideBehavior( + ConsumeElideBehavior(&fdp, generate_only_homogeneous_styles)); break; case RenderTextAPI::kIsGraphemeBoundary: @@ -365,10 +407,18 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { fdp.ConsumeIntegralInRange<int>(0, 30))); break; case RenderTextAPI::kGetSubstringBounds: + // RenderText doesn't support that case (https://crbug.com/1085014). + if (!DoesDisplayRangeSupportElideBehavior(render_text.get())) + break; + render_text->GetSubstringBounds( ConsumeRange(&fdp, render_text->text().length())); break; case RenderTextAPI::kGetCursorSpan: + // RenderText doesn't support that case (https://crbug.com/1085014). + if (!DoesDisplayRangeSupportElideBehavior(render_text.get())) + break; + render_text->GetCursorSpan( ConsumeRange(&fdp, render_text->text().length())); break; diff --git a/chromium/ui/gfx/render_text_fuzzer.cc b/chromium/ui/gfx/render_text_fuzzer.cc index dc2a26c10fb..de1d7aec058 100644 --- a/chromium/ui/gfx/render_text_fuzzer.cc +++ b/chromium/ui/gfx/render_text_fuzzer.cc @@ -11,8 +11,13 @@ #include "base/test/test_timeouts.h" #include "build/build_config.h" #include "ui/gfx/canvas.h" +#include "ui/gfx/font_util.h" #include "ui/gfx/render_text.h" +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) +#include "third_party/test_fonts/fontconfig/fontconfig_util_linux.h" +#endif + namespace { #if BUILDFLAG(IS_WIN) @@ -31,6 +36,11 @@ struct Environment { logging::SetMinLogLevel(logging::LOG_FATAL); CHECK(base::i18n::InitializeICU()); + +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) + test_fonts::SetUpFontconfig(); +#endif + gfx::InitializeFonts(); gfx::FontList::SetDefaultFontDescription(kFontDescription); } diff --git a/chromium/ui/gfx/render_text_harfbuzz.cc b/chromium/ui/gfx/render_text_harfbuzz.cc index cd779904454..42d798e9b85 100644 --- a/chromium/ui/gfx/render_text_harfbuzz.cc +++ b/chromium/ui/gfx/render_text_harfbuzz.cc @@ -413,7 +413,6 @@ class HarfBuzzLineBreaker { float glyph_height_for_test, WordWrapBehavior word_wrap_behavior, const std::u16string& text, - const BreakList<size_t>* words, const internal::TextRunList& run_list) : max_width_((max_width == 0) ? SK_ScalarMax : SkIntToScalar(max_width)), min_baseline_(min_baseline), @@ -421,7 +420,6 @@ class HarfBuzzLineBreaker { glyph_height_for_test_(glyph_height_for_test), word_wrap_behavior_(word_wrap_behavior), text_(text), - words_(words), run_list_(run_list), max_descent_(0), max_ascent_(0), @@ -448,10 +446,17 @@ class HarfBuzzLineBreaker { // Constructs multiple lines for |text_| based on words iteration approach. void ConstructMultiLines() { - DCHECK(words_); - for (auto iter = words_->breaks().begin(); iter != words_->breaks().end(); - iter++) { - const Range word_range = words_->GetRange(iter); + // Get an iterator that pass through valid line breaking positions. + // See https://www.unicode.org/reports/tr14/tr14-11.html for lines breaking. + base::i18n::BreakIterator words(text_, + base::i18n::BreakIterator::BREAK_LINE); + const bool success = words.Init(); + DCHECK(success); + if (!success) + return; + + while (words.Advance()) { + const Range word_range = Range(words.prev(), words.pos()); std::vector<internal::LineSegment> word_segments; SkScalar word_width = GetWordWidth(word_range, &word_segments); @@ -674,8 +679,7 @@ class HarfBuzzLineBreaker { } const size_t valid_end_pos = std::max( - segment.char_range.start(), - static_cast<uint32_t>(FindValidBoundaryBefore(text_, end_pos))); + segment.char_range.start(), FindValidBoundaryBefore(text_, end_pos)); if (end_pos != valid_end_pos) { end_pos = valid_end_pos; width = run.GetGlyphWidthForCharRange( @@ -687,9 +691,8 @@ class HarfBuzzLineBreaker { // not separate surrogate pair or combining characters. // See RenderTextHarfBuzzTest.Multiline_MinWidth for an example. if (width == 0 && available_width_ == max_width_) { - end_pos = std::min( - segment.char_range.end(), - static_cast<uint32_t>(FindValidBoundaryAfter(text_, end_pos + 1))); + end_pos = std::min(segment.char_range.end(), + FindValidBoundaryAfter(text_, end_pos + 1)); } return end_pos; @@ -699,7 +702,6 @@ class HarfBuzzLineBreaker { // segments based on its runs. SkScalar GetWordWidth(const Range& word_range, std::vector<internal::LineSegment>* segments) const { - DCHECK(words_); if (word_range.is_empty() || segments == nullptr) return 0; size_t run_start_index = run_list_.GetRunIndexAt(word_range.start()); @@ -745,7 +747,6 @@ class HarfBuzzLineBreaker { const float glyph_height_for_test_; const WordWrapBehavior word_wrap_behavior_; const std::u16string& text_; - const raw_ptr<const BreakList<size_t>> words_; const internal::TextRunList& run_list_; // Stores the resulting lines. @@ -1705,7 +1706,7 @@ void RenderTextHarfBuzz::EnsureLayout() { display_rect().width(), DetermineBaselineCenteringText(height, font_list()), height, glyph_height_for_test_, word_wrap_behavior(), GetDisplayText(), - multiline() ? &GetLineBreaks() : nullptr, *run_list); + *run_list); if (multiline()) line_breaker.ConstructMultiLines(); @@ -1713,7 +1714,9 @@ void RenderTextHarfBuzz::EnsureLayout() { line_breaker.ConstructSingleLine(); std::vector<internal::Line> lines; line_breaker.FinalizeLines(&lines, &total_size_); - if (multiline() && max_lines()) { + // In multiline, only ELIDE_TAIL is supported. max_lines_ is not used + // otherwise. + if (multiline() && max_lines() && elide_behavior() == ELIDE_TAIL) { // TODO(crbug.com/866720): no more than max_lines() should be rendered. // Remove the IsHomogeneous() condition for the following DCHECK when the // bug is fixed. diff --git a/chromium/ui/gfx/render_text_unittest.cc b/chromium/ui/gfx/render_text_unittest.cc index fe40f1c6d2c..ab7dfc85ddc 100644 --- a/chromium/ui/gfx/render_text_unittest.cc +++ b/chromium/ui/gfx/render_text_unittest.cc @@ -511,12 +511,14 @@ class RenderTextTest : public testing::Test { size_t logical_index = run_list->visual_to_logical(i); const internal::TextRunHarfBuzz& run = *run_list->runs()[logical_index]; if (run.range.length() == 1) { - result.append(base::StringPrintf("[%d]", run.range.start())); + result.append(base::StringPrintf("[%" PRIuS "]", run.range.start())); } else if (run.font_params.is_rtl) { - result.append(base::StringPrintf("[%d<-%d]", run.range.end() - 1, + result.append(base::StringPrintf("[%" PRIuS "<-%" PRIuS "]", + run.range.end() - 1, run.range.start())); } else { - result.append(base::StringPrintf("[%d->%d]", run.range.start(), + result.append(base::StringPrintf("[%" PRIuS "->%" PRIuS "]", + run.range.start(), run.range.end() - 1)); } } @@ -1070,7 +1072,7 @@ TEST_F(RenderTextTest, SelectWithTranslucentBackground) { SkImageInfo::MakeN32Premul(kCanvasSize.width(), kCanvasSize.height())); cc::SkiaPaintCanvas paint_canvas(bitmap); Canvas canvas(&paint_canvas, 1.0f); - paint_canvas.clear(SK_ColorWHITE); + paint_canvas.clear(SkColors::kWhite); SetGlyphWidth(kGlyphWidth); RenderText* render_text = GetRenderText(); @@ -1320,7 +1322,7 @@ TEST_F(RenderTextTest, RevealObscuredText) { render_text->GetDisplayText()); // Invalid reveal index. - render_text->RenderText::SetObscuredRevealIndex(-1); + render_text->RenderText::SetObscuredRevealIndex(absl::nullopt); EXPECT_EQ(no_seuss, render_text->GetDisplayText()); render_text->RenderText::SetObscuredRevealIndex(seuss.length() + 1); EXPECT_EQ(no_seuss, render_text->GetDisplayText()); @@ -7423,7 +7425,7 @@ TEST_F(RenderTextTest, DISABLED_TextDoesntClip) { render_text->SetColor(SK_ColorBLACK); for (auto* string : kTestStrings) { - paint_canvas.clear(SK_ColorWHITE); + paint_canvas.clear(SkColors::kWhite); render_text->SetText(base::UTF8ToUTF16(string)); render_text->ApplyBaselineStyle(SUPERSCRIPT, Range(1, 2)); render_text->ApplyBaselineStyle(SUPERIOR, Range(3, 4)); @@ -7494,7 +7496,7 @@ TEST_F(RenderTextTest, DISABLED_TextDoesClip) { render_text->SetColor(SK_ColorBLACK); for (auto* string : kTestStrings) { - paint_canvas.clear(SK_ColorWHITE); + paint_canvas.clear(SkColors::kWhite); render_text->SetText(base::UTF8ToUTF16(string)); const Size string_size = render_text->GetStringSize(); int fake_width = string_size.width() / 2; @@ -8565,8 +8567,7 @@ TEST_F(RenderTextTest, Clusterfuzz_Issue_1298286) { gfx::FontList font_list; gfx::Rect field(2119635455, font_list.GetHeight()); - std::unique_ptr<gfx::RenderText> render_text = - gfx::RenderText::CreateRenderText(); + RenderText* render_text = GetRenderText(); render_text->SetFontList(font_list); render_text->SetHorizontalAlignment(ALIGN_RIGHT); render_text->SetDirectionalityMode(DIRECTIONALITY_FROM_UI); @@ -8574,7 +8575,7 @@ TEST_F(RenderTextTest, Clusterfuzz_Issue_1298286) { render_text->SetDisplayRect(field); render_text->SetCursorEnabled(true); - gfx::test::RenderTextTestApi render_text_test_api(render_text.get()); + gfx::test::RenderTextTestApi render_text_test_api(render_text); render_text_test_api.SetGlyphWidth(2016371456); EXPECT_FALSE(render_text->multiline()); @@ -8595,8 +8596,7 @@ TEST_F(RenderTextTest, Clusterfuzz_Issue_1299054) { gfx::FontList font_list; gfx::Rect field(-1334808765, font_list.GetHeight()); - std::unique_ptr<gfx::RenderText> render_text = - gfx::RenderText::CreateRenderText(); + RenderText* render_text = GetRenderText(); render_text->SetFontList(font_list); render_text->SetHorizontalAlignment(ALIGN_CENTER); render_text->SetDirectionalityMode(DIRECTIONALITY_FROM_TEXT); @@ -8604,7 +8604,7 @@ TEST_F(RenderTextTest, Clusterfuzz_Issue_1299054) { render_text->SetDisplayRect(field); render_text->SetCursorEnabled(false); - gfx::test::RenderTextTestApi render_text_test_api(render_text.get()); + gfx::test::RenderTextTestApi render_text_test_api(render_text); render_text_test_api.SetGlyphWidth(1778384896); const Vector2d& offset = render_text->GetUpdatedDisplayOffset(); @@ -8622,4 +8622,15 @@ TEST_F(RenderTextTest, Clusterfuzz_Issue_1287804) { EXPECT_EQ(RangeF(0, 0), render_text->GetCursorSpan(Range(0, 0))); } +TEST_F(RenderTextTest, Clusterfuzz_Issue_1193815) { + RenderText* render_text = GetRenderText(); + gfx::FontList font_list; + render_text->SetFontList(font_list); + render_text->Draw(canvas()); + render_text->SetText(u"F\r"); + render_text->SetMaxLines(1); + render_text->SetMultiline(true); + render_text->Draw(canvas()); +} + } // namespace gfx diff --git a/chromium/ui/gfx/selection_model.cc b/chromium/ui/gfx/selection_model.cc index a792731f0fc..98d557c26c9 100644 --- a/chromium/ui/gfx/selection_model.cc +++ b/chromium/ui/gfx/selection_model.cc @@ -66,7 +66,7 @@ std::string SelectionModel::ToString() const { for (auto selection : secondary_selections()) { str += ","; if (selection.is_empty()) - base::StringAppendF(&str, "%" PRIu32, selection.end()); + base::StringAppendF(&str, "%" PRIuS, selection.end()); else str += selection.ToString(); } diff --git a/chromium/ui/gfx/skia_font_delegate.cc b/chromium/ui/gfx/skia_font_delegate.cc deleted file mode 100644 index f7c24c5f5b8..00000000000 --- a/chromium/ui/gfx/skia_font_delegate.cc +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2013 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 "ui/gfx/skia_font_delegate.h" - -namespace { - -gfx::SkiaFontDelegate* g_skia_font_delegate = 0; - -} // namespace - -namespace gfx { - -void SkiaFontDelegate::SetInstance(SkiaFontDelegate* instance) { - g_skia_font_delegate = instance; -} - -const SkiaFontDelegate* SkiaFontDelegate::instance() { - return g_skia_font_delegate; -} - -} // namespace gfx diff --git a/chromium/ui/gfx/skia_font_delegate.h b/chromium/ui/gfx/skia_font_delegate.h deleted file mode 100644 index 05636e98fab..00000000000 --- a/chromium/ui/gfx/skia_font_delegate.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2013 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. - -#ifndef UI_GFX_SKIA_FONT_DELEGATE_H_ -#define UI_GFX_SKIA_FONT_DELEGATE_H_ - -#include <memory> -#include <string> - -#include "ui/gfx/font_render_params.h" -#include "ui/gfx/gfx_export.h" - -namespace gfx { - -// Allows a Linux platform-specific overriding of font preferences. -class GFX_EXPORT SkiaFontDelegate { - public: - virtual ~SkiaFontDelegate() {} - - // Sets the dynamically loaded singleton that provides font preferences. - // This pointer is not owned, and if this method is called a second time, - // the first instance is not deleted. - static void SetInstance(SkiaFontDelegate* instance); - - // Returns a SkiaFontDelegate instance for the toolkit used in - // the user's desktop environment. - // - // Can return NULL, in case no toolkit has been set. (For example, if we're - // running with the "--ash" flag.) - static const SkiaFontDelegate* instance(); - - // Returns the default font rendering settings. - virtual FontRenderParams GetDefaultFontRenderParams() const = 0; - - // Returns details about the default UI font. |style_out| holds a bitfield of - // gfx::Font::Style values. - virtual void GetDefaultFontDescription( - std::string* family_out, - int* size_pixels_out, - int* style_out, - Font::Weight* weight_out, - FontRenderParams* params_out) const = 0; -}; - -} // namespace gfx - -#endif // UI_GFX_SKIA_FONT_DELEGATE_H_ diff --git a/chromium/ui/gfx/skia_paint_util.cc b/chromium/ui/gfx/skia_paint_util.cc index 7bc2d44cb49..b25b305dae3 100644 --- a/chromium/ui/gfx/skia_paint_util.cc +++ b/chromium/ui/gfx/skia_paint_util.cc @@ -61,7 +61,9 @@ sk_sp<cc::PaintShader> CreateGradientShader(const gfx::Point& start_point, const gfx::Point& end_point, SkColor start_color, SkColor end_color) { - SkColor grad_colors[2] = {start_color, end_color}; + // TODO(crbug/1308932): Remove FromColor and make all SkColor4f. + SkColor4f grad_colors[2] = {SkColor4f::FromColor(start_color), + SkColor4f::FromColor(end_color)}; SkPoint grad_points[2] = {gfx::PointToSkPoint(start_point), gfx::PointToSkPoint(end_point)}; diff --git a/chromium/ui/gfx/swap_result.h b/chromium/ui/gfx/swap_result.h index 39a62d54e92..03e50112c7f 100644 --- a/chromium/ui/gfx/swap_result.h +++ b/chromium/ui/gfx/swap_result.h @@ -41,15 +41,13 @@ struct SwapTimings { // dicontinuities in associated UMA data. base::TimeTicks swap_end; - // When Display Compositor thread scheduled work to GPU Thread. For GLRenderer - // it's when InProcessCommandBuffer::Flush() happens, for SkiaRenderer it's - // PostTask time for FinishPaintRenderPass or SwapBuffers whichever comes - // first. + // When Display Compositor thread scheduled work to GPU Thread. For + // SkiaRenderer it's PostTask time for FinishPaintRenderPass or SwapBuffers + // whichever comes first. base::TimeTicks viz_scheduled_draw; // When GPU thread started draw submitted by Display Compositor thread. For - // GLRenderer it's InProcessCommandBuffer::FlushOnGpuThread, for SkiaRenderer - // it's FinishPaintRenderPass/SwapBuffers. + // SkiaRenderer it's FinishPaintRenderPass/SwapBuffers. base::TimeTicks gpu_started_draw; // When GPU scheduler removed the last required dependency. diff --git a/chromium/ui/gfx/win/hwnd_util.cc b/chromium/ui/gfx/win/hwnd_util.cc index b7ac93e6287..258a9844ef5 100644 --- a/chromium/ui/gfx/win/hwnd_util.cc +++ b/chromium/ui/gfx/win/hwnd_util.cc @@ -4,6 +4,7 @@ #include "ui/gfx/win/hwnd_util.h" +#include <dwmapi.h> // DWMWA_CLOAKED #include <windows.h> #include "base/debug/gdi_debug_util_win.h" @@ -114,6 +115,13 @@ void* GetWindowUserData(HWND hwnd) { return reinterpret_cast<void*>(GetWindowLongPtr(hwnd, GWLP_USERDATA)); } +bool IsWindowCloaked(HWND hwnd) { + BOOL is_cloaked = FALSE; + return SUCCEEDED(DwmGetWindowAttribute(hwnd, DWMWA_CLOAKED, &is_cloaked, + sizeof(is_cloaked))) && + is_cloaked; +} + absl::optional<bool> IsWindowOnCurrentVirtualDesktop( HWND window, Microsoft::WRL::ComPtr<IVirtualDesktopManager> virtual_desktop_manager) { diff --git a/chromium/ui/gfx/win/hwnd_util.h b/chromium/ui/gfx/win/hwnd_util.h index 06529229c44..a17c5a7943d 100644 --- a/chromium/ui/gfx/win/hwnd_util.h +++ b/chromium/ui/gfx/win/hwnd_util.h @@ -33,6 +33,11 @@ GFX_EXPORT void* GetWindowUserData(HWND hwnd); // of its children. GFX_EXPORT bool DoesWindowBelongToActiveWindow(HWND window); +// Returns true if the specified window is cloaked. Windows 10 and later +// have cloaked windows which are windows with WS_VISIBLE attribute but not +// displayed. +GFX_EXPORT bool IsWindowCloaked(HWND hwnd); + // Returns true if `window` is on the current virtual desktop, false if isn't, // and absl::nullopt if a COM method fails. Since this calls COM methods, // it can only be called from a COM thread. diff --git a/chromium/ui/gfx/x/connection.h b/chromium/ui/gfx/x/connection.h index 57c14b3d2d9..a21e84a5ca7 100644 --- a/chromium/ui/gfx/x/connection.h +++ b/chromium/ui/gfx/x/connection.h @@ -9,6 +9,7 @@ #include "base/component_export.h" #include "base/containers/circular_deque.h" #include "base/containers/flat_map.h" +#include "base/memory/raw_ptr.h" #include "base/observer_list.h" #include "base/sequence_checker.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -261,7 +262,7 @@ class COMPONENT_EXPORT(X11) Connection : public XProto, // The response must already have been obtained using WaitForResponse(). void TakeResponse(RawReply* reply, std::unique_ptr<Error>* error); - Connection* connection = nullptr; + raw_ptr<Connection, DanglingUntriaged> connection = nullptr; SequenceType sequence = 0; bool generates_reply = false; const char* request_name_for_tracing = nullptr; @@ -325,7 +326,7 @@ class COMPONENT_EXPORT(X11) Connection : public XProto, uint32_t GenerateIdImpl(); - xcb_connection_t* connection_ = nullptr; + raw_ptr<xcb_connection_t, DanglingUntriaged> connection_ = nullptr; std::unique_ptr<XlibDisplay> xlib_display_; bool synchronous_ = false; @@ -336,9 +337,9 @@ class COMPONENT_EXPORT(X11) Connection : public XProto, std::string display_string_; int default_screen_id_ = 0; Setup setup_; - Screen* default_screen_ = nullptr; - Depth* default_root_depth_ = nullptr; - VisualType* default_root_visual_ = nullptr; + raw_ptr<Screen> default_screen_ = nullptr; + raw_ptr<Depth> default_root_depth_ = nullptr; + raw_ptr<VisualType> default_root_visual_ = nullptr; base::flat_map<VisualId, VisualInfo> default_screen_visuals_; @@ -349,7 +350,7 @@ class COMPONENT_EXPORT(X11) Connection : public XProto, base::ObserverList<EventObserver>::Unchecked event_observers_; // The Event currently being dispatched, or nullptr if there is none. - const Event* dispatching_event_ = nullptr; + raw_ptr<const Event> dispatching_event_ = nullptr; base::circular_deque<Request> requests_; // The sequence ID of requests_.front(), or if |requests_| is empty, then the diff --git a/chromium/ui/gfx/x/event.h b/chromium/ui/gfx/x/event.h index dd2335149e4..66e611e5060 100644 --- a/chromium/ui/gfx/x/event.h +++ b/chromium/ui/gfx/x/event.h @@ -9,6 +9,7 @@ #include <utility> #include "base/component_export.h" +#include "base/memory/raw_ptr.h" #include "base/memory/ref_counted_memory.h" #include "base/memory/scoped_refptr.h" #include "ui/gfx/x/xproto.h" @@ -54,7 +55,7 @@ class COMPONENT_EXPORT(X11) Event { template <typename T> T* As() { if (type_id_ == T::type_id) - return reinterpret_cast<T*>(event_); + return reinterpret_cast<T*>(event_.get()); return nullptr; } @@ -90,11 +91,11 @@ class COMPONENT_EXPORT(X11) Event { // XProto event state. int type_id_ = 0; void (*deleter_)(void*) = nullptr; - void* event_ = nullptr; + raw_ptr<void, DanglingUntriaged> event_ = nullptr; // This member points to a field in |event_|, or may be nullptr if there's no // associated window for the event. It's owned by |event_|, not us. - Window* window_ = nullptr; + raw_ptr<Window, DanglingUntriaged> window_ = nullptr; }; } // namespace x11 diff --git a/chromium/ui/gfx/x/keyboard_state.cc b/chromium/ui/gfx/x/keyboard_state.cc index 147b6c0668e..7c7162ee1d1 100644 --- a/chromium/ui/gfx/x/keyboard_state.cc +++ b/chromium/ui/gfx/x/keyboard_state.cc @@ -5,6 +5,7 @@ #include "ui/gfx/x/keyboard_state.h" #include "base/i18n/case_conversion.h" +#include "base/memory/raw_ptr.h" #include "ui/gfx/x/connection.h" #include "ui/gfx/x/future.h" #include "ui/gfx/x/keysyms/keysyms.h" @@ -84,7 +85,7 @@ class CoreKeyboardState : public KeyboardState { &mode_switch_, &num_lock_); } - Connection* const connection_; + const raw_ptr<Connection> connection_; GetKeyboardMappingReply keyboard_mapping_; uint16_t lock_meaning_ = 0; uint8_t mode_switch_ = 0; @@ -124,7 +125,7 @@ class XkbKeyboardState : public KeyboardState { map_ = std::move(*response.reply); } - Connection* const connection_; + const raw_ptr<Connection> connection_; Xkb::GetMapReply map_; }; diff --git a/chromium/ui/gfx/x/property_cache.h b/chromium/ui/gfx/x/property_cache.h index 1004b07626a..90be1739cfa 100644 --- a/chromium/ui/gfx/x/property_cache.h +++ b/chromium/ui/gfx/x/property_cache.h @@ -9,6 +9,7 @@ #include "base/component_export.h" #include "base/containers/flat_map.h" +#include "base/memory/raw_ptr.h" #include "base/memory/ref_counted_memory.h" #include "base/memory/weak_ptr.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -72,7 +73,7 @@ class COMPONENT_EXPORT(X11) PropertyCache : public EventObserver { void OnGetPropertyResponse(PropertyValue* value, GetPropertyResponse response); - Connection* connection_; + raw_ptr<Connection> connection_; Window window_; XScopedEventSelector event_selector_; base::flat_map<Atom, PropertyValue> properties_; diff --git a/chromium/ui/gfx/x/property_cache_unittest.cc b/chromium/ui/gfx/x/property_cache_unittest.cc index ffc39d6d5e4..a464cde6b56 100644 --- a/chromium/ui/gfx/x/property_cache_unittest.cc +++ b/chromium/ui/gfx/x/property_cache_unittest.cc @@ -6,6 +6,7 @@ #include <memory> +#include "base/memory/raw_ptr.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/x/x11_atom_cache.h" #include "ui/gfx/x/xproto.h" @@ -39,7 +40,7 @@ class PropertyCacheTest : public testing::Test { connection_ = nullptr; } - Connection* connection_ = nullptr; + raw_ptr<Connection> connection_ = nullptr; Window window_ = Window::None; }; diff --git a/chromium/ui/gfx/x/scoped_ignore_errors.h b/chromium/ui/gfx/x/scoped_ignore_errors.h index baa48b5fd5a..96fc78a1f4e 100644 --- a/chromium/ui/gfx/x/scoped_ignore_errors.h +++ b/chromium/ui/gfx/x/scoped_ignore_errors.h @@ -6,6 +6,7 @@ #define UI_GFX_X_SCOPED_IGNORE_ERRORS_H_ #include "base/component_export.h" +#include "base/memory/raw_ptr.h" #include "ui/gfx/x/connection.h" namespace x11 { @@ -17,7 +18,7 @@ class COMPONENT_EXPORT(X11) ScopedIgnoreErrors { ~ScopedIgnoreErrors(); private: - Connection* const connection_; + const raw_ptr<Connection> connection_; Connection::ErrorHandler old_error_handler_; }; diff --git a/chromium/ui/gfx/x/window_cache.h b/chromium/ui/gfx/x/window_cache.h index 2d11968d962..fa6c0bd59fa 100644 --- a/chromium/ui/gfx/x/window_cache.h +++ b/chromium/ui/gfx/x/window_cache.h @@ -12,6 +12,7 @@ #include "base/component_export.h" #include "base/containers/circular_deque.h" #include "base/containers/flat_set.h" +#include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "ui/gfx/geometry/insets.h" @@ -36,7 +37,7 @@ class ScopedShapeEventSelector { ~ScopedShapeEventSelector(); private: - Connection* const connection_; + const raw_ptr<Connection> connection_; const Window window_; }; @@ -150,7 +151,7 @@ class COMPONENT_EXPORT(X11) WindowCache : public EventObserver { static WindowCache* instance_; - Connection* const connection_; + const raw_ptr<Connection> connection_; const Window root_; const Atom gtk_frame_extents_; std::unique_ptr<XScopedEventSelector> root_events_; diff --git a/chromium/ui/gfx/x/window_cache_unittest.cc b/chromium/ui/gfx/x/window_cache_unittest.cc index c88dbfd5c28..0fbd304e342 100644 --- a/chromium/ui/gfx/x/window_cache_unittest.cc +++ b/chromium/ui/gfx/x/window_cache_unittest.cc @@ -4,6 +4,7 @@ #include "ui/gfx/x/window_cache.h" +#include "base/memory/raw_ptr.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/geometry/insets.h" #include "ui/gfx/x/connection.h" @@ -61,7 +62,7 @@ class WindowCacheTest : public testing::Test { connection_ = nullptr; } - Connection* connection_; + raw_ptr<Connection> connection_; Window root_container_ = Window::None; Window root_ = Window::None; std::unique_ptr<WindowCache> cache_; diff --git a/chromium/ui/gfx/x/x11_atom_cache.h b/chromium/ui/gfx/x/x11_atom_cache.h index 3035f42691a..14bd3fa736e 100644 --- a/chromium/ui/gfx/x/x11_atom_cache.h +++ b/chromium/ui/gfx/x/x11_atom_cache.h @@ -9,6 +9,7 @@ #include <string> #include "base/component_export.h" +#include "base/memory/raw_ptr.h" #include "ui/gfx/x/xproto.h" namespace base { @@ -47,7 +48,7 @@ class COMPONENT_EXPORT(X11) X11AtomCache { // On failure, None is returned. Atom GetAtom(const std::string&) const; - Connection* connection_; + raw_ptr<Connection> connection_; // Using std::map, as it is possible for thousands of atoms to be registered. mutable std::map<std::string, Atom> cached_atoms_; diff --git a/chromium/ui/gfx/x/xlib_support.cc b/chromium/ui/gfx/x/xlib_support.cc index 281c318287b..aa362ed1193 100644 --- a/chromium/ui/gfx/x/xlib_support.cc +++ b/chromium/ui/gfx/x/xlib_support.cc @@ -32,7 +32,7 @@ XlibXcbLoader* GetXlibXcbLoader() { } // namespace -DISABLE_CFI_ICALL +DISABLE_CFI_DLSYM void InitXlib() { auto* xlib_loader = GetXlibLoader(); if (xlib_loader->loaded()) @@ -53,17 +53,17 @@ void InitXlib() { SetXlibErrorHandler(); } -DISABLE_CFI_ICALL +DISABLE_CFI_DLSYM void SetXlibErrorHandler() { GetXlibLoader()->XSetErrorHandler(XlibErrorHandler); } -DISABLE_CFI_ICALL +DISABLE_CFI_DLSYM void XlibFree(void* data) { GetXlibLoader()->XFree(data); } -DISABLE_CFI_ICALL +DISABLE_CFI_DLSYM XlibDisplay::XlibDisplay(const std::string& address) { InitXlib(); @@ -71,7 +71,7 @@ XlibDisplay::XlibDisplay(const std::string& address) { : address.c_str()); } -DISABLE_CFI_ICALL +DISABLE_CFI_DLSYM XlibDisplay::~XlibDisplay() { if (!display_) return; @@ -81,10 +81,12 @@ XlibDisplay::~XlibDisplay() { // events, they will just queue up and leak memory. This check makes sure // |display_| never had any pending events before it is closed. CHECK(!loader->XPending(display_)); - loader->XCloseDisplay(display_); + // ExtractAsDangling clears the underlying pointer and returns another raw_ptr + // instance that is allowed to dangle. + loader->XCloseDisplay(display_.ExtractAsDangling()); } -DISABLE_CFI_ICALL +DISABLE_CFI_DLSYM XlibDisplayWrapper::XlibDisplayWrapper(struct _XDisplay* display, XlibDisplayType type) : display_(display), type_(type) { @@ -94,7 +96,7 @@ XlibDisplayWrapper::XlibDisplayWrapper(struct _XDisplay* display, GetXlibLoader()->XSynchronize(display_, true); } -DISABLE_CFI_ICALL +DISABLE_CFI_DLSYM XlibDisplayWrapper::~XlibDisplayWrapper() { if (!display_) return; @@ -119,7 +121,7 @@ XlibDisplayWrapper& XlibDisplayWrapper::operator=(XlibDisplayWrapper&& other) { return *this; } -DISABLE_CFI_ICALL +DISABLE_CFI_DLSYM struct xcb_connection_t* XlibDisplayWrapper::GetXcbConnection() { return GetXlibXcbLoader()->XGetXCBConnection(display_); } diff --git a/chromium/ui/gfx/x/xlib_support.h b/chromium/ui/gfx/x/xlib_support.h index 26accef2418..91edc322feb 100644 --- a/chromium/ui/gfx/x/xlib_support.h +++ b/chromium/ui/gfx/x/xlib_support.h @@ -9,6 +9,7 @@ #include <string> #include "base/component_export.h" +#include "base/memory/raw_ptr.h" struct _XDisplay; struct xcb_connection_t; @@ -47,7 +48,7 @@ class COMPONENT_EXPORT(X11) XlibDisplay { explicit XlibDisplay(const std::string& address); - struct _XDisplay* display_ = nullptr; + raw_ptr<struct _XDisplay> display_ = nullptr; }; // A temporary wrapper around an unowned Xlib display that adds behavior @@ -71,7 +72,7 @@ class COMPONENT_EXPORT(X11) XlibDisplayWrapper { friend class Connection; - struct _XDisplay* display_; + raw_ptr<struct _XDisplay> display_; XlibDisplayType type_; }; diff --git a/chromium/ui/gfx/x/xproto_internal.cc b/chromium/ui/gfx/x/xproto_internal.cc index e0ffe7ef608..a73b9a7bc49 100644 --- a/chromium/ui/gfx/x/xproto_internal.cc +++ b/chromium/ui/gfx/x/xproto_internal.cc @@ -14,7 +14,7 @@ MallocedRefCountedMemory::MallocedRefCountedMemory(void* data) : data_(reinterpret_cast<uint8_t*>(data)) {} const uint8_t* MallocedRefCountedMemory::front() const { - return data_; + return data_.get(); } size_t MallocedRefCountedMemory::size() const { @@ -23,9 +23,7 @@ size_t MallocedRefCountedMemory::size() const { return 0; } -MallocedRefCountedMemory::~MallocedRefCountedMemory() { - free(data_); -} +MallocedRefCountedMemory::~MallocedRefCountedMemory() = default; OffsetRefCountedMemory::OffsetRefCountedMemory( scoped_refptr<base::RefCountedMemory> memory, diff --git a/chromium/ui/gfx/x/xproto_internal.h b/chromium/ui/gfx/x/xproto_internal.h index 6bf0f5142c4..e69c9f42502 100644 --- a/chromium/ui/gfx/x/xproto_internal.h +++ b/chromium/ui/gfx/x/xproto_internal.h @@ -5,6 +5,8 @@ #ifndef UI_GFX_X_XPROTO_INTERNAL_H_ #define UI_GFX_X_XPROTO_INTERNAL_H_ +#include "base/memory/raw_ptr.h" + #ifndef IS_X11_IMPL #error "This file should only be included by //ui/gfx/x:xprotos" #endif @@ -53,9 +55,16 @@ class COMPONENT_EXPORT(X11) MallocedRefCountedMemory size_t size() const override; private: + struct deleter { + void operator()(uint8_t* data) { + if (data) { + free(data); + } + } + }; ~MallocedRefCountedMemory() override; - uint8_t* const data_; + std::unique_ptr<uint8_t, deleter> data_; }; // Wraps another RefCountedMemory, giving a view into it. Similar to diff --git a/chromium/ui/gfx/x/xproto_types.h b/chromium/ui/gfx/x/xproto_types.h index e670fcec166..488e98d44f1 100644 --- a/chromium/ui/gfx/x/xproto_types.h +++ b/chromium/ui/gfx/x/xproto_types.h @@ -12,6 +12,7 @@ #include "base/callback.h" #include "base/component_export.h" #include "base/memory/free_deleter.h" +#include "base/memory/raw_ptr.h" #include "base/memory/ref_counted_memory.h" #include "base/memory/scoped_refptr.h" @@ -49,7 +50,7 @@ struct COMPONENT_EXPORT(X11) ReadBuffer { scoped_refptr<base::RefCountedMemory> data; size_t offset = 0; - const int* fds = nullptr; + raw_ptr<const int> fds = nullptr; }; // Wraps data to write to the connection. |