Flutter Engine
The Flutter Engine
DistanceFieldAdjustTable.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
9
15
16#include <cstddef>
17#include <cstdint>
18
19using namespace skia_private;
20
21namespace sktext::gpu {
22
23SkDEBUGCODE(static const int kExpectedDistanceAdjustTableSize = 8;)
24
25SkScalar* build_distance_adjust_table(SkScalar deviceGamma) {
26 // This is used for an approximation of the mask gamma hack, used by raster and bitmap
27 // text. The mask gamma hack is based off of guessing what the blend color is going to
28 // be, and adjusting the mask so that when run through the linear blend will
29 // produce the value closest to the desired result. However, in practice this means
30 // that the 'adjusted' mask is just increasing or decreasing the coverage of
31 // the mask depending on what it is thought it will blit against. For black (on
32 // assumed white) this means that coverages are decreased (on a curve). For white (on
33 // assumed black) this means that coverages are increased (on a a curve). At
34 // middle (perceptual) gray (which could be blit against anything) the coverages
35 // remain the same.
36 //
37 // The idea here is that instead of determining the initial (real) coverage and
38 // then adjusting that coverage, we determine an adjusted coverage directly by
39 // essentially manipulating the geometry (in this case, the distance to the glyph
40 // edge). So for black (on assumed white) this thins a bit; for white (on
41 // assumed black) this fake bolds the geometry a bit.
42 //
43 // The distance adjustment is calculated by determining the actual coverage value which
44 // when fed into in the mask gamma table gives us an 'adjusted coverage' value of 0.5. This
45 // actual coverage value (assuming it's between 0 and 1) corresponds to a distance from the
46 // actual edge. So by subtracting this distance adjustment and computing without the
47 // the coverage adjustment we should get 0.5 coverage at the same point.
48 //
49 // This has several implications:
50 // For non-gray lcd smoothed text, each subpixel essentially is using a
51 // slightly different geometry.
52 //
53 // For black (on assumed white) this may not cover some pixels which were
54 // previously covered; however those pixels would have been only slightly
55 // covered and that slight coverage would have been decreased anyway. Also, some pixels
56 // which were previously fully covered may no longer be fully covered.
57 //
58 // For white (on assumed black) this may cover some pixels which weren't
59 // previously covered at all.
60
61 int width, height;
62 size_t size;
63 SkScalar contrast = SK_GAMMA_CONTRAST;
64
65 size = SkScalerContext::GetGammaLUTSize(contrast, deviceGamma,
66 &width, &height);
67
68 SkASSERT(kExpectedDistanceAdjustTableSize == height);
70
72 if (!SkScalerContext::GetGammaLUTData(contrast, deviceGamma, data.get())) {
73 // if no valid data is available simply do no adjustment
74 for (int row = 0; row < height; ++row) {
75 table[row] = 0;
76 }
77 return table;
78 }
79
80 // find the inverse points where we cross 0.5
81 // binsearch might be better, but we only need to do this once on creation
82 for (int row = 0; row < height; ++row) {
83 uint8_t* rowPtr = data.get() + row*width;
84 for (int col = 0; col < width - 1; ++col) {
85 if (rowPtr[col] <= 127 && rowPtr[col + 1] >= 128) {
86 // compute point where a mask value will give us a result of 0.5
87 float interp = (127.5f - rowPtr[col]) / (rowPtr[col + 1] - rowPtr[col]);
88 float borderAlpha = (col + interp) / 255.f;
89
90 // compute t value for that alpha
91 // this is an approximate inverse for smoothstep()
92 float t = borderAlpha*(borderAlpha*(4.0f*borderAlpha - 6.0f) + 5.0f) / 3.0f;
93
94 // compute distance which gives us that t value
95 const float kDistanceFieldAAFactor = 0.65f; // should match SK_DistanceFieldAAFactor
96 float d = 2.0f*kDistanceFieldAAFactor*t - kDistanceFieldAAFactor;
97
98 table[row] = d;
99 break;
100 }
101 }
102 }
103
104 return table;
105}
106
109 return dfat.get();
110}
111
112DistanceFieldAdjustTable::DistanceFieldAdjustTable() {
113 fTable = build_distance_adjust_table(SK_GAMMA_EXPONENT);
114 fGammaCorrectTable = build_distance_adjust_table(SK_Scalar1);
115}
116
117} // namespace sktext::gpu
#define SkASSERT(cond)
Definition: SkAssert.h:116
static float2 interp(const float2 &v0, const float2 &v1, const float2 &t)
Definition: SkGeometry.cpp:169
#define SK_Scalar1
Definition: SkScalar.h:18
#define SK_GAMMA_CONTRAST
Definition: SkTypes.h:94
#define SK_GAMMA_EXPONENT
Definition: SkTypes.h:86
SI F table(const skcms_Curve *curve, F v)
const T * get() const
static size_t GetGammaLUTSize(SkScalar contrast, SkScalar deviceGamma, int *width, int *height)
static bool GetGammaLUTData(SkScalar contrast, SkScalar deviceGamma, uint8_t *data)
static const DistanceFieldAdjustTable * Get()
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition: main.cc:19
float SkScalar
Definition: extension.cpp:12
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
SkDEBUGCODE(static const int kExpectedDistanceAdjustTableSize=8;) SkScalar *build_distance_adjust_table(SkScalar deviceGamma)
int32_t height
int32_t width
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63