---
# System prepended metadata

title: Subpixel Calculation
tags: [Chromium-Graphics, elkurin-daily-note]

---

# Subpixel Calculation

Subpixel offset is used to adjust float bounds.  
Let's see the calulcation logic and who refers to the subpixel.

## How subpixel offset is calculated
[Layer::GetSubpixelOffset](https://source.chromium.org/chromium/chromium/src/+/main:ui/compositor/layer.cc;l=525;drc=977dc02c431b4979e34c7792bc3d646f649dacb4) gets subpixel offset with the scale factor, target origin and target transform.

Device scale factor is notifired by [OnDeviceScaleFactorChanged](https://source.chromium.org/chromium/chromium/src/+/main:ui/compositor/layer.cc;l=1328;drc=977dc02c431b4979e34c7792bc3d646f649dacb4) and tied to ui::Layer.  
Target origin comes from [`bounds_`](https://source.chromium.org/chromium/chromium/src/+/main:ui/compositor/layer.h;l=738;drc=977dc02c431b4979e34c7792bc3d646f649dacb4) set to the layer.  
Target transform comes from cc::Layer via [`transform()`](https://source.chromium.org/chromium/chromium/src/+/main:cc/layers/layer.h;l=420;drc=977dc02c431b4979e34c7792bc3d646f649dacb4).  

Given 3 parameters, [SubpixelPositionOffsetCache](https://source.chromium.org/chromium/chromium/src/+/main:ui/compositor/layer.cc;l=122;drc=3e8ca029a67e50cd5a73ae784da40b05c63df153) is responsible for calculating the subpixel offset.

If it is explicitly set to `has_explicit_subpixel_offset_`, it immediately returns this offset without adjust or anything. This is set, for example, from [ShellSurfaceBase::UpdateHostWindowOrigin](https://source.chromium.org/chromium/chromium/src/+/main:components/exo/shell_surface_base.cc;l=1927-1928;drc=977dc02c431b4979e34c7792bc3d646f649dacb4).  
If not, the calculation begins.  

First, it calculate the effective offset from the parent. It's position + transform.
```cpp=
gfx::PointF offset_from_parent(origin);
if (!tm.IsIdentity() && tm.Preserves2dAxisAlignment())
  offset_from_parent += tm.To2dTranslation();
```
`tm` is a transform came from cc layer. Note that this is not ui layer, but cc layer.

If the effective offset and the scale is the same as cached values, we don't need to recompute, so immediately return the cached `offset_` value here.  
If not, it proceeds with computing subpixel offset from the effective offset against parent.

Scale `offset_from_parent` by the device scale factor, round it, calculate the ignored value (= diff between the original value and the rounded value), and inverse it by the device scale factor.
```cpp=
gfx::PointF scaled_offset_from_parent(offset_from_parent);
scaled_offset_from_parent.Scale(device_scale_factor, device_scale_factor);
gfx::PointF snapped_offset_from_parent(
    gfx::ToRoundedPoint(scaled_offset_from_parent));

gfx::Vector2dF offset =
    snapped_offset_from_parent - scaled_offset_from_parent;
offset.InvScale(device_scale_factor);
```

Then cache these values to `offset_`, `device_scale_factor_` and `offset_from_parent_` to avoid recomputation.  
`position` passed to [cc::Layer::SetPosition](https://source.chromium.org/chromium/chromium/src/+/main:cc/layers/layer.cc;l=896;drc=977dc02c431b4979e34c7792bc3d646f649dacb4) is used on cc layer bounds, so the subpixel offset is ignored in ui::Layer while it is counted in cc::Layer.

## Who use subpixel offset
On [ui::Layer::RecomputePosition](https://source.chromium.org/chromium/chromium/src/+/main:ui/compositor/layer.cc;l=1784;drc=977dc02c431b4979e34c7792bc3d646f649dacb4), the position is set to cc layer.  
Here, we don't set `bounds_` but instead `bounds_.origin() + GetSubpixelOffset`.
```cpp=
void Layer::RecomputePosition() {
  cc_layer_->SetPosition(gfx::PointF(bounds_.origin()) + GetSubpixelOffset());
}
```

## Do we need explicit subpixel in HostWindow
In the current code, we set subpixel offset explicitly on host window.
```cpp=
const gfx::Vector2dF surface_origin_subpixel_offset =
    ScaleVector2d(ToRoundedVector2d(ScaleVector2d(origin.OffsetFromOrigin(),
                                                  GetScaleFactor())),
                  1.f / GetScaleFactor()) -
    origin.OffsetFromOrigin();

const gfx::Vector2dF root_surface_origin_dp = ScaleVector2d(
    root_surface_origin_pixel().OffsetFromOrigin(), 1.f / GetScaleFactor());
origin -= ToFlooredVector2d(root_surface_origin_dp);

const gfx::Vector2dF root_surface_origin_subpixel_offset =
    ToFlooredVector2d(root_surface_origin_dp) - root_surface_origin_dp;

host_window()->layer()->SetSubpixelPositionOffset(
    surface_origin_subpixel_offset + root_surface_origin_subpixel_offset);
```

`surface_origin_subpixel_offset` is a diff between the original and rounded value. This looks similar to what GetSubpixelOffset does.  
However, we need this logic to keep the window stays at the same point.  

This is probably because `root_surface_origin_dp` is floored instead of ceild when it's subtracted from `origin`.  
TODO(elkurin): Verify the behavior with `ToCeiledVector2d`.