[webkit-changes] [WebKit/WebKit] cc1298: REGRESSION (iOS 16): Incorrect text color used wit...

Aditya Keerthi noreply at github.com
Tue Jan 10 18:26:05 PST 2023


  Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: cc12988dce62c9150ad502327d8885654c615717
      https://github.com/WebKit/WebKit/commit/cc12988dce62c9150ad502327d8885654c615717
  Author: Aditya Keerthi <akeerthi at apple.com>
  Date:   2023-01-10 (Tue, 10 Jan 2023)

  Changed paths:
    A LayoutTests/fast/css/color-matching-translucent-border-color-expected.html
    A LayoutTests/fast/css/color-matching-translucent-border-color.html
    M Source/WebCore/platform/graphics/BifurcatedGraphicsContext.cpp
    M Source/WebCore/platform/graphics/GraphicsContextState.cpp
    M Source/WebCore/platform/graphics/GraphicsContextState.h
    M Source/WebCore/platform/graphics/displaylists/DisplayListRecorder.cpp

  Log Message:
  -----------
  REGRESSION (iOS 16): Incorrect text color used with matching translucent border color
https://bugs.webkit.org/show_bug.cgi?id=247020
rdar://101560064

Reviewed by Wenson Hsieh and Said Abou-Hallawa.

Consider the following test case, which should have some green text above red text,
but ends up having only green text:

```
<div style="color: green;">Green</div>
<span style="color: red; border-style: solid; border-top-color: rgb(255, 0, 0, 0.1); border-right-color: rgb(255, 0, 0, 0.1); border-left-color: rgb(255, 0, 0, 0.1);">Red</span>
```

Which issues the following (reduced) set of `GraphicsContext` commands:

```
context.setFillColor(Color::green);
context.drawText("Green");
context.beginTransparencyLayer(0.1);
context.setFillColor(Color::red);
// Draw borders
context.endTransparencyLayer();
context.setFillColor(Color::red);
context.drawText("Red");
```

When the call to set a green fill color is made, the `GraphicsContext` state
member is updated, as there has been a change in the fill color. Then, the
`DisplayList::Recorder` is informed of the state change via `didUpdateState` and
the appropriate `ChangeFlags`. The recorder has its own `GraphicsContextState`,
which is updated with the latest changes. This ensures the green text is painted
correctly.

The use of a translucent border results in the use of a transparency layer.
`beginTransparencyLayer` and `endTransparencyLayer` push and pop to the recorder's
state stack respectively. However, the parent class, `GraphicsContext`, maintains
its own state and state stack.

Currently, when beginning a transparency layer, the `GraphicsContext` state stack is
not updated. Consequently, the second call to set a red fill color (for the text
color) is made to the same `GraphicsContextState` as the first call, which
occurred while there was a transparency layer. Since the colors are equal, the recorder
is not informed that a change has been made. However, at this time, the recorder's
own state has a green fill, following the "pop" from ending the transparency layer.
This green fill color is what is recorded when painting the second line of text,
resulting in an incorrect text color.

To fix, update the `GraphicsContext` state stack is alongside the `DisplayList::Recorder`
state stack when beginning/ending a transparency layer. This ensures that the
`GraphicsContext` state matches the recorder's state after ending the transparency
layer, and any state updates are not dropped on their way to the recorder.

* LayoutTests/fast/css/color-matching-translucent-border-color-expected.html: Added.
* LayoutTests/fast/css/color-matching-translucent-border-color.html: Added.

Original test case provided by Kevin Muncie, with slight modifications to
support writing a reference test that fails without this change.

* Source/WebCore/platform/graphics/BifurcatedGraphicsContext.cpp:

Make an equivalent change in `BifurcatedGraphicsContext`.

(WebCore::BifurcatedGraphicsContext::beginTransparencyLayer):
(WebCore::BifurcatedGraphicsContext::endTransparencyLayer):
* Source/WebCore/platform/graphics/GraphicsContextState.cpp:
(WebCore::GraphicsContextState::didEndTransparencyLayer): Deleted.
* Source/WebCore/platform/graphics/GraphicsContextState.h:
* Source/WebCore/platform/graphics/displaylists/DisplayListRecorder.cpp:
(WebCore::DisplayList::Recorder::beginTransparencyLayer):

Push to the `GraphicsContext` state stack by calling parent class method. The
`DisplayList::Recorder::save` is not called to avoid recording an unnecessary
display list item.

(WebCore::DisplayList::Recorder::endTransparencyLayer):

Remove the call to `didEndTransparencyLayer`, as `GraphicsContext` `m_state`
is now correctly restored to the state prior to beginning the transparency
layer.

Canonical link: https://commits.webkit.org/258762@main




More information about the webkit-changes mailing list