1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_DARK_MODE_FILTER_H_
6 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_DARK_MODE_FILTER_H_
7 
8 #include <memory>
9 
10 #include "cc/paint/paint_flags.h"
11 #include "third_party/blink/renderer/platform/geometry/float_rect.h"
12 #include "third_party/blink/renderer/platform/graphics/color.h"
13 #include "third_party/blink/renderer/platform/graphics/dark_mode_settings.h"
14 #include "third_party/blink/renderer/platform/graphics/image.h"
15 #include "third_party/blink/renderer/platform/platform_export.h"
16 #include "third_party/skia/include/core/SkRefCnt.h"
17 
18 class SkColorFilter;
19 
20 namespace blink {
21 
22 class DarkModeColorClassifier;
23 class DarkModeColorFilter;
24 class ScopedDarkModeElementRoleOverride;
25 
26 class PLATFORM_EXPORT DarkModeFilter {
27  public:
28   // Dark mode is disabled by default. Enable it by calling UpdateSettings()
29   // with a mode other than DarkMode::kOff.
30   DarkModeFilter();
31   ~DarkModeFilter();
32 
33   bool IsDarkModeActive() const;
34 
settings()35   const DarkModeSettings& settings() const { return settings_; }
36   void UpdateSettings(const DarkModeSettings& new_settings);
37 
38   // TODO(gilmanmh): Add a role for shadows. In general, we don't want to
39   // invert shadows, but we may need to do some other kind of processing for
40   // them.
41   enum class ElementRole { kText, kListSymbol, kBackground, kSVG };
42   Color InvertColorIfNeeded(const Color& color, ElementRole element_role);
43   base::Optional<cc::PaintFlags> ApplyToFlagsIfNeeded(
44       const cc::PaintFlags& flags,
45       ElementRole element_role);
46 
47   // |image| and |flags| must not be null.
48   void ApplyToImageFlagsIfNeeded(const FloatRect& src_rect,
49                                  const FloatRect& dest_rect,
50                                  Image* image,
51                                  cc::PaintFlags* flags);
52 
GetImageFilterForTesting()53   SkColorFilter* GetImageFilterForTesting() { return image_filter_.get(); }
54 
55  private:
56   friend class ScopedDarkModeElementRoleOverride;
57 
58   DarkModeSettings settings_;
59 
60   bool ShouldApplyToColor(const Color& color, ElementRole role);
61 
62   std::unique_ptr<DarkModeColorClassifier> text_classifier_;
63   std::unique_ptr<DarkModeColorClassifier> background_classifier_;
64   std::unique_ptr<DarkModeColorFilter> color_filter_;
65   sk_sp<SkColorFilter> image_filter_;
66   base::Optional<ElementRole> role_override_;
67 };
68 
69 // Temporarily override the element role for the scope of this object's
70 // lifetime - for example when drawing symbols that play the role of text.
71 class PLATFORM_EXPORT ScopedDarkModeElementRoleOverride {
72  public:
73   ScopedDarkModeElementRoleOverride(GraphicsContext* graphics_context,
74                                     DarkModeFilter::ElementRole role);
75   ~ScopedDarkModeElementRoleOverride();
76 
77  private:
78   GraphicsContext* graphics_context_;
79   base::Optional<DarkModeFilter::ElementRole> previous_role_override_;
80 };
81 
82 }  // namespace blink
83 
84 #endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_DARK_MODE_FILTER_H_
85