Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(47)

Side by Side Diff: src/gpu/GrTextStrike.cpp

Issue 41213003: Hook in rough distance field support for fonts (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Port over fix for alpha-blended paint color (may not be needed). Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright 2010 Google Inc. 2 * Copyright 2010 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "GrAtlas.h" 8 #include "GrAtlas.h"
9 #include "GrGpu.h" 9 #include "GrGpu.h"
10 #include "GrRectanizer.h" 10 #include "GrRectanizer.h"
11 #include "GrTextStrike.h" 11 #include "GrTextStrike.h"
12 #include "GrTextStrike_impl.h" 12 #include "GrTextStrike_impl.h"
13 #include "SkString.h" 13 #include "SkString.h"
14 14
15 #include "edtaa3.h"
16
15 SK_DEFINE_INST_COUNT(GrFontScaler) 17 SK_DEFINE_INST_COUNT(GrFontScaler)
16 SK_DEFINE_INST_COUNT(GrKey) 18 SK_DEFINE_INST_COUNT(GrKey)
17 19
18 /////////////////////////////////////////////////////////////////////////////// 20 ///////////////////////////////////////////////////////////////////////////////
19 21
20 #define FONT_CACHE_STATS 0 22 #define FONT_CACHE_STATS 0
21 #if FONT_CACHE_STATS 23 #if FONT_CACHE_STATS
22 static int g_PurgeCount = 0; 24 static int g_PurgeCount = 0;
23 #endif 25 #endif
24 26
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
186 ++gDumpCount; 188 ++gDumpCount;
187 } 189 }
188 #endif 190 #endif
189 191
190 /////////////////////////////////////////////////////////////////////////////// 192 ///////////////////////////////////////////////////////////////////////////////
191 193
192 #ifdef SK_DEBUG 194 #ifdef SK_DEBUG
193 static int gCounter; 195 static int gCounter;
194 #endif 196 #endif
195 197
198 #define DISTANCE_FIELD_PAD 4
199 #define DISTANCE_FIELD_RANGE (4.0)
200
196 /* 201 /*
197 The text strike is specific to a given font/style/matrix setup, which is 202 The text strike is specific to a given font/style/matrix setup, which is
198 represented by the GrHostFontScaler object we are given in getGlyph(). 203 represented by the GrHostFontScaler object we are given in getGlyph().
199 204
200 We map a 32bit glyphID to a GrGlyph record, which in turn points to a 205 We map a 32bit glyphID to a GrGlyph record, which in turn points to a
201 atlas and a position within that texture. 206 atlas and a position within that texture.
202 */ 207 */
203 208
204 GrTextStrike::GrTextStrike(GrFontCache* cache, const GrKey* key, 209 GrTextStrike::GrTextStrike(GrFontCache* cache, const GrKey* key,
205 GrMaskFormat format, 210 GrMaskFormat format,
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 } 244 }
240 245
241 GrGlyph* GrTextStrike::generateGlyph(GrGlyph::PackedID packed, 246 GrGlyph* GrTextStrike::generateGlyph(GrGlyph::PackedID packed,
242 GrFontScaler* scaler) { 247 GrFontScaler* scaler) {
243 SkIRect bounds; 248 SkIRect bounds;
244 if (!scaler->getPackedGlyphBounds(packed, &bounds)) { 249 if (!scaler->getPackedGlyphBounds(packed, &bounds)) {
245 return NULL; 250 return NULL;
246 } 251 }
247 252
248 GrGlyph* glyph = fPool.alloc(); 253 GrGlyph* glyph = fPool.alloc();
254 // expand bounds to hold full distance field data
255 if (fUseDistanceField) {
256 bounds.fLeft -= DISTANCE_FIELD_PAD;
257 bounds.fRight += DISTANCE_FIELD_PAD;
258 bounds.fTop -= DISTANCE_FIELD_PAD;
259 bounds.fBottom += DISTANCE_FIELD_PAD;
260 }
249 glyph->init(packed, bounds); 261 glyph->init(packed, bounds);
250 fCache.insert(packed, glyph); 262 fCache.insert(packed, glyph);
251 return glyph; 263 return glyph;
252 } 264 }
253 265
254 bool GrTextStrike::removeUnusedPlots() { 266 bool GrTextStrike::removeUnusedPlots() {
255 fCache.getArray().visitAll(invalidate_glyph); 267 fCache.getArray().visitAll(invalidate_glyph);
256 return fAtlasMgr->removeUnusedPlots(&fAtlas); 268 return fAtlasMgr->removeUnusedPlots(&fAtlas);
257 } 269 }
258 270
271
259 bool GrTextStrike::getGlyphAtlas(GrGlyph* glyph, GrFontScaler* scaler) { 272 bool GrTextStrike::getGlyphAtlas(GrGlyph* glyph, GrFontScaler* scaler) {
260 #if 0 // testing hack to force us to flush our cache often 273 #if 0 // testing hack to force us to flush our cache often
261 static int gCounter; 274 static int gCounter;
262 if ((++gCounter % 10) == 0) return false; 275 if ((++gCounter % 10) == 0) return false;
263 #endif 276 #endif
264 277
265 SkASSERT(glyph); 278 SkASSERT(glyph);
266 SkASSERT(scaler); 279 SkASSERT(scaler);
267 SkASSERT(fCache.contains(glyph)); 280 SkASSERT(fCache.contains(glyph));
268 SkASSERT(NULL == glyph->fPlot); 281 SkASSERT(NULL == glyph->fPlot);
269 282
270 SkAutoRef ar(scaler); 283 SkAutoRef ar(scaler);
271 284
272 int bytesPerPixel = GrMaskFormatBytesPerPixel(fMaskFormat); 285 int bytesPerPixel = GrMaskFormatBytesPerPixel(fMaskFormat);
273 size_t size = glyph->fBounds.area() * bytesPerPixel; 286
274 SkAutoSMalloc<1024> storage(size); 287 GrPlot* plot;
275 if (!scaler->getPackedGlyphImage(glyph->fPackedID, glyph->width(), 288 if (fUseDistanceField) {
276 glyph->height(), 289 SkASSERT(1 == bytesPerPixel);
277 glyph->width() * bytesPerPixel, 290
278 storage.get())) { 291 // we've already expanded the glyph dimensions to match the final size
279 return false; 292 // but must shrink back down to get the packed glyph data
293 int dfwidth = glyph->width();
294 int dfheight = glyph->height();
295 int width = dfwidth - 2*DISTANCE_FIELD_PAD;
296 int height = dfheight - 2*DISTANCE_FIELD_PAD;
297 size_t stride = width*bytesPerPixel;
298
299 size_t size = width * height * bytesPerPixel;
300 SkAutoSMalloc<1024> storage(size);
301 if (!scaler->getPackedGlyphImage(glyph->fPackedID, width, height, stride , storage.get())) {
302 return false;
303 }
304
305 // alloc storage for distance field glyph
306 size_t dfsize = dfwidth * dfheight * bytesPerPixel;
307 SkAutoSMalloc<1024> dfstorage(dfsize);
308
309 // copy glyph into distance field storage
310 memset(dfstorage.get(), 0, dfsize);
311
312 unsigned char* ptr = (unsigned char*) storage.get();
313 unsigned char* dfptr = (unsigned char*) dfstorage.get();
314 size_t dfstride = dfwidth*bytesPerPixel;
315 dfptr += DISTANCE_FIELD_PAD*dfstride;
316 dfptr += DISTANCE_FIELD_PAD*bytesPerPixel;
317
318 for (int i = 0; i < height; ++i) {
319 memcpy(dfptr, ptr, stride);
320
321 dfptr += dfstride;
322 ptr += stride;
323 }
324
325 // generate distance field data
326 short* distx = new short[dfwidth*dfheight];
327 short* disty = new short[dfwidth*dfheight];
328 double* outerdist = new double[dfwidth*dfheight];
329 double* gx = new double[dfwidth*dfheight];
330 double* gy = new double[dfwidth*dfheight];
331 dfptr = (unsigned char*) dfstorage.get();
332 computegradient(dfptr, dfwidth, dfheight, gx, gy);
333 edtaa3(dfptr, gx, gy, dfwidth, dfheight, distx, disty, outerdist);
334
335 for (int i = 0; i < dfwidth*dfheight; ++i) {
336 *dfptr++ = 255 - *dfptr;
337 }
338 double* innerdist = new double[dfwidth*dfheight];
339 dfptr = (unsigned char*) dfstorage.get();
340 memset(gx, 0, sizeof(double)*dfwidth*dfheight);
341 memset(gy, 0, sizeof(double)*dfwidth*dfheight);
342 computegradient(dfptr, dfwidth, dfheight, gx, gy);
343 edtaa3(dfptr, gx, gy, dfwidth, dfheight, distx, disty, innerdist);
344
345 for (int i = 0; i < dfwidth*dfheight; ++i) {
346 unsigned char val;
347 double outerval = outerdist[i];
348 if (outerval < 0.0) { outerval = 0.0; }
349 double innerval = innerdist[i];
350 if (innerval < 0.0) { innerval = 0.0; }
351 double dist = outerval - innerval;
352 if (dist <= -DISTANCE_FIELD_RANGE) {
353 val = 255;
354 } else if (dist > DISTANCE_FIELD_RANGE) {
355 val = 0;
356 } else {
357 val = (unsigned char)((DISTANCE_FIELD_RANGE-dist)*128.0/DISTANCE _FIELD_RANGE);
358 }
359 *dfptr++ = val;
360 }
361
362 delete [] distx;
363 delete [] disty;
364 delete [] innerdist;
365 delete [] outerdist;
366
367 // copy to atlas
368 plot = fAtlasMgr->addToAtlas(&fAtlas, dfwidth, dfheight, dfstorage.get() ,
369 &glyph->fAtlasLocation);
370
371 } else {
372 size_t size = glyph->fBounds.area() * bytesPerPixel;
373 SkAutoSMalloc<1024> storage(size);
374 if (!scaler->getPackedGlyphImage(glyph->fPackedID, glyph->width(),
375 glyph->height(),
376 glyph->width() * bytesPerPixel,
377 storage.get())) {
378 return false;
379 }
380
381 plot = fAtlasMgr->addToAtlas(&fAtlas, glyph->width(), glyph->height(), s torage.get(),
382 &glyph->fAtlasLocation);
280 } 383 }
281 384
282 GrPlot* plot = fAtlasMgr->addToAtlas(&fAtlas, glyph->width(),
283 glyph->height(), storage.get(),
284 &glyph->fAtlasLocation);
285 if (NULL == plot) { 385 if (NULL == plot) {
286 return false; 386 return false;
287 } 387 }
288 388
289 glyph->fPlot = plot; 389 glyph->fPlot = plot;
290 return true; 390 return true;
291 } 391 }
392
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698