OLD | NEW |
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 #if SK_DISTANCEFIELD_FONTS | 15 #if SK_DISTANCEFIELD_FONTS |
16 #include "edtaa3.h" | 16 #include "SkDistanceFieldGen.h" |
17 #endif | 17 #endif |
18 | 18 |
19 /////////////////////////////////////////////////////////////////////////////// | 19 /////////////////////////////////////////////////////////////////////////////// |
20 | 20 |
21 #define FONT_CACHE_STATS 0 | 21 #define FONT_CACHE_STATS 0 |
22 #if FONT_CACHE_STATS | 22 #if FONT_CACHE_STATS |
23 static int g_PurgeCount = 0; | 23 static int g_PurgeCount = 0; |
24 #endif | 24 #endif |
25 | 25 |
26 GrFontCache::GrFontCache(GrGpu* gpu) : fGpu(gpu) { | 26 GrFontCache::GrFontCache(GrGpu* gpu) : fGpu(gpu) { |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 } | 192 } |
193 #endif | 193 #endif |
194 | 194 |
195 /////////////////////////////////////////////////////////////////////////////// | 195 /////////////////////////////////////////////////////////////////////////////// |
196 | 196 |
197 #ifdef SK_DEBUG | 197 #ifdef SK_DEBUG |
198 static int gCounter; | 198 static int gCounter; |
199 #endif | 199 #endif |
200 | 200 |
201 #if SK_DISTANCEFIELD_FONTS | 201 #if SK_DISTANCEFIELD_FONTS |
202 #define DISTANCE_FIELD_PAD 4 | 202 // this acts as the max magnitude for the distance field, |
203 #define DISTANCE_FIELD_RANGE (4.0) | 203 // as well as the pad we need around the glyph |
| 204 #define DISTANCE_FIELD_RANGE 4 |
204 #endif | 205 #endif |
205 | 206 |
206 /* | 207 /* |
207 The text strike is specific to a given font/style/matrix setup, which is | 208 The text strike is specific to a given font/style/matrix setup, which is |
208 represented by the GrHostFontScaler object we are given in getGlyph(). | 209 represented by the GrHostFontScaler object we are given in getGlyph(). |
209 | 210 |
210 We map a 32bit glyphID to a GrGlyph record, which in turn points to a | 211 We map a 32bit glyphID to a GrGlyph record, which in turn points to a |
211 atlas and a position within that texture. | 212 atlas and a position within that texture. |
212 */ | 213 */ |
213 | 214 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
246 GrFontScaler* scaler) { | 247 GrFontScaler* scaler) { |
247 SkIRect bounds; | 248 SkIRect bounds; |
248 if (!scaler->getPackedGlyphBounds(packed, &bounds)) { | 249 if (!scaler->getPackedGlyphBounds(packed, &bounds)) { |
249 return NULL; | 250 return NULL; |
250 } | 251 } |
251 | 252 |
252 GrGlyph* glyph = fPool.alloc(); | 253 GrGlyph* glyph = fPool.alloc(); |
253 #if SK_DISTANCEFIELD_FONTS | 254 #if SK_DISTANCEFIELD_FONTS |
254 // expand bounds to hold full distance field data | 255 // expand bounds to hold full distance field data |
255 if (fUseDistanceField) { | 256 if (fUseDistanceField) { |
256 bounds.fLeft -= DISTANCE_FIELD_PAD; | 257 bounds.fLeft -= DISTANCE_FIELD_RANGE; |
257 bounds.fRight += DISTANCE_FIELD_PAD; | 258 bounds.fRight += DISTANCE_FIELD_RANGE; |
258 bounds.fTop -= DISTANCE_FIELD_PAD; | 259 bounds.fTop -= DISTANCE_FIELD_RANGE; |
259 bounds.fBottom += DISTANCE_FIELD_PAD; | 260 bounds.fBottom += DISTANCE_FIELD_RANGE; |
260 } | 261 } |
261 #endif | 262 #endif |
262 glyph->init(packed, bounds); | 263 glyph->init(packed, bounds); |
263 fCache.insert(packed, glyph); | 264 fCache.insert(packed, glyph); |
264 return glyph; | 265 return glyph; |
265 } | 266 } |
266 | 267 |
267 void GrTextStrike::removePlot(const GrPlot* plot) { | 268 void GrTextStrike::removePlot(const GrPlot* plot) { |
268 SkTDArray<GrGlyph*>& glyphArray = fCache.getArray(); | 269 SkTDArray<GrGlyph*>& glyphArray = fCache.getArray(); |
269 for (int i = 0; i < glyphArray.count(); ++i) { | 270 for (int i = 0; i < glyphArray.count(); ++i) { |
(...skipping 17 matching lines...) Expand all Loading... |
287 SkASSERT(fCache.contains(glyph)); | 288 SkASSERT(fCache.contains(glyph)); |
288 SkASSERT(NULL == glyph->fPlot); | 289 SkASSERT(NULL == glyph->fPlot); |
289 | 290 |
290 SkAutoRef ar(scaler); | 291 SkAutoRef ar(scaler); |
291 | 292 |
292 int bytesPerPixel = GrMaskFormatBytesPerPixel(fMaskFormat); | 293 int bytesPerPixel = GrMaskFormatBytesPerPixel(fMaskFormat); |
293 | 294 |
294 GrPlot* plot; | 295 GrPlot* plot; |
295 #if SK_DISTANCEFIELD_FONTS | 296 #if SK_DISTANCEFIELD_FONTS |
296 if (fUseDistanceField) { | 297 if (fUseDistanceField) { |
297 SkASSERT(1 == bytesPerPixel); | |
298 | |
299 // we've already expanded the glyph dimensions to match the final size | 298 // we've already expanded the glyph dimensions to match the final size |
300 // but must shrink back down to get the packed glyph data | 299 // but must shrink back down to get the packed glyph data |
301 int dfWidth = glyph->width(); | 300 int dfWidth = glyph->width(); |
302 int dfHeight = glyph->height(); | 301 int dfHeight = glyph->height(); |
303 int width = dfWidth - 2*DISTANCE_FIELD_PAD; | 302 int width = dfWidth - 2*DISTANCE_FIELD_RANGE; |
304 int height = dfHeight - 2*DISTANCE_FIELD_PAD; | 303 int height = dfHeight - 2*DISTANCE_FIELD_RANGE; |
305 size_t stride = width*bytesPerPixel; | 304 int stride = width*bytesPerPixel; |
306 | 305 |
307 size_t size = width * height * bytesPerPixel; | 306 size_t size = width * height * bytesPerPixel; |
308 SkAutoSMalloc<1024> storage(size); | 307 SkAutoSMalloc<1024> storage(size); |
309 if (!scaler->getPackedGlyphImage(glyph->fPackedID, width, height, stride
, storage.get())) { | 308 if (!scaler->getPackedGlyphImage(glyph->fPackedID, width, height, stride
, storage.get())) { |
310 return false; | 309 return false; |
311 } | 310 } |
312 | 311 |
313 // alloc storage for distance field glyph | 312 // alloc storage for distance field glyph |
314 size_t dfSize = dfWidth * dfHeight * bytesPerPixel; | 313 size_t dfSize = dfWidth * dfHeight * bytesPerPixel; |
315 SkAutoSMalloc<1024> dfStorage(dfSize); | 314 SkAutoSMalloc<1024> dfStorage(dfSize); |
| 315 |
| 316 if (1 == bytesPerPixel) { |
| 317 (void) SkGenerateDistanceFieldFromImage((unsigned char*)dfStorage.ge
t(), |
| 318 (unsigned char*)storage.get(
), |
| 319 width, height, DISTANCE_FIEL
D_RANGE); |
| 320 } else { |
| 321 // TODO: Fix color emoji |
| 322 // for now, copy glyph into distance field storage |
| 323 // this is not correct, but it won't crash |
| 324 sk_bzero(dfStorage.get(), dfSize); |
| 325 unsigned char* ptr = (unsigned char*) storage.get(); |
| 326 unsigned char* dfPtr = (unsigned char*) dfStorage.get(); |
| 327 size_t dfStride = dfWidth*bytesPerPixel; |
| 328 dfPtr += DISTANCE_FIELD_RANGE*dfStride; |
| 329 dfPtr += DISTANCE_FIELD_RANGE*bytesPerPixel; |
316 | 330 |
317 // copy glyph into distance field storage | 331 for (int i = 0; i < height; ++i) { |
318 sk_bzero(dfStorage.get(), dfSize); | 332 memcpy(dfPtr, ptr, stride); |
319 | 333 |
320 unsigned char* ptr = (unsigned char*) storage.get(); | 334 dfPtr += dfStride; |
321 unsigned char* dfPtr = (unsigned char*) dfStorage.get(); | 335 ptr += stride; |
322 size_t dfStride = dfWidth*bytesPerPixel; | |
323 dfPtr += DISTANCE_FIELD_PAD*dfStride; | |
324 dfPtr += DISTANCE_FIELD_PAD*bytesPerPixel; | |
325 | |
326 for (int i = 0; i < height; ++i) { | |
327 memcpy(dfPtr, ptr, stride); | |
328 | |
329 dfPtr += dfStride; | |
330 ptr += stride; | |
331 } | |
332 | |
333 // generate distance field data | |
334 SkAutoSMalloc<1024> distXStorage(dfWidth*dfHeight*sizeof(short)); | |
335 SkAutoSMalloc<1024> distYStorage(dfWidth*dfHeight*sizeof(short)); | |
336 SkAutoSMalloc<1024> outerDistStorage(dfWidth*dfHeight*sizeof(double)); | |
337 SkAutoSMalloc<1024> innerDistStorage(dfWidth*dfHeight*sizeof(double)); | |
338 SkAutoSMalloc<1024> gxStorage(dfWidth*dfHeight*sizeof(double)); | |
339 SkAutoSMalloc<1024> gyStorage(dfWidth*dfHeight*sizeof(double)); | |
340 | |
341 short* distX = (short*) distXStorage.get(); | |
342 short* distY = (short*) distYStorage.get(); | |
343 double* outerDist = (double*) outerDistStorage.get(); | |
344 double* innerDist = (double*) innerDistStorage.get(); | |
345 double* gx = (double*) gxStorage.get(); | |
346 double* gy = (double*) gyStorage.get(); | |
347 | |
348 dfPtr = (unsigned char*) dfStorage.get(); | |
349 EDTAA::computegradient(dfPtr, dfWidth, dfHeight, gx, gy); | |
350 EDTAA::edtaa3(dfPtr, gx, gy, dfWidth, dfHeight, distX, distY, outerDist)
; | |
351 | |
352 for (int i = 0; i < dfWidth*dfHeight; ++i) { | |
353 *dfPtr = 255 - *dfPtr; | |
354 dfPtr++; | |
355 } | |
356 dfPtr = (unsigned char*) dfStorage.get(); | |
357 sk_bzero(gx, sizeof(double)*dfWidth*dfHeight); | |
358 sk_bzero(gy, sizeof(double)*dfWidth*dfHeight); | |
359 EDTAA::computegradient(dfPtr, dfWidth, dfHeight, gx, gy); | |
360 EDTAA::edtaa3(dfPtr, gx, gy, dfWidth, dfHeight, distX, distY, innerDist)
; | |
361 | |
362 for (int i = 0; i < dfWidth*dfHeight; ++i) { | |
363 unsigned char val; | |
364 double outerval = outerDist[i]; | |
365 if (outerval < 0.0) { | |
366 outerval = 0.0; | |
367 } | 336 } |
368 double innerval = innerDist[i]; | |
369 if (innerval < 0.0) { | |
370 innerval = 0.0; | |
371 } | |
372 double dist = outerval - innerval; | |
373 if (dist <= -DISTANCE_FIELD_RANGE) { | |
374 val = 255; | |
375 } else if (dist > DISTANCE_FIELD_RANGE) { | |
376 val = 0; | |
377 } else { | |
378 val = (unsigned char)((DISTANCE_FIELD_RANGE-dist)*128.0/DISTANCE
_FIELD_RANGE); | |
379 } | |
380 *dfPtr++ = val; | |
381 } | 337 } |
382 | 338 |
383 // copy to atlas | 339 // copy to atlas |
384 plot = fAtlasMgr->addToAtlas(&fAtlas, dfWidth, dfHeight, dfStorage.get()
, | 340 plot = fAtlasMgr->addToAtlas(&fAtlas, dfWidth, dfHeight, dfStorage.get()
, |
385 &glyph->fAtlasLocation); | 341 &glyph->fAtlasLocation); |
386 | 342 |
387 } else { | 343 } else { |
388 #endif | 344 #endif |
389 size_t size = glyph->fBounds.area() * bytesPerPixel; | 345 size_t size = glyph->fBounds.area() * bytesPerPixel; |
390 SkAutoSMalloc<1024> storage(size); | 346 SkAutoSMalloc<1024> storage(size); |
(...skipping 11 matching lines...) Expand all Loading... |
402 } | 358 } |
403 #endif | 359 #endif |
404 | 360 |
405 if (NULL == plot) { | 361 if (NULL == plot) { |
406 return false; | 362 return false; |
407 } | 363 } |
408 | 364 |
409 glyph->fPlot = plot; | 365 glyph->fPlot = plot; |
410 return true; | 366 return true; |
411 } | 367 } |
OLD | NEW |