@@ -49,9 +49,6 @@ static FontGlyphPair::Set CollectUniqueFontGlyphPairs(
4949 while (const TextFrame* frame = frame_iterator ()) {
5050 for (const TextRun& run : frame->GetRuns ()) {
5151 const Font& font = run.GetFont ();
52- // TODO(dnfield): If we're doing SDF here, we should be using a consistent
53- // point size.
54- // https://github.com/flutter/flutter/issues/112016
5552 for (const TextRun::GlyphPosition& glyph_position :
5653 run.GetGlyphPositions ()) {
5754 set.insert ({font, glyph_position.glyph });
@@ -171,121 +168,6 @@ ISize OptimumAtlasSizeForFontGlyphPairs(
171168}
172169} // namespace
173170
174- // / Compute signed-distance field for an 8-bpp grayscale image (values greater
175- // / than 127 are considered "on") For details of this algorithm, see "The 'dead
176- // / reckoning' signed distance transform" [Grevera 2004]
177- static void ConvertBitmapToSignedDistanceField (uint8_t * pixels,
178- uint16_t width,
179- uint16_t height) {
180- if (!pixels || width == 0 || height == 0 ) {
181- return ;
182- }
183-
184- using ShortPoint = TPoint<uint16_t >;
185-
186- // distance to nearest boundary point map
187- std::vector<Scalar> distance_map (width * height);
188- // nearest boundary point map
189- std::vector<ShortPoint> boundary_point_map (width * height);
190-
191- // Some helpers for manipulating the above arrays
192- #define image (_x, _y ) (pixels[(_y)*width + (_x)] > 0x7f )
193- #define distance (_x, _y ) distance_map[(_y)*width + (_x)]
194- #define nearestpt (_x, _y ) boundary_point_map[(_y)*width + (_x)]
195-
196- const Scalar maxDist = hypot (width, height);
197- const Scalar distUnit = 1 ;
198- const Scalar distDiag = sqrt (2 );
199-
200- // Initialization phase: set all distances to "infinity"; zero out nearest
201- // boundary point map
202- for (uint16_t y = 0 ; y < height; ++y) {
203- for (uint16_t x = 0 ; x < width; ++x) {
204- distance (x, y) = maxDist;
205- nearestpt (x, y) = ShortPoint{0 , 0 };
206- }
207- }
208-
209- // Immediate interior/exterior phase: mark all points along the boundary as
210- // such
211- for (uint16_t y = 1 ; y < height - 1 ; ++y) {
212- for (uint16_t x = 1 ; x < width - 1 ; ++x) {
213- bool inside = image (x, y);
214- if (image (x - 1 , y) != inside || image (x + 1 , y) != inside ||
215- image (x, y - 1 ) != inside || image (x, y + 1 ) != inside) {
216- distance (x, y) = 0 ;
217- nearestpt (x, y) = ShortPoint{x, y};
218- }
219- }
220- }
221-
222- // Forward dead-reckoning pass
223- for (uint16_t y = 1 ; y < height - 2 ; ++y) {
224- for (uint16_t x = 1 ; x < width - 2 ; ++x) {
225- if (distance_map[(y - 1 ) * width + (x - 1 )] + distDiag < distance (x, y)) {
226- nearestpt (x, y) = nearestpt (x - 1 , y - 1 );
227- distance (x, y) = hypot (x - nearestpt (x, y).x , y - nearestpt (x, y).y );
228- }
229- if (distance (x, y - 1 ) + distUnit < distance (x, y)) {
230- nearestpt (x, y) = nearestpt (x, y - 1 );
231- distance (x, y) = hypot (x - nearestpt (x, y).x , y - nearestpt (x, y).y );
232- }
233- if (distance (x + 1 , y - 1 ) + distDiag < distance (x, y)) {
234- nearestpt (x, y) = nearestpt (x + 1 , y - 1 );
235- distance (x, y) = hypot (x - nearestpt (x, y).x , y - nearestpt (x, y).y );
236- }
237- if (distance (x - 1 , y) + distUnit < distance (x, y)) {
238- nearestpt (x, y) = nearestpt (x - 1 , y);
239- distance (x, y) = hypot (x - nearestpt (x, y).x , y - nearestpt (x, y).y );
240- }
241- }
242- }
243-
244- // Backward dead-reckoning pass
245- for (uint16_t y = height - 2 ; y >= 1 ; --y) {
246- for (uint16_t x = width - 2 ; x >= 1 ; --x) {
247- if (distance (x + 1 , y) + distUnit < distance (x, y)) {
248- nearestpt (x, y) = nearestpt (x + 1 , y);
249- distance (x, y) = hypot (x - nearestpt (x, y).x , y - nearestpt (x, y).y );
250- }
251- if (distance (x - 1 , y + 1 ) + distDiag < distance (x, y)) {
252- nearestpt (x, y) = nearestpt (x - 1 , y + 1 );
253- distance (x, y) = hypot (x - nearestpt (x, y).x , y - nearestpt (x, y).y );
254- }
255- if (distance (x, y + 1 ) + distUnit < distance (x, y)) {
256- nearestpt (x, y) = nearestpt (x, y + 1 );
257- distance (x, y) = hypot (x - nearestpt (x, y).x , y - nearestpt (x, y).y );
258- }
259- if (distance (x + 1 , y + 1 ) + distDiag < distance (x, y)) {
260- nearestpt (x, y) = nearestpt (x + 1 , y + 1 );
261- distance (x, y) = hypot (x - nearestpt (x, y).x , y - nearestpt (x, y).y );
262- }
263- }
264- }
265-
266- // Interior distance negation pass; distances outside the figure are
267- // considered negative
268- // Also does final quantization.
269- for (uint16_t y = 0 ; y < height; ++y) {
270- for (uint16_t x = 0 ; x < width; ++x) {
271- if (!image (x, y)) {
272- distance (x, y) = -distance (x, y);
273- }
274-
275- float norm_factor = 13.5 ;
276- float dist = distance (x, y);
277- float clamped_dist = fmax (-norm_factor, fmin (dist, norm_factor));
278- float scaled_dist = clamped_dist / norm_factor;
279- uint8_t quantized_value = ((scaled_dist + 1 ) / 2 ) * UINT8_MAX;
280- pixels[y * width + x] = quantized_value;
281- }
282- }
283-
284- #undef image
285- #undef distance
286- #undef nearestpt
287- }
288-
289171static void DrawGlyph (SkCanvas* canvas,
290172 const FontGlyphPair& font_glyph,
291173 const Rect& location,
@@ -353,7 +235,6 @@ static std::shared_ptr<SkBitmap> CreateAtlasBitmap(const GlyphAtlas& atlas,
353235 SkImageInfo image_info;
354236
355237 switch (atlas.GetType ()) {
356- case GlyphAtlas::Type::kSignedDistanceField :
357238 case GlyphAtlas::Type::kAlphaBitmap :
358239 image_info = SkImageInfo::MakeA8 (atlas_size.width , atlas_size.height );
359240 break ;
@@ -563,10 +444,6 @@ std::shared_ptr<GlyphAtlas> TextRenderContextSkia::CreateGlyphAtlas(
563444 // ---------------------------------------------------------------------------
564445 PixelFormat format;
565446 switch (type) {
566- case GlyphAtlas::Type::kSignedDistanceField :
567- ConvertBitmapToSignedDistanceField (
568- reinterpret_cast <uint8_t *>(bitmap->getPixels ()), atlas_size.width ,
569- atlas_size.height );
570447 case GlyphAtlas::Type::kAlphaBitmap :
571448 format = PixelFormat::kA8UNormInt ;
572449 break ;
0 commit comments