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

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: Rebase to ToT 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 textContext->fFallbackTextContext = GrBitmapTextContext::Create(context, gpu Device, props); 83 textContext->fFallbackTextContext = GrBitmapTextContext::Create(context, gpu Device, props);
78 84
79 return textContext; 85 return textContext;
80 } 86 }
81 87
88
89 void GrDistanceFieldTextContext::buildWidthAdjustTable() {
90 int width, height;
91 size_t size;
92
93 #ifdef SK_GAMMA_CONTRAST
94 SkScalar contrast = SK_GAMMA_CONTRAST;
95 #else
96 SkScalar contrast = 0.5f;
97 #endif
98 SkScalar paintGamma = fDeviceProperties.gamma();
99 SkScalar deviceGamma = fDeviceProperties.gamma();
100
101 size = SkScalerContext::GetGammaLUTSize(contrast, paintGamma, deviceGamma,
102 &width, &height);
103
104 SkASSERT(kExpectedWidthAdjustTableSize == height);
105 fWidthAdjustTable = SkNEW_ARRAY(SkScalar, height);
106
107 SkAutoTArray<uint8_t> data((int)size);
108 SkScalerContext::GetGammaLUTData(contrast, paintGamma, deviceGamma, data.get ());
109
110 // find the inverse points where we cross 0.5
111 // binsearch might be better, but we only need to do this once on creation
112 for (int row = 0; row < height; ++row) {
113 uint8_t* rowPtr = data.get() + row*width;
114 for (int col = 0; col < width - 1; ++col) {
115 if (rowPtr[col] <= 127 && rowPtr[col + 1] >= 128) {
116 // compute point where a mask value will give us a result of 0.5
117 float interp = (127.5f - rowPtr[col]) / (rowPtr[col + 1] - rowPt r[col]);
118 float borderAlpha = (col + interp) / 255.f;
119
120 // compute t value for that alpha
121 // this is an approximate inverse for smoothstep()
122 float t = borderAlpha*(borderAlpha*(4.0f*borderAlpha - 6.0f) + 5 .0f) / 3.0f;
123
124 // compute distance which gives us that t value
125 float d = 2.0f*0.7071f*t - 0.7071f;
126
127 fWidthAdjustTable[row] = d;
128 break;
129 }
130 }
131 }
132 }
133
134
82 GrDistanceFieldTextContext::~GrDistanceFieldTextContext() { 135 GrDistanceFieldTextContext::~GrDistanceFieldTextContext() {
83 SkSafeSetNull(fGammaTexture); 136 SkDELETE_ARRAY(fWidthAdjustTable);
137 fWidthAdjustTable = NULL;
84 } 138 }
85 139
86 bool GrDistanceFieldTextContext::canDraw(const GrRenderTarget* rt, 140 bool GrDistanceFieldTextContext::canDraw(const GrRenderTarget* rt,
87 const GrClip& clip, 141 const GrClip& clip,
88 const GrPaint& paint, 142 const GrPaint& paint,
89 const SkPaint& skPaint, 143 const SkPaint& skPaint,
90 const SkMatrix& viewMatrix) { 144 const SkMatrix& viewMatrix) {
91 // TODO: support perspective (need getMaxScale replacement) 145 // TODO: support perspective (need getMaxScale replacement)
92 if (viewMatrix.hasPerspective()) { 146 if (viewMatrix.hasPerspective()) {
93 return false; 147 return false;
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
171 } 225 }
172 226
173 fUseLCDText = fSkPaint.isLCDRenderText(); 227 fUseLCDText = fSkPaint.isLCDRenderText();
174 228
175 fSkPaint.setLCDRenderText(false); 229 fSkPaint.setLCDRenderText(false);
176 fSkPaint.setAutohinted(false); 230 fSkPaint.setAutohinted(false);
177 fSkPaint.setHinting(SkPaint::kNormal_Hinting); 231 fSkPaint.setHinting(SkPaint::kNormal_Hinting);
178 fSkPaint.setSubpixelText(true); 232 fSkPaint.setSubpixelText(true);
179 } 233 }
180 234
181 static void setup_gamma_texture(GrContext* context, const SkGlyphCache* cache,
182 const SkDeviceProperties& deviceProperties,
183 GrTexture** gammaTexture) {
184 if (NULL == *gammaTexture) {
185 int width, height;
186 size_t size;
187
188 #ifdef SK_GAMMA_CONTRAST
189 SkScalar contrast = SK_GAMMA_CONTRAST;
190 #else
191 SkScalar contrast = 0.5f;
192 #endif
193 SkScalar paintGamma = deviceProperties.gamma();
194 SkScalar deviceGamma = deviceProperties.gamma();
195
196 size = SkScalerContext::GetGammaLUTSize(contrast, paintGamma, deviceGamm a,
197 &width, &height);
198
199 SkAutoTArray<uint8_t> data((int)size);
200 SkScalerContext::GetGammaLUTData(contrast, paintGamma, deviceGamma, data .get());
201
202 // TODO: Update this to use the cache rather than directly creating a te xture.
203 GrSurfaceDesc desc;
204 desc.fFlags = kNone_GrSurfaceFlags;
205 desc.fWidth = width;
206 desc.fHeight = height;
207 desc.fConfig = kAlpha_8_GrPixelConfig;
208
209 *gammaTexture = context->getGpu()->createTexture(desc, true, NULL, 0);
210 if (NULL == *gammaTexture) {
211 return;
212 }
213
214 (*gammaTexture)->writePixels(0, 0, width, height,
215 (*gammaTexture)->config(), data.get(), 0,
216 GrContext::kDontFlush_PixelOpsFlag);
217 }
218 }
219
220 void GrDistanceFieldTextContext::onDrawText(GrRenderTarget* rt, const GrClip& cl ip, 235 void GrDistanceFieldTextContext::onDrawText(GrRenderTarget* rt, const GrClip& cl ip,
221 const GrPaint& paint, 236 const GrPaint& paint,
222 const SkPaint& skPaint, const SkMatr ix& viewMatrix, 237 const SkPaint& skPaint, const SkMatr ix& viewMatrix,
223 const char text[], size_t byteLength , 238 const char text[], size_t byteLength ,
224 SkScalar x, SkScalar y, 239 SkScalar x, SkScalar y,
225 const SkIRect& regionClipBounds) { 240 const SkIRect& regionClipBounds) {
226 SkASSERT(byteLength == 0 || text != NULL); 241 SkASSERT(byteLength == 0 || text != NULL);
227 242
228 // nothing to draw 243 // nothing to draw
229 if (text == NULL || byteLength == 0) { 244 if (text == NULL || byteLength == 0) {
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
302 317
303 fViewMatrix = viewMatrix; 318 fViewMatrix = viewMatrix;
304 this->init(rt, clip, paint, skPaint, regionClipBounds); 319 this->init(rt, clip, paint, skPaint, regionClipBounds);
305 320
306 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); 321 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
307 322
308 SkAutoGlyphCacheNoGamma autoCache(fSkPaint, &fDeviceProperties, NULL); 323 SkAutoGlyphCacheNoGamma autoCache(fSkPaint, &fDeviceProperties, NULL);
309 SkGlyphCache* cache = autoCache.getCache(); 324 SkGlyphCache* cache = autoCache.getCache();
310 GrFontScaler* fontScaler = GetGrFontScaler(cache); 325 GrFontScaler* fontScaler = GetGrFontScaler(cache);
311 326
312 setup_gamma_texture(fContext, cache, fDeviceProperties, &fGammaTexture);
313
314 int numGlyphs = fSkPaint.textToGlyphs(text, byteLength, NULL); 327 int numGlyphs = fSkPaint.textToGlyphs(text, byteLength, NULL);
315 fTotalVertexCount = kVerticesPerGlyph*numGlyphs; 328 fTotalVertexCount = kVerticesPerGlyph*numGlyphs;
316 329
317 const char* stop = text + byteLength; 330 const char* stop = text + byteLength;
318 SkTArray<char> fallbackTxt; 331 SkTArray<char> fallbackTxt;
319 SkTArray<SkScalar> fallbackPos; 332 SkTArray<SkScalar> fallbackPos;
320 333
321 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) { 334 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
322 while (text < stop) { 335 while (text < stop) {
323 const char* lastText = text; 336 const char* lastText = text;
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
431 flags |= fUseLCDText && useBGR ? kBGR_DistanceFieldEffectFlag : 0; 444 flags |= fUseLCDText && useBGR ? kBGR_DistanceFieldEffectFlag : 0;
432 445
433 // see if we need to create a new effect 446 // see if we need to create a new effect
434 if (textureUniqueID != fEffectTextureUniqueID || 447 if (textureUniqueID != fEffectTextureUniqueID ||
435 filteredColor != fEffectColor || 448 filteredColor != fEffectColor ||
436 flags != fEffectFlags || 449 flags != fEffectFlags ||
437 !fCachedGeometryProcessor->viewMatrix().cheapEqualTo(fViewMatrix)) { 450 !fCachedGeometryProcessor->viewMatrix().cheapEqualTo(fViewMatrix)) {
438 GrColor color = fPaint.getColor(); 451 GrColor color = fPaint.getColor();
439 if (fUseLCDText) { 452 if (fUseLCDText) {
440 GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredCol or); 453 GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredCol or);
454
455 float redCorrection =
456 fWidthAdjustTable[GrColorUnpackR(colorNoPreMul) >> kWidthAdjustL umShift];
457 float greenCorrection =
458 fWidthAdjustTable[GrColorUnpackG(colorNoPreMul) >> kWidthAdjustL umShift];
459 float blueCorrection =
460 fWidthAdjustTable[GrColorUnpackB(colorNoPreMul) >> kWidthAdjustL umShift];
461 GrDistanceFieldLCDTextureEffect::WidthAdjust widthAdjust =
462 GrDistanceFieldLCDTextureEffect::WidthAdjust::Make(redCorrection ,
463 greenCorrecti on,
464 blueCorrectio n);
441 fCachedGeometryProcessor.reset(GrDistanceFieldLCDTextureEffect::Crea te(color, 465 fCachedGeometryProcessor.reset(GrDistanceFieldLCDTextureEffect::Crea te(color,
442 fViewMatrix, 466 fViewMatrix,
443 fCurrTexture, 467 fCurrTexture,
444 params, 468 params,
445 fGammaTexture, 469 widthAdjust,
446 gammaParams,
447 colorNoPreMul,
448 flags)); 470 flags));
449 } else { 471 } else {
450 flags |= kColorAttr_DistanceFieldEffectFlag; 472 flags |= kColorAttr_DistanceFieldEffectFlag;
451 bool opaque = GrColorIsOpaque(color); 473 bool opaque = GrColorIsOpaque(color);
452 #ifdef SK_GAMMA_APPLY_TO_A8 474 #ifdef SK_GAMMA_APPLY_TO_A8
453 U8CPU lum = SkColorSpaceLuminance::computeLuminance(fDevicePropertie s.gamma(), 475 U8CPU lum = SkColorSpaceLuminance::computeLuminance(fDevicePropertie s.gamma(),
454 filteredColor); 476 filteredColor);
477 float correction = fWidthAdjustTable[lum >> kWidthAdjustLumShift];
455 fCachedGeometryProcessor.reset(GrDistanceFieldTextureEffect::Create( color, 478 fCachedGeometryProcessor.reset(GrDistanceFieldTextureEffect::Create( color,
456 fViewMatrix, 479 fViewMatrix,
457 fCurrTexture, 480 fCurrTexture,
458 params, 481 params,
459 fGammaTexture, 482 correction,
460 gammaParams,
461 lum/255.f,
462 flags, 483 flags,
463 opaque)); 484 opaque));
464 #else 485 #else
465 fCachedGeometryProcessor.reset(GrDistanceFieldTextureEffect::Create( color, 486 fCachedGeometryProcessor.reset(GrDistanceFieldTextureEffect::Create( color,
466 fViewMatrix, 487 fViewMatrix,
467 fCurrTexture, 488 fCurrTexture,
468 params, 489 params,
469 flags, 490 flags,
470 opaque)); 491 opaque));
471 #endif 492 #endif
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
732 } 753 }
733 } 754 }
734 755
735 inline void GrDistanceFieldTextContext::finish() { 756 inline void GrDistanceFieldTextContext::finish() {
736 this->flush(); 757 this->flush();
737 fTotalVertexCount = 0; 758 fTotalVertexCount = 0;
738 759
739 GrTextContext::finish(); 760 GrTextContext::finish();
740 } 761 }
741 762
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698