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

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

Issue 1045723010: move Atlas Text Context to its own file (Closed) Base URL: https://skia.googlesource.com/skia.git@bmptext3
Patch Set: rebase 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
« no previous file with comments | « src/gpu/GrAtlasTextContext.h ('k') | src/gpu/GrBitmapTextContext.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2013 Google Inc. 2 * Copyright 2015 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 #include "GrBitmapTextContext.h" 7 #include "GrAtlasTextContext.h"
8 8
9 #include "GrAtlas.h" 9 #include "GrAtlas.h"
10 #include "GrBatch.h" 10 #include "GrBatch.h"
11 #include "GrBatchFontCache.h" 11 #include "GrBatchFontCache.h"
12 #include "GrBatchTarget.h" 12 #include "GrBatchTarget.h"
13 #include "GrDefaultGeoProcFactory.h" 13 #include "GrDefaultGeoProcFactory.h"
14 #include "GrDrawTarget.h" 14 #include "GrDrawTarget.h"
15 #include "GrFontCache.h"
16 #include "GrFontScaler.h" 15 #include "GrFontScaler.h"
17 #include "GrIndexBuffer.h" 16 #include "GrIndexBuffer.h"
18 #include "GrStrokeInfo.h" 17 #include "GrStrokeInfo.h"
19 #include "GrTexturePriv.h" 18 #include "GrTexturePriv.h"
20 19
21 #include "SkAutoKern.h" 20 #include "SkAutoKern.h"
22 #include "SkColorPriv.h" 21 #include "SkColorPriv.h"
23 #include "SkDraw.h" 22 #include "SkDraw.h"
24 #include "SkDrawFilter.h" 23 #include "SkDrawFilter.h"
25 #include "SkDrawProcs.h" 24 #include "SkDrawProcs.h"
26 #include "SkGlyphCache.h" 25 #include "SkGlyphCache.h"
27 #include "SkGpuDevice.h" 26 #include "SkGpuDevice.h"
28 #include "SkGr.h" 27 #include "SkGr.h"
29 #include "SkPath.h" 28 #include "SkPath.h"
30 #include "SkRTConf.h" 29 #include "SkRTConf.h"
31 #include "SkStrokeRec.h" 30 #include "SkStrokeRec.h"
32 #include "SkTextBlob.h" 31 #include "SkTextBlob.h"
33 #include "SkTextMapStateProc.h" 32 #include "SkTextMapStateProc.h"
34 33
35 #include "effects/GrBitmapTextGeoProc.h" 34 #include "effects/GrBitmapTextGeoProc.h"
36 #include "effects/GrSimpleTextureEffect.h" 35 #include "effects/GrSimpleTextureEffect.h"
37 36
38 SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false,
39 "Dump the contents of the font cache before every purge.");
40
41 namespace { 37 namespace {
42 static const size_t kLCDTextVASize = sizeof(SkPoint) + sizeof(SkIPoint16); 38 static const size_t kLCDTextVASize = sizeof(SkPoint) + sizeof(SkIPoint16);
43 39
44 // position + local coord 40 // position + local coord
45 static const size_t kColorTextVASize = sizeof(SkPoint) + sizeof(SkIPoint16); 41 static const size_t kColorTextVASize = sizeof(SkPoint) + sizeof(SkIPoint16);
46 42
47 static const size_t kGrayTextVASize = sizeof(SkPoint) + sizeof(GrColor) + sizeof (SkIPoint16); 43 static const size_t kGrayTextVASize = sizeof(SkPoint) + sizeof(GrColor) + sizeof (SkIPoint16);
48 44
49 static const int kVerticesPerGlyph = 4; 45 static const int kVerticesPerGlyph = 4;
50 static const int kIndicesPerGlyph = 6; 46 static const int kIndicesPerGlyph = 6;
47
48 static size_t get_vertex_stride(GrMaskFormat maskFormat) {
49 switch (maskFormat) {
50 case kA8_GrMaskFormat:
51 return kGrayTextVASize;
52 case kARGB_GrMaskFormat:
53 return kColorTextVASize;
54 default:
55 return kLCDTextVASize;
56 }
57 }
58
51 }; 59 };
52 60
53 // TODO 61 // TODO
54 // More tests 62 // More tests
55 // move to SkCache 63 // move to SkCache
56 // handle textblobs where the whole run is larger than the cache size 64 // handle textblobs where the whole run is larger than the cache size
57 // TODO implement micro speedy hash map for fast refing of glyphs 65 // TODO implement micro speedy hash map for fast refing of glyphs
58 66
59 GrBitmapTextContextB::GrBitmapTextContextB(GrContext* context, 67 GrBitmapTextContextB::GrBitmapTextContextB(GrContext* context,
60 SkGpuDevice* gpuDevice, 68 SkGpuDevice* gpuDevice,
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after
408 416
409 fCurrStrike = NULL; 417 fCurrStrike = NULL;
410 SkDrawCacheProc glyphCacheProc = skPaint.getDrawCacheProc(); 418 SkDrawCacheProc glyphCacheProc = skPaint.getDrawCacheProc();
411 419
412 // Get GrFontScaler from cache 420 // Get GrFontScaler from cache
413 GrFontScaler* fontScaler = GetGrFontScaler(cache); 421 GrFontScaler* fontScaler = GetGrFontScaler(cache);
414 422
415 const char* stop = text + byteLength; 423 const char* stop = text + byteLength;
416 SkTextAlignProc alignProc(skPaint.getTextAlign()); 424 SkTextAlignProc alignProc(skPaint.getTextAlign());
417 SkTextMapStateProc tmsProc(viewMatrix, offset, scalarsPerPosition); 425 SkTextMapStateProc tmsProc(viewMatrix, offset, scalarsPerPosition);
418 SkScalar halfSampleX = 0, halfSampleY = 0;
419 426
420 if (cache->isSubpixel()) { 427 if (cache->isSubpixel()) {
421 // maybe we should skip the rounding if linearText is set 428 // maybe we should skip the rounding if linearText is set
422 SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(viewMatrix); 429 SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(viewMatrix);
423 430
424 SkFixed fxMask = ~0; 431 SkFixed fxMask = ~0;
425 SkFixed fyMask = ~0; 432 SkFixed fyMask = ~0;
433 SkScalar halfSampleX = SkFixedToScalar(SkGlyph::kSubpixelRound);
434 SkScalar halfSampleY = SkFixedToScalar(SkGlyph::kSubpixelRound);
426 if (kX_SkAxisAlignment == baseline) { 435 if (kX_SkAxisAlignment == baseline) {
427 fyMask = 0; 436 fyMask = 0;
428 halfSampleY = SK_ScalarHalf; 437 halfSampleY = SK_ScalarHalf;
429 } else if (kY_SkAxisAlignment == baseline) { 438 } else if (kY_SkAxisAlignment == baseline) {
430 fxMask = 0; 439 fxMask = 0;
431 halfSampleX = SK_ScalarHalf; 440 halfSampleX = SK_ScalarHalf;
432 } 441 }
433 442
434 if (SkPaint::kLeft_Align == skPaint.getTextAlign()) { 443 if (SkPaint::kLeft_Align == skPaint.getTextAlign()) {
435 while (text < stop) { 444 while (text < stop) {
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
543 Sk48Dot16FloorToInt(fy), 552 Sk48Dot16FloorToInt(fy),
544 fontScaler, 553 fontScaler,
545 clipRect); 554 clipRect);
546 } 555 }
547 pos += scalarsPerPosition; 556 pos += scalarsPerPosition;
548 } 557 }
549 } 558 }
550 } 559 }
551 } 560 }
552 561
553 static size_t get_vertex_stride(GrMaskFormat maskFormat) {
554 switch (maskFormat) {
555 case kA8_GrMaskFormat:
556 return kGrayTextVASize;
557 case kARGB_GrMaskFormat:
558 return kColorTextVASize;
559 default:
560 return kLCDTextVASize;
561 }
562 }
563
564 void GrBitmapTextContextB::appendGlyph(BitmapTextBlob* blob, int runIndex, GrGly ph::PackedID packed, 562 void GrBitmapTextContextB::appendGlyph(BitmapTextBlob* blob, int runIndex, GrGly ph::PackedID packed,
565 int vx, int vy, GrFontScaler* scaler, 563 int vx, int vy, GrFontScaler* scaler,
566 const SkIRect& clipRect) { 564 const SkIRect& clipRect) {
567 if (NULL == fCurrStrike) { 565 if (NULL == fCurrStrike) {
568 fCurrStrike = fContext->getBatchFontCache()->getStrike(scaler); 566 fCurrStrike = fContext->getBatchFontCache()->getStrike(scaler);
569 } 567 }
570 568
571 GrGlyph* glyph = fCurrStrike->getGlyph(packed, scaler); 569 GrGlyph* glyph = fCurrStrike->getGlyph(packed, scaler);
572 if (NULL == glyph || glyph->fBounds.isEmpty()) { 570 if (NULL == glyph || glyph->fBounds.isEmpty()) {
573 return; 571 return;
(...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after
1048 for (int i = 0; i < blob->fBigGlyphs.count(); i++) { 1046 for (int i = 0; i < blob->fBigGlyphs.count(); i++) {
1049 BitmapTextBlob::BigGlyph& bigGlyph = blob->fBigGlyphs[i]; 1047 BitmapTextBlob::BigGlyph& bigGlyph = blob->fBigGlyphs[i];
1050 SkMatrix translate; 1048 SkMatrix translate;
1051 translate.setTranslate(SkIntToScalar(bigGlyph.fVx), SkIntToScalar(bigGly ph.fVy)); 1049 translate.setTranslate(SkIntToScalar(bigGlyph.fVx), SkIntToScalar(bigGly ph.fVy));
1052 SkPath tmpPath(bigGlyph.fPath); 1050 SkPath tmpPath(bigGlyph.fPath);
1053 tmpPath.transform(translate); 1051 tmpPath.transform(translate);
1054 GrStrokeInfo strokeInfo(SkStrokeRec::kFill_InitStyle); 1052 GrStrokeInfo strokeInfo(SkStrokeRec::kFill_InitStyle);
1055 fContext->drawPath(rt, clip, paint, SkMatrix::I(), tmpPath, strokeInfo); 1053 fContext->drawPath(rt, clip, paint, SkMatrix::I(), tmpPath, strokeInfo);
1056 } 1054 }
1057 } 1055 }
1058
1059 GrBitmapTextContext::GrBitmapTextContext(GrContext* context,
1060 SkGpuDevice* gpuDevice,
1061 const SkDeviceProperties& properties)
1062 : GrTextContext(context, gpuDevice, properties) {
1063 fStrike = NULL;
1064
1065 fCurrTexture = NULL;
1066 fEffectTextureUniqueID = SK_InvalidUniqueID;
1067
1068 fVertices = NULL;
1069 fCurrVertex = 0;
1070 fAllocVertexCount = 0;
1071 fTotalVertexCount = 0;
1072
1073 fVertexBounds.setLargestInverted();
1074 }
1075
1076 GrBitmapTextContext* GrBitmapTextContext::Create(GrContext* context,
1077 SkGpuDevice* gpuDevice,
1078 const SkDeviceProperties& props ) {
1079 return SkNEW_ARGS(GrBitmapTextContext, (context, gpuDevice, props));
1080 }
1081
1082 bool GrBitmapTextContext::canDraw(const GrRenderTarget* rt,
1083 const GrClip& clip,
1084 const GrPaint& paint,
1085 const SkPaint& skPaint,
1086 const SkMatrix& viewMatrix) {
1087 return !SkDraw::ShouldDrawTextAsPaths(skPaint, viewMatrix);
1088 }
1089
1090 inline void GrBitmapTextContext::init(GrRenderTarget* rt, const GrClip& clip,
1091 const GrPaint& paint, const SkPaint& skPai nt,
1092 const SkIRect& regionClipBounds) {
1093 GrTextContext::init(rt, clip, paint, skPaint, regionClipBounds);
1094
1095 fStrike = NULL;
1096
1097 fCurrTexture = NULL;
1098 fCurrVertex = 0;
1099
1100 fVertices = NULL;
1101 fAllocVertexCount = 0;
1102 fTotalVertexCount = 0;
1103 }
1104
1105 void GrBitmapTextContext::onDrawText(GrRenderTarget* rt, const GrClip& clip,
1106 const GrPaint& paint, const SkPaint& skPain t,
1107 const SkMatrix& viewMatrix,
1108 const char text[], size_t byteLength,
1109 SkScalar x, SkScalar y, const SkIRect& regi onClipBounds) {
1110 SkASSERT(byteLength == 0 || text != NULL);
1111
1112 // nothing to draw
1113 if (text == NULL || byteLength == 0 /*|| fRC->isEmpty()*/) {
1114 return;
1115 }
1116
1117 this->init(rt, clip, paint, skPaint, regionClipBounds);
1118
1119 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
1120
1121 SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, &viewMatrix);
1122 SkGlyphCache* cache = autoCache.getCache();
1123 GrFontScaler* fontScaler = GetGrFontScaler(cache);
1124
1125 // transform our starting point
1126 {
1127 SkPoint loc;
1128 viewMatrix.mapXY(x, y, &loc);
1129 x = loc.fX;
1130 y = loc.fY;
1131 }
1132
1133 // need to measure first
1134 int numGlyphs;
1135 if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) {
1136 SkVector stopVector;
1137 numGlyphs = MeasureText(cache, glyphCacheProc, text, byteLength, &stopVe ctor);
1138
1139 SkScalar stopX = stopVector.fX;
1140 SkScalar stopY = stopVector.fY;
1141
1142 if (fSkPaint.getTextAlign() == SkPaint::kCenter_Align) {
1143 stopX = SkScalarHalf(stopX);
1144 stopY = SkScalarHalf(stopY);
1145 }
1146 x -= stopX;
1147 y -= stopY;
1148 } else {
1149 numGlyphs = fSkPaint.textToGlyphs(text, byteLength, NULL);
1150 }
1151 fTotalVertexCount = kVerticesPerGlyph*numGlyphs;
1152
1153 const char* stop = text + byteLength;
1154
1155 SkAutoKern autokern;
1156
1157 SkFixed fxMask = ~0;
1158 SkFixed fyMask = ~0;
1159 SkScalar halfSampleX, halfSampleY;
1160 if (cache->isSubpixel()) {
1161 halfSampleX = halfSampleY = SkFixedToScalar(SkGlyph::kSubpixelRound);
1162 SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(viewMatrix);
1163 if (kX_SkAxisAlignment == baseline) {
1164 fyMask = 0;
1165 halfSampleY = SK_ScalarHalf;
1166 } else if (kY_SkAxisAlignment == baseline) {
1167 fxMask = 0;
1168 halfSampleX = SK_ScalarHalf;
1169 }
1170 } else {
1171 halfSampleX = halfSampleY = SK_ScalarHalf;
1172 }
1173
1174 Sk48Dot16 fx = SkScalarTo48Dot16(x + halfSampleX);
1175 Sk48Dot16 fy = SkScalarTo48Dot16(y + halfSampleY);
1176
1177 // if we have RGB, then we won't have any SkShaders so no need to use a loca lmatrix, but for
1178 // performance reasons we just invert here instead
1179 if (!viewMatrix.invert(&fLocalMatrix)) {
1180 SkDebugf("Cannot invert viewmatrix\n");
1181 return;
1182 }
1183
1184 while (text < stop) {
1185 const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fy Mask);
1186
1187 fx += autokern.adjust(glyph);
1188
1189 if (glyph.fWidth) {
1190 this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(),
1191 glyph.getSubXFixed(),
1192 glyph.getSubYFixed(),
1193 GrGlyph::kCoverage_MaskStyle),
1194 Sk48Dot16FloorToInt(fx),
1195 Sk48Dot16FloorToInt(fy),
1196 fontScaler);
1197 }
1198
1199 fx += glyph.fAdvanceX;
1200 fy += glyph.fAdvanceY;
1201 }
1202
1203 this->finish();
1204 }
1205
1206 void GrBitmapTextContext::onDrawPosText(GrRenderTarget* rt, const GrClip& clip,
1207 const GrPaint& paint, const SkPaint& skP aint,
1208 const SkMatrix& viewMatrix,
1209 const char text[], size_t byteLength,
1210 const SkScalar pos[], int scalarsPerPosi tion,
1211 const SkPoint& offset, const SkIRect& re gionClipBounds) {
1212 SkASSERT(byteLength == 0 || text != NULL);
1213 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
1214
1215 // nothing to draw
1216 if (text == NULL || byteLength == 0/* || fRC->isEmpty()*/) {
1217 return;
1218 }
1219
1220 this->init(rt, clip, paint, skPaint, regionClipBounds);
1221
1222 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
1223
1224 SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, &viewMatrix);
1225 SkGlyphCache* cache = autoCache.getCache();
1226 GrFontScaler* fontScaler = GetGrFontScaler(cache);
1227
1228 // if we have RGB, then we won't have any SkShaders so no need to use a loca lmatrix, but for
1229 // performance reasons we just invert here instead
1230 if (!viewMatrix.invert(&fLocalMatrix)) {
1231 SkDebugf("Cannot invert viewmatrix\n");
1232 return;
1233 }
1234
1235 int numGlyphs = fSkPaint.textToGlyphs(text, byteLength, NULL);
1236 fTotalVertexCount = kVerticesPerGlyph*numGlyphs;
1237
1238 const char* stop = text + byteLength;
1239 SkTextAlignProc alignProc(fSkPaint.getTextAlign());
1240 SkTextMapStateProc tmsProc(viewMatrix, offset, scalarsPerPosition);
1241
1242 if (cache->isSubpixel()) {
1243 // maybe we should skip the rounding if linearText is set
1244 SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(viewMatrix);
1245
1246 SkFixed fxMask = ~0;
1247 SkFixed fyMask = ~0;
1248 SkScalar halfSampleX = SkFixedToScalar(SkGlyph::kSubpixelRound);
1249 SkScalar halfSampleY = SkFixedToScalar(SkGlyph::kSubpixelRound);
1250 if (kX_SkAxisAlignment == baseline) {
1251 fyMask = 0;
1252 halfSampleY = SK_ScalarHalf;
1253 } else if (kY_SkAxisAlignment == baseline) {
1254 fxMask = 0;
1255 halfSampleX = SK_ScalarHalf;
1256 }
1257
1258 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
1259 while (text < stop) {
1260 SkPoint tmsLoc;
1261 tmsProc(pos, &tmsLoc);
1262 Sk48Dot16 fx = SkScalarTo48Dot16(tmsLoc.fX + halfSampleX);
1263 Sk48Dot16 fy = SkScalarTo48Dot16(tmsLoc.fY + halfSampleY);
1264
1265 const SkGlyph& glyph = glyphCacheProc(cache, &text,
1266 fx & fxMask, fy & fyMask);
1267
1268 if (glyph.fWidth) {
1269 this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(),
1270 glyph.getSubXFixed(),
1271 glyph.getSubYFixed(),
1272 GrGlyph::kCoverage_MaskStyle ),
1273 Sk48Dot16FloorToInt(fx),
1274 Sk48Dot16FloorToInt(fy),
1275 fontScaler);
1276 }
1277 pos += scalarsPerPosition;
1278 }
1279 } else {
1280 while (text < stop) {
1281 const char* currentText = text;
1282 const SkGlyph& metricGlyph = glyphCacheProc(cache, &text, 0, 0);
1283
1284 if (metricGlyph.fWidth) {
1285 SkDEBUGCODE(SkFixed prevAdvX = metricGlyph.fAdvanceX;)
1286 SkDEBUGCODE(SkFixed prevAdvY = metricGlyph.fAdvanceY;)
1287 SkPoint tmsLoc;
1288 tmsProc(pos, &tmsLoc);
1289 SkPoint alignLoc;
1290 alignProc(tmsLoc, metricGlyph, &alignLoc);
1291
1292 Sk48Dot16 fx = SkScalarTo48Dot16(alignLoc.fX + halfSampleX);
1293 Sk48Dot16 fy = SkScalarTo48Dot16(alignLoc.fY + halfSampleY);
1294
1295 // have to call again, now that we've been "aligned"
1296 const SkGlyph& glyph = glyphCacheProc(cache, &currentText,
1297 fx & fxMask, fy & fyMa sk);
1298 // the assumption is that the metrics haven't changed
1299 SkASSERT(prevAdvX == glyph.fAdvanceX);
1300 SkASSERT(prevAdvY == glyph.fAdvanceY);
1301 SkASSERT(glyph.fWidth);
1302
1303 this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(),
1304 glyph.getSubXFixed(),
1305 glyph.getSubYFixed(),
1306 GrGlyph::kCoverage_MaskStyle ),
1307 Sk48Dot16FloorToInt(fx),
1308 Sk48Dot16FloorToInt(fy),
1309 fontScaler);
1310 }
1311 pos += scalarsPerPosition;
1312 }
1313 }
1314 } else { // not subpixel
1315
1316 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
1317 while (text < stop) {
1318 // the last 2 parameters are ignored
1319 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
1320
1321 if (glyph.fWidth) {
1322 SkPoint tmsLoc;
1323 tmsProc(pos, &tmsLoc);
1324
1325 Sk48Dot16 fx = SkScalarTo48Dot16(tmsLoc.fX + SK_ScalarHalf);
1326 Sk48Dot16 fy = SkScalarTo48Dot16(tmsLoc.fY + SK_ScalarHalf);
1327 this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(),
1328 glyph.getSubXFixed(),
1329 glyph.getSubYFixed(),
1330 GrGlyph::kCoverage_MaskStyle ),
1331 Sk48Dot16FloorToInt(fx),
1332 Sk48Dot16FloorToInt(fy),
1333 fontScaler);
1334 }
1335 pos += scalarsPerPosition;
1336 }
1337 } else {
1338 while (text < stop) {
1339 // the last 2 parameters are ignored
1340 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
1341
1342 if (glyph.fWidth) {
1343 SkPoint tmsLoc;
1344 tmsProc(pos, &tmsLoc);
1345
1346 SkPoint alignLoc;
1347 alignProc(tmsLoc, glyph, &alignLoc);
1348
1349 Sk48Dot16 fx = SkScalarTo48Dot16(alignLoc.fX + SK_ScalarHalf );
1350 Sk48Dot16 fy = SkScalarTo48Dot16(alignLoc.fY + SK_ScalarHalf );
1351 this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(),
1352 glyph.getSubXFixed(),
1353 glyph.getSubYFixed(),
1354 GrGlyph::kCoverage_MaskStyle ),
1355 Sk48Dot16FloorToInt(fx),
1356 Sk48Dot16FloorToInt(fy),
1357 fontScaler);
1358 }
1359 pos += scalarsPerPosition;
1360 }
1361 }
1362 }
1363
1364 this->finish();
1365 }
1366
1367 static void* alloc_vertices(GrDrawTarget* drawTarget,
1368 int numVertices,
1369 GrMaskFormat maskFormat) {
1370 if (numVertices <= 0) {
1371 return NULL;
1372 }
1373
1374 // set up attributes
1375 void* vertices = NULL;
1376 bool success = drawTarget->reserveVertexAndIndexSpace(numVertices,
1377 get_vertex_stride(mask Format),
1378 0,
1379 &vertices,
1380 NULL);
1381 GrAlwaysAssert(success);
1382 return vertices;
1383 }
1384
1385 inline bool GrBitmapTextContext::uploadGlyph(GrGlyph* glyph, GrFontScaler* scale r) {
1386 if (!fStrike->glyphTooLargeForAtlas(glyph)) {
1387 if (fStrike->addGlyphToAtlas(glyph, scaler)) {
1388 return true;
1389 }
1390
1391 // try to clear out an unused plot before we flush
1392 if (fContext->getFontCache()->freeUnusedPlot(fStrike, glyph) &&
1393 fStrike->addGlyphToAtlas(glyph, scaler)) {
1394 return true;
1395 }
1396
1397 if (c_DumpFontCache) {
1398 #ifdef SK_DEVELOPER
1399 fContext->getFontCache()->dump();
1400 #endif
1401 }
1402
1403 // before we purge the cache, we must flush any accumulated draws
1404 this->flush();
1405 fContext->flush();
1406
1407 // we should have an unused plot now
1408 if (fContext->getFontCache()->freeUnusedPlot(fStrike, glyph) &&
1409 fStrike->addGlyphToAtlas(glyph, scaler)) {
1410 return true;
1411 }
1412
1413 // we should never get here
1414 SkASSERT(false);
1415 }
1416
1417 return false;
1418 }
1419
1420 void GrBitmapTextContext::appendGlyph(GrGlyph::PackedID packed,
1421 int vx, int vy,
1422 GrFontScaler* scaler) {
1423 if (NULL == fDrawTarget) {
1424 return;
1425 }
1426
1427 if (NULL == fStrike) {
1428 fStrike = fContext->getFontCache()->getStrike(scaler);
1429 }
1430
1431 GrGlyph* glyph = fStrike->getGlyph(packed, scaler);
1432 if (NULL == glyph || glyph->fBounds.isEmpty()) {
1433 return;
1434 }
1435
1436 int x = vx + glyph->fBounds.fLeft;
1437 int y = vy + glyph->fBounds.fTop;
1438
1439 // keep them as ints until we've done the clip-test
1440 int width = glyph->fBounds.width();
1441 int height = glyph->fBounds.height();
1442
1443 // check if we clipped out
1444 if (fClipRect.quickReject(x, y, x + width, y + height)) {
1445 return;
1446 }
1447
1448 // If the glyph is too large we fall back to paths
1449 if (NULL == glyph->fPlot && !uploadGlyph(glyph, scaler)) {
1450 if (NULL == glyph->fPath) {
1451 SkPath* path = SkNEW(SkPath);
1452 if (!scaler->getGlyphPath(glyph->glyphID(), path)) {
1453 // flag the glyph as being dead?
1454 delete path;
1455 return;
1456 }
1457 glyph->fPath = path;
1458 }
1459
1460 // flush any accumulated draws before drawing this glyph as a path.
1461 this->flush();
1462
1463 SkMatrix translate;
1464 translate.setTranslate(SkIntToScalar(vx), SkIntToScalar(vy));
1465 SkPath tmpPath(*glyph->fPath);
1466 tmpPath.transform(translate);
1467 GrStrokeInfo strokeInfo(SkStrokeRec::kFill_InitStyle);
1468 fContext->drawPath(fRenderTarget, fClip, fPaint, SkMatrix::I(), tmpPath, strokeInfo);
1469
1470 // remove this glyph from the vertices we need to allocate
1471 fTotalVertexCount -= kVerticesPerGlyph;
1472 return;
1473 }
1474
1475 SkASSERT(glyph->fPlot);
1476 GrDrawTarget::DrawToken drawToken = fDrawTarget->getCurrentDrawToken();
1477 glyph->fPlot->setDrawToken(drawToken);
1478
1479 // the current texture/maskformat must match what the glyph needs
1480 GrTexture* texture = glyph->fPlot->texture();
1481 SkASSERT(texture);
1482
1483 if (fCurrTexture != texture || fCurrVertex + kVerticesPerGlyph > fAllocVerte xCount) {
1484 this->flush();
1485 fCurrTexture = texture;
1486 fCurrTexture->ref();
1487 fCurrMaskFormat = glyph->fMaskFormat;
1488 }
1489
1490 if (NULL == fVertices) {
1491 int maxQuadVertices = kVerticesPerGlyph * fContext->getQuadIndexBuffer() ->maxQuads();
1492 fAllocVertexCount = SkMin32(fTotalVertexCount, maxQuadVertices);
1493 fVertices = alloc_vertices(fDrawTarget, fAllocVertexCount, fCurrMaskForm at);
1494 }
1495
1496 SkRect r;
1497 r.fLeft = SkIntToScalar(x);
1498 r.fTop = SkIntToScalar(y);
1499 r.fRight = r.fLeft + SkIntToScalar(width);
1500 r.fBottom = r.fTop + SkIntToScalar(height);
1501
1502 fVertexBounds.joinNonEmptyArg(r);
1503
1504 int u0 = glyph->fAtlasLocation.fX;
1505 int v0 = glyph->fAtlasLocation.fY;
1506 int u1 = u0 + width;
1507 int v1 = v0 + height;
1508
1509 size_t vertSize = get_vertex_stride(fCurrMaskFormat);
1510 intptr_t vertex = reinterpret_cast<intptr_t>(fVertices) + vertSize * fCurrVe rtex;
1511
1512 // V0
1513 SkPoint* position = reinterpret_cast<SkPoint*>(vertex);
1514 position->set(r.fLeft, r.fTop);
1515 if (kA8_GrMaskFormat == fCurrMaskFormat) {
1516 SkColor* color = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint));
1517 *color = fPaint.getColor();
1518 }
1519 SkIPoint16* textureCoords = reinterpret_cast<SkIPoint16*>(vertex + vertSize -
1520 sizeof(SkIPoint16) );
1521 textureCoords->set(u0, v0);
1522 vertex += vertSize;
1523
1524 // V1
1525 position = reinterpret_cast<SkPoint*>(vertex);
1526 position->set(r.fLeft, r.fBottom);
1527 if (kA8_GrMaskFormat == fCurrMaskFormat) {
1528 SkColor* color = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint));
1529 *color = fPaint.getColor();
1530 }
1531 textureCoords = reinterpret_cast<SkIPoint16*>(vertex + vertSize - sizeof(Sk IPoint16));
1532 textureCoords->set(u0, v1);
1533 vertex += vertSize;
1534
1535 // V2
1536 position = reinterpret_cast<SkPoint*>(vertex);
1537 position->set(r.fRight, r.fBottom);
1538 if (kA8_GrMaskFormat == fCurrMaskFormat) {
1539 SkColor* color = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint));
1540 *color = fPaint.getColor();
1541 }
1542 textureCoords = reinterpret_cast<SkIPoint16*>(vertex + vertSize - sizeof(Sk IPoint16));
1543 textureCoords->set(u1, v1);
1544 vertex += vertSize;
1545
1546 // V3
1547 position = reinterpret_cast<SkPoint*>(vertex);
1548 position->set(r.fRight, r.fTop);
1549 if (kA8_GrMaskFormat == fCurrMaskFormat) {
1550 SkColor* color = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint));
1551 *color = fPaint.getColor();
1552 }
1553 textureCoords = reinterpret_cast<SkIPoint16*>(vertex + vertSize - sizeof(Sk IPoint16));
1554 textureCoords->set(u1, v0);
1555
1556 fCurrVertex += 4;
1557 }
1558
1559 void GrBitmapTextContext::flush() {
1560 if (NULL == fDrawTarget) {
1561 return;
1562 }
1563
1564 if (fCurrVertex > 0) {
1565 GrPipelineBuilder pipelineBuilder;
1566 pipelineBuilder.setFromPaint(fPaint, fRenderTarget, fClip);
1567
1568 // setup our sampler state for our text texture/atlas
1569 SkASSERT(SkIsAlign4(fCurrVertex));
1570 SkASSERT(fCurrTexture);
1571
1572 SkASSERT(fStrike);
1573 GrColor color = fPaint.getColor();
1574 switch (fCurrMaskFormat) {
1575 // Color bitmap text
1576 case kARGB_GrMaskFormat: {
1577 int a = fSkPaint.getAlpha();
1578 color = SkColorSetARGB(a, a, a, a);
1579 break;
1580 }
1581 // LCD text
1582 case kA565_GrMaskFormat: {
1583 // TODO: move supportsRGBCoverage check to setupCoverageEffect a nd only add LCD
1584 // processor if the xp can support it. For now we will simply as sume that if
1585 // fUseLCDText is true, then we have a known color output.
1586 const GrXPFactory* xpFactory = pipelineBuilder.getXPFactory();
1587 if (!xpFactory->supportsRGBCoverage(0, kRGBA_GrColorComponentFla gs)) {
1588 SkDebugf("LCD Text will not draw correctly.\n");
1589 }
1590 break;
1591 }
1592 // Grayscale/BW text
1593 case kA8_GrMaskFormat:
1594 break;
1595 default:
1596 SkFAIL("Unexpected mask format.");
1597 }
1598
1599 GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kNone _FilterMode);
1600 uint32_t textureUniqueID = fCurrTexture->getUniqueID();
1601 if (textureUniqueID != fEffectTextureUniqueID ||
1602 fCachedGeometryProcessor->color() != color ||
1603 !fCachedGeometryProcessor->localMatrix().cheapEqualTo(fLocalMatrix)) {
1604 // This will be ignored in the non A8 case
1605 bool opaqueVertexColors = GrColorIsOpaque(fPaint.getColor());
1606 fCachedGeometryProcessor.reset(GrBitmapTextGeoProc::Create(color,
1607 fCurrText ure,
1608 params,
1609 fCurrMask Format,
1610 opaqueVer texColors,
1611 fLocalMat rix));
1612 fEffectTextureUniqueID = textureUniqueID;
1613 }
1614
1615 int nGlyphs = fCurrVertex / kVerticesPerGlyph;
1616 fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer());
1617 fDrawTarget->drawIndexedInstances(&pipelineBuilder,
1618 fCachedGeometryProcessor.get(),
1619 kTriangles_GrPrimitiveType,
1620 nGlyphs,
1621 kVerticesPerGlyph,
1622 kIndicesPerGlyph,
1623 &fVertexBounds);
1624
1625 fDrawTarget->resetVertexSource();
1626 fVertices = NULL;
1627 fAllocVertexCount = 0;
1628 // reset to be those that are left
1629 fTotalVertexCount -= fCurrVertex;
1630 fCurrVertex = 0;
1631 fVertexBounds.setLargestInverted();
1632 SkSafeSetNull(fCurrTexture);
1633 }
1634 }
1635
1636 inline void GrBitmapTextContext::finish() {
1637 this->flush();
1638 fTotalVertexCount = 0;
1639
1640 GrTextContext::finish();
1641 }
OLDNEW
« no previous file with comments | « src/gpu/GrAtlasTextContext.h ('k') | src/gpu/GrBitmapTextContext.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698