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

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

Issue 1042373002: Emulate gamma fix by making glyphs thicker or thinner (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Remove header Created 5 years, 8 months 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
OLDNEW
1 /* 1 /*
2 * Copyright 2013 Google Inc. 2 * Copyright 2013 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 "GrDistanceFieldTextContext.h" 8 #include "GrDistanceFieldTextContext.h"
9 #include "GrAtlas.h" 9 #include "GrAtlas.h"
10 #include "GrBitmapTextContext.h" 10 #include "GrBitmapTextContext.h"
(...skipping 24 matching lines...) Expand all
35 static const int kMinDFFontSize = 18; 35 static const int kMinDFFontSize = 18;
36 static const int kSmallDFFontSize = 32; 36 static const int kSmallDFFontSize = 32;
37 static const int kSmallDFFontLimit = 32; 37 static const int kSmallDFFontLimit = 32;
38 static const int kMediumDFFontSize = 72; 38 static const int kMediumDFFontSize = 72;
39 static const int kMediumDFFontLimit = 72; 39 static const int kMediumDFFontLimit = 72;
40 static const int kLargeDFFontSize = 162; 40 static const int kLargeDFFontSize = 162;
41 41
42 static const int kVerticesPerGlyph = 4; 42 static const int kVerticesPerGlyph = 4;
43 static const int kIndicesPerGlyph = 6; 43 static const int kIndicesPerGlyph = 6;
44 44
45 #ifdef SK_DEBUG
46 static const int kExpectedWidthAdjustTableSize = 8;
47 #endif
48 static const int kWidthAdjustLumShift = 5;
49
45 GrDistanceFieldTextContext::GrDistanceFieldTextContext(GrContext* context, 50 GrDistanceFieldTextContext::GrDistanceFieldTextContext(GrContext* context,
46 SkGpuDevice* gpuDevice, 51 SkGpuDevice* gpuDevice,
47 const SkDeviceProperties& properties, 52 const SkDeviceProperties& properties,
48 bool enable) 53 bool enable)
49 : GrTextContext(context, gpuDevice, properties) { 54 : GrTextContext(context, gpuDevice, properties) {
50 #if SK_FORCE_DISTANCE_FIELD_TEXT 55 #if SK_FORCE_DISTANCE_FIELD_TEXT
51 fEnableDFRendering = true; 56 fEnableDFRendering = true;
52 #else 57 #else
53 fEnableDFRendering = enable; 58 fEnableDFRendering = enable;
54 #endif 59 #endif
55 fStrike = NULL; 60 fStrike = NULL;
56 fGammaTexture = NULL; 61 fWidthAdjustTable = NULL;
57 62
58 fEffectTextureUniqueID = SK_InvalidUniqueID; 63 fEffectTextureUniqueID = SK_InvalidUniqueID;
59 fEffectColor = GrColor_ILLEGAL; 64 fEffectColor = GrColor_ILLEGAL;
60 fEffectFlags = kInvalid_DistanceFieldEffectFlag; 65 fEffectFlags = kInvalid_DistanceFieldEffectFlag;
61 66
62 fVertices = NULL; 67 fVertices = NULL;
63 fCurrVertex = 0; 68 fCurrVertex = 0;
64 fAllocVertexCount = 0; 69 fAllocVertexCount = 0;
65 fTotalVertexCount = 0; 70 fTotalVertexCount = 0;
66 fCurrTexture = NULL; 71 fCurrTexture = NULL;
67 72
68 fVertexBounds.setLargestInverted(); 73 fVertexBounds.setLargestInverted();
69 } 74 }
70 75
71 GrDistanceFieldTextContext* GrDistanceFieldTextContext::Create(GrContext* contex t, 76 GrDistanceFieldTextContext* GrDistanceFieldTextContext::Create(GrContext* contex t,
72 SkGpuDevice* gpuD evice, 77 SkGpuDevice* gpuD evice,
73 const SkDevicePro perties& props, 78 const SkDevicePro perties& props,
74 bool enable) { 79 bool enable) {
75 GrDistanceFieldTextContext* textContext = SkNEW_ARGS(GrDistanceFieldTextCont ext, 80 GrDistanceFieldTextContext* textContext = SkNEW_ARGS(GrDistanceFieldTextCont ext,
76 (context, gpuDevice, pr ops, enable)); 81 (context, gpuDevice, pr ops, enable));
82 textContext->buildWidthAdjustTable();
77 #ifdef USE_BITMAP_TEXTBLOBS 83 #ifdef USE_BITMAP_TEXTBLOBS
78 textContext->fFallbackTextContext = GrBitmapTextContextB::Create(context, gp uDevice, props); 84 textContext->fFallbackTextContext = GrBitmapTextContextB::Create(context, gp uDevice, props);
79 #else 85 #else
80 textContext->fFallbackTextContext = GrBitmapTextContext::Create(context, gpu Device, props); 86 textContext->fFallbackTextContext = GrBitmapTextContext::Create(context, gpu Device, props);
81 #endif 87 #endif
82 88
83 return textContext; 89 return textContext;
84 } 90 }
85 91
92
93 void GrDistanceFieldTextContext::buildWidthAdjustTable() {
94 int width, height;
95 size_t size;
96
97 #ifdef SK_GAMMA_CONTRAST
98 SkScalar contrast = SK_GAMMA_CONTRAST;
99 #else
100 SkScalar contrast = 0.5f;
101 #endif
102 SkScalar paintGamma = fDeviceProperties.gamma();
103 SkScalar deviceGamma = fDeviceProperties.gamma();
104
105 size = SkScalerContext::GetGammaLUTSize(contrast, paintGamma, deviceGamma,
106 &width, &height);
107
108 SkASSERT(kExpectedWidthAdjustTableSize == height);
109 fWidthAdjustTable = SkNEW_ARRAY(SkScalar, height);
110
111 SkAutoTArray<uint8_t> data((int)size);
112 SkScalerContext::GetGammaLUTData(contrast, paintGamma, deviceGamma, data.get ());
113
114 // find the inverse points where we cross 0.5
115 // binsearch might be better, but we only need to do this once on creation
116 for (int row = 0; row < height; ++row) {
117 uint8_t* rowPtr = data.get() + row*width;
118 for (int col = 0; col < width - 1; ++col) {
119 if (rowPtr[col] <= 127 && rowPtr[col + 1] >= 128) {
120 // compute point where a mask value will give us a result of 0.5
121 float interp = (127.5f - rowPtr[col]) / (rowPtr[col + 1] - rowPt r[col]);
122 float borderAlpha = (col + interp) / 255.f;
123
124 // compute t value for that alpha
125 // this is an approximate inverse for smoothstep()
126 float t = borderAlpha*(borderAlpha*(4.0f*borderAlpha - 6.0f) + 5 .0f) / 3.0f;
127
128 // compute distance which gives us that t value
129 float d = 2.0f*0.7071f*t - 0.7071f;
130
131 fWidthAdjustTable[row] = d;
132 break;
133 }
134 }
135 }
136 }
137
138
86 GrDistanceFieldTextContext::~GrDistanceFieldTextContext() { 139 GrDistanceFieldTextContext::~GrDistanceFieldTextContext() {
87 SkSafeSetNull(fGammaTexture); 140 SkDELETE_ARRAY(fWidthAdjustTable);
141 fWidthAdjustTable = NULL;
88 } 142 }
89 143
90 bool GrDistanceFieldTextContext::canDraw(const GrRenderTarget* rt, 144 bool GrDistanceFieldTextContext::canDraw(const GrRenderTarget* rt,
91 const GrClip& clip, 145 const GrClip& clip,
92 const GrPaint& paint, 146 const GrPaint& paint,
93 const SkPaint& skPaint, 147 const SkPaint& skPaint,
94 const SkMatrix& viewMatrix) { 148 const SkMatrix& viewMatrix) {
95 // TODO: support perspective (need getMaxScale replacement) 149 // TODO: support perspective (need getMaxScale replacement)
96 if (viewMatrix.hasPerspective()) { 150 if (viewMatrix.hasPerspective()) {
97 return false; 151 return false;
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 } 229 }
176 230
177 fUseLCDText = fSkPaint.isLCDRenderText(); 231 fUseLCDText = fSkPaint.isLCDRenderText();
178 232
179 fSkPaint.setLCDRenderText(false); 233 fSkPaint.setLCDRenderText(false);
180 fSkPaint.setAutohinted(false); 234 fSkPaint.setAutohinted(false);
181 fSkPaint.setHinting(SkPaint::kNormal_Hinting); 235 fSkPaint.setHinting(SkPaint::kNormal_Hinting);
182 fSkPaint.setSubpixelText(true); 236 fSkPaint.setSubpixelText(true);
183 } 237 }
184 238
185 static void setup_gamma_texture(GrContext* context, const SkGlyphCache* cache,
186 const SkDeviceProperties& deviceProperties,
187 GrTexture** gammaTexture) {
188 if (NULL == *gammaTexture) {
189 int width, height;
190 size_t size;
191
192 #ifdef SK_GAMMA_CONTRAST
193 SkScalar contrast = SK_GAMMA_CONTRAST;
194 #else
195 SkScalar contrast = 0.5f;
196 #endif
197 SkScalar paintGamma = deviceProperties.gamma();
198 SkScalar deviceGamma = deviceProperties.gamma();
199
200 size = SkScalerContext::GetGammaLUTSize(contrast, paintGamma, deviceGamm a,
201 &width, &height);
202
203 SkAutoTArray<uint8_t> data((int)size);
204 SkScalerContext::GetGammaLUTData(contrast, paintGamma, deviceGamma, data .get());
205
206 // TODO: Update this to use the cache rather than directly creating a te xture.
207 GrSurfaceDesc desc;
208 desc.fFlags = kNone_GrSurfaceFlags;
209 desc.fWidth = width;
210 desc.fHeight = height;
211 desc.fConfig = kAlpha_8_GrPixelConfig;
212
213 *gammaTexture = context->getGpu()->createTexture(desc, true, NULL, 0);
214 if (NULL == *gammaTexture) {
215 return;
216 }
217
218 (*gammaTexture)->writePixels(0, 0, width, height,
219 (*gammaTexture)->config(), data.get(), 0,
220 GrContext::kDontFlush_PixelOpsFlag);
221 }
222 }
223
224 void GrDistanceFieldTextContext::onDrawText(GrRenderTarget* rt, const GrClip& cl ip, 239 void GrDistanceFieldTextContext::onDrawText(GrRenderTarget* rt, const GrClip& cl ip,
225 const GrPaint& paint, 240 const GrPaint& paint,
226 const SkPaint& skPaint, const SkMatr ix& viewMatrix, 241 const SkPaint& skPaint, const SkMatr ix& viewMatrix,
227 const char text[], size_t byteLength , 242 const char text[], size_t byteLength ,
228 SkScalar x, SkScalar y, 243 SkScalar x, SkScalar y,
229 const SkIRect& regionClipBounds) { 244 const SkIRect& regionClipBounds) {
230 SkASSERT(byteLength == 0 || text != NULL); 245 SkASSERT(byteLength == 0 || text != NULL);
231 246
232 // nothing to draw 247 // nothing to draw
233 if (text == NULL || byteLength == 0) { 248 if (text == NULL || byteLength == 0) {
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 321
307 fViewMatrix = viewMatrix; 322 fViewMatrix = viewMatrix;
308 this->init(rt, clip, paint, skPaint, regionClipBounds); 323 this->init(rt, clip, paint, skPaint, regionClipBounds);
309 324
310 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); 325 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
311 326
312 SkAutoGlyphCacheNoGamma autoCache(fSkPaint, &fDeviceProperties, NULL); 327 SkAutoGlyphCacheNoGamma autoCache(fSkPaint, &fDeviceProperties, NULL);
313 SkGlyphCache* cache = autoCache.getCache(); 328 SkGlyphCache* cache = autoCache.getCache();
314 GrFontScaler* fontScaler = GetGrFontScaler(cache); 329 GrFontScaler* fontScaler = GetGrFontScaler(cache);
315 330
316 setup_gamma_texture(fContext, cache, fDeviceProperties, &fGammaTexture);
317
318 int numGlyphs = fSkPaint.textToGlyphs(text, byteLength, NULL); 331 int numGlyphs = fSkPaint.textToGlyphs(text, byteLength, NULL);
319 fTotalVertexCount = kVerticesPerGlyph*numGlyphs; 332 fTotalVertexCount = kVerticesPerGlyph*numGlyphs;
320 333
321 const char* stop = text + byteLength; 334 const char* stop = text + byteLength;
322 SkTArray<char> fallbackTxt; 335 SkTArray<char> fallbackTxt;
323 SkTArray<SkScalar> fallbackPos; 336 SkTArray<SkScalar> fallbackPos;
324 337
325 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) { 338 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
326 while (text < stop) { 339 while (text < stop) {
327 const char* lastText = text; 340 const char* lastText = text;
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
435 flags |= fUseLCDText && useBGR ? kBGR_DistanceFieldEffectFlag : 0; 448 flags |= fUseLCDText && useBGR ? kBGR_DistanceFieldEffectFlag : 0;
436 449
437 // see if we need to create a new effect 450 // see if we need to create a new effect
438 if (textureUniqueID != fEffectTextureUniqueID || 451 if (textureUniqueID != fEffectTextureUniqueID ||
439 filteredColor != fEffectColor || 452 filteredColor != fEffectColor ||
440 flags != fEffectFlags || 453 flags != fEffectFlags ||
441 !fCachedGeometryProcessor->viewMatrix().cheapEqualTo(fViewMatrix)) { 454 !fCachedGeometryProcessor->viewMatrix().cheapEqualTo(fViewMatrix)) {
442 GrColor color = fPaint.getColor(); 455 GrColor color = fPaint.getColor();
443 if (fUseLCDText) { 456 if (fUseLCDText) {
444 GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredCol or); 457 GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredCol or);
458
459 float redCorrection =
460 fWidthAdjustTable[GrColorUnpackR(colorNoPreMul) >> kWidthAdjustL umShift];
461 float greenCorrection =
462 fWidthAdjustTable[GrColorUnpackG(colorNoPreMul) >> kWidthAdjustL umShift];
463 float blueCorrection =
464 fWidthAdjustTable[GrColorUnpackB(colorNoPreMul) >> kWidthAdjustL umShift];
465 GrDistanceFieldLCDTextureEffect::WidthAdjust widthAdjust =
466 GrDistanceFieldLCDTextureEffect::WidthAdjust::Make(redCorrection ,
467 greenCorrecti on,
468 blueCorrectio n);
445 fCachedGeometryProcessor.reset(GrDistanceFieldLCDTextureEffect::Crea te(color, 469 fCachedGeometryProcessor.reset(GrDistanceFieldLCDTextureEffect::Crea te(color,
446 fViewMatrix, 470 fViewMatrix,
447 fCurrTexture, 471 fCurrTexture,
448 params, 472 params,
449 fGammaTexture, 473 widthAdjust,
450 gammaParams,
451 colorNoPreMul,
452 flags)); 474 flags));
453 } else { 475 } else {
454 flags |= kColorAttr_DistanceFieldEffectFlag; 476 flags |= kColorAttr_DistanceFieldEffectFlag;
455 bool opaque = GrColorIsOpaque(color); 477 bool opaque = GrColorIsOpaque(color);
456 #ifdef SK_GAMMA_APPLY_TO_A8 478 #ifdef SK_GAMMA_APPLY_TO_A8
457 U8CPU lum = SkColorSpaceLuminance::computeLuminance(fDevicePropertie s.gamma(), 479 U8CPU lum = SkColorSpaceLuminance::computeLuminance(fDevicePropertie s.gamma(),
458 filteredColor); 480 filteredColor);
481 float correction = fWidthAdjustTable[lum >> kWidthAdjustLumShift];
459 fCachedGeometryProcessor.reset(GrDistanceFieldTextureEffect::Create( color, 482 fCachedGeometryProcessor.reset(GrDistanceFieldTextureEffect::Create( color,
460 fViewMatrix, 483 fViewMatrix,
461 fCurrTexture, 484 fCurrTexture,
462 params, 485 params,
463 fGammaTexture, 486 correction,
464 gammaParams,
465 lum/255.f,
466 flags, 487 flags,
467 opaque)); 488 opaque));
468 #else 489 #else
469 fCachedGeometryProcessor.reset(GrDistanceFieldTextureEffect::Create( color, 490 fCachedGeometryProcessor.reset(GrDistanceFieldTextureEffect::Create( color,
470 fViewMatrix, 491 fViewMatrix,
471 fCurrTexture, 492 fCurrTexture,
472 params, 493 params,
473 flags, 494 flags,
474 opaque)); 495 opaque));
475 #endif 496 #endif
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
736 } 757 }
737 } 758 }
738 759
739 inline void GrDistanceFieldTextContext::finish() { 760 inline void GrDistanceFieldTextContext::finish() {
740 this->flush(); 761 this->flush();
741 fTotalVertexCount = 0; 762 fTotalVertexCount = 0;
742 763
743 GrTextContext::finish(); 764 GrTextContext::finish();
744 } 765 }
745 766
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698