11d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt/* 21d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt * Copyright 2015 Google Inc. 31d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt * 41d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt * Use of this source code is governed by a BSD-style license that can be 51d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt * found in the LICENSE file. 61d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt */ 71d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt#include "GrAtlasTextContext.h" 81d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 91d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt#include "GrBatch.h" 101d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt#include "GrBatchFontCache.h" 111d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt#include "GrBatchTarget.h" 1279dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt#include "GrBatchTest.h" 131d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt#include "GrDefaultGeoProcFactory.h" 141d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt#include "GrDrawTarget.h" 151d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt#include "GrFontScaler.h" 161d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt#include "GrIndexBuffer.h" 17ed0bcad9c8147fd37c23bdda00ec27ec9ef8d66bbsalomon#include "GrResourceProvider.h" 181d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt#include "GrStrokeInfo.h" 19b7133bed55af8dd4ca9427892bb1a5623dbaccf0joshualitt#include "GrTextBlobCache.h" 201d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt#include "GrTexturePriv.h" 2172e3ae486c66871c2043eac4f08d85d419fbca2absalomon#include "GrVertexBuffer.h" 221d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 231d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt#include "SkAutoKern.h" 241d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt#include "SkColorPriv.h" 259bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt#include "SkColorFilter.h" 269bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt#include "SkDistanceFieldGen.h" 271d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt#include "SkDraw.h" 281d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt#include "SkDrawFilter.h" 291d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt#include "SkDrawProcs.h" 301d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt#include "SkGlyphCache.h" 311d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt#include "SkGpuDevice.h" 321d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt#include "SkGr.h" 331d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt#include "SkPath.h" 341d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt#include "SkRTConf.h" 351d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt#include "SkStrokeRec.h" 361d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt#include "SkTextBlob.h" 371d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt#include "SkTextMapStateProc.h" 381d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 391d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt#include "effects/GrBitmapTextGeoProc.h" 409bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt#include "effects/GrDistanceFieldGeoProc.h" 411d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 421d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualittnamespace { 431d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualittstatic const size_t kLCDTextVASize = sizeof(SkPoint) + sizeof(SkIPoint16); 441d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 451d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt// position + local coord 461d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualittstatic const size_t kColorTextVASize = sizeof(SkPoint) + sizeof(SkIPoint16); 471d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 481d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualittstatic const size_t kGrayTextVASize = sizeof(SkPoint) + sizeof(GrColor) + sizeof(SkIPoint16); 491d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 509bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualittstatic const int kMinDFFontSize = 18; 519bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualittstatic const int kSmallDFFontSize = 32; 529bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualittstatic const int kSmallDFFontLimit = 32; 539bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualittstatic const int kMediumDFFontSize = 72; 549bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualittstatic const int kMediumDFFontLimit = 72; 559bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualittstatic const int kLargeDFFontSize = 162; 56a7c6389ebf19cf58926f7a1616f0e5554c56aa84joshualittstatic const int kLargeDFFontLimit = 2 * kLargeDFFontSize; 579bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 589bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualittSkDEBUGCODE(static const int kExpectedDistanceAdjustTableSize = 8;) 599bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualittstatic const int kDistanceAdjustLumShift = 5; 609bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 611d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualittstatic const int kVerticesPerGlyph = 4; 621d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualittstatic const int kIndicesPerGlyph = 6; 631d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 641d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualittstatic size_t get_vertex_stride(GrMaskFormat maskFormat) { 651d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt switch (maskFormat) { 661d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt case kA8_GrMaskFormat: 671d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt return kGrayTextVASize; 681d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt case kARGB_GrMaskFormat: 691d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt return kColorTextVASize; 701d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt default: 711d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt return kLCDTextVASize; 721d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 731d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt} 741d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 759bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualittstatic size_t get_vertex_stride_df(GrMaskFormat maskFormat, bool useLCDText) { 769bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkASSERT(maskFormat == kA8_GrMaskFormat); 779bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (useLCDText) { 789bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt return kLCDTextVASize; 799bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } else { 809bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt return kGrayTextVASize; 819bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 829bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt} 839bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 849bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualittstatic inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) { 859bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt unsigned r = SkColorGetR(c); 869bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt unsigned g = SkColorGetG(c); 879bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt unsigned b = SkColorGetB(c); 889bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt return GrColorPackRGBA(r, g, b, 0xff); 899bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt} 909bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 911d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt}; 921d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 931d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt// TODO 949bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt// Distance field text in textblobs 951d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 96dbd3593e0b0cfb04f23b9d7bce623e6e32364b3fjoshualittGrAtlasTextContext::GrAtlasTextContext(GrContext* context, 97dbd3593e0b0cfb04f23b9d7bce623e6e32364b3fjoshualitt SkGpuDevice* gpuDevice, 989bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt const SkDeviceProperties& properties, 999bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt bool enableDistanceFields) 1009bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt : INHERITED(context, gpuDevice, properties) 1019bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt , fDistanceAdjustTable(SkNEW_ARGS(DistanceAdjustTable, (properties.gamma()))) { 102b7133bed55af8dd4ca9427892bb1a5623dbaccf0joshualitt // We overallocate vertices in our textblobs based on the assumption that A8 has the greatest 103b7133bed55af8dd4ca9427892bb1a5623dbaccf0joshualitt // vertexStride 104b7133bed55af8dd4ca9427892bb1a5623dbaccf0joshualitt SK_COMPILE_ASSERT(kGrayTextVASize >= kColorTextVASize && kGrayTextVASize >= kLCDTextVASize, 105b7133bed55af8dd4ca9427892bb1a5623dbaccf0joshualitt vertex_attribute_changed); 1061d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt fCurrStrike = NULL; 107b7133bed55af8dd4ca9427892bb1a5623dbaccf0joshualitt fCache = context->getTextBlobCache(); 1089bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 1099bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt#if SK_FORCE_DISTANCE_FIELD_TEXT 1109bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt fEnableDFRendering = true; 1119bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt#else 1129bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt fEnableDFRendering = enableDistanceFields; 1139bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt#endif 1149bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt} 1159bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 1169bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualittvoid GrAtlasTextContext::DistanceAdjustTable::buildDistanceAdjustTable(float gamma) { 1179bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 1189bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // This is used for an approximation of the mask gamma hack, used by raster and bitmap 1199bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // text. The mask gamma hack is based off of guessing what the blend color is going to 1209bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // be, and adjusting the mask so that when run through the linear blend will 1219bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // produce the value closest to the desired result. However, in practice this means 1229bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // that the 'adjusted' mask is just increasing or decreasing the coverage of 1239bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // the mask depending on what it is thought it will blit against. For black (on 1249bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // assumed white) this means that coverages are decreased (on a curve). For white (on 1259bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // assumed black) this means that coverages are increased (on a a curve). At 1269bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // middle (perceptual) gray (which could be blit against anything) the coverages 1279bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // remain the same. 1289bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // 1299bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // The idea here is that instead of determining the initial (real) coverage and 1309bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // then adjusting that coverage, we determine an adjusted coverage directly by 1319bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // essentially manipulating the geometry (in this case, the distance to the glyph 1329bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // edge). So for black (on assumed white) this thins a bit; for white (on 1339bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // assumed black) this fake bolds the geometry a bit. 1349bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // 1359bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // The distance adjustment is calculated by determining the actual coverage value which 1369bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // when fed into in the mask gamma table gives us an 'adjusted coverage' value of 0.5. This 1379bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // actual coverage value (assuming it's between 0 and 1) corresponds to a distance from the 1389bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // actual edge. So by subtracting this distance adjustment and computing without the 1399bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // the coverage adjustment we should get 0.5 coverage at the same point. 1409bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // 1419bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // This has several implications: 1429bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // For non-gray lcd smoothed text, each subpixel essentially is using a 1439bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // slightly different geometry. 1449bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // 1459bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // For black (on assumed white) this may not cover some pixels which were 1469bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // previously covered; however those pixels would have been only slightly 1479bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // covered and that slight coverage would have been decreased anyway. Also, some pixels 1489bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // which were previously fully covered may no longer be fully covered. 1499bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // 1509bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // For white (on assumed black) this may cover some pixels which weren't 1519bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // previously covered at all. 1529bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 1539bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt int width, height; 1549bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt size_t size; 1559bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 1569bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt#ifdef SK_GAMMA_CONTRAST 1579bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkScalar contrast = SK_GAMMA_CONTRAST; 1589bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt#else 1599bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkScalar contrast = 0.5f; 1609bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt#endif 1619bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkScalar paintGamma = gamma; 1629bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkScalar deviceGamma = gamma; 1639bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 1649bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt size = SkScalerContext::GetGammaLUTSize(contrast, paintGamma, deviceGamma, 1659bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt &width, &height); 1669bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 1679bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkASSERT(kExpectedDistanceAdjustTableSize == height); 1689bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt fTable = SkNEW_ARRAY(SkScalar, height); 1699bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 1709bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkAutoTArray<uint8_t> data((int)size); 1719bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkScalerContext::GetGammaLUTData(contrast, paintGamma, deviceGamma, data.get()); 1729bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 1739bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // find the inverse points where we cross 0.5 1749bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // binsearch might be better, but we only need to do this once on creation 1759bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt for (int row = 0; row < height; ++row) { 1769bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt uint8_t* rowPtr = data.get() + row*width; 1779bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt for (int col = 0; col < width - 1; ++col) { 1789bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (rowPtr[col] <= 127 && rowPtr[col + 1] >= 128) { 1799bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // compute point where a mask value will give us a result of 0.5 1809bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt float interp = (127.5f - rowPtr[col]) / (rowPtr[col + 1] - rowPtr[col]); 1819bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt float borderAlpha = (col + interp) / 255.f; 1829bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 1839bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // compute t value for that alpha 1849bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // this is an approximate inverse for smoothstep() 1859bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt float t = borderAlpha*(borderAlpha*(4.0f*borderAlpha - 6.0f) + 5.0f) / 3.0f; 1869bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 1879bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // compute distance which gives us that t value 1889bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt const float kDistanceFieldAAFactor = 0.65f; // should match SK_DistanceFieldAAFactor 1899bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt float d = 2.0f*kDistanceFieldAAFactor*t - kDistanceFieldAAFactor; 1909bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 1919bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt fTable[row] = d; 1929bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt break; 1939bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 1949bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 1959bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 1961d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt} 1971d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 198dbd3593e0b0cfb04f23b9d7bce623e6e32364b3fjoshualittGrAtlasTextContext* GrAtlasTextContext::Create(GrContext* context, 199dbd3593e0b0cfb04f23b9d7bce623e6e32364b3fjoshualitt SkGpuDevice* gpuDevice, 2009bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt const SkDeviceProperties& props, 2019bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt bool enableDistanceFields) { 2029bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt return SkNEW_ARGS(GrAtlasTextContext, (context, gpuDevice, props, enableDistanceFields)); 2031d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt} 2041d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 205dbd3593e0b0cfb04f23b9d7bce623e6e32364b3fjoshualittbool GrAtlasTextContext::canDraw(const GrRenderTarget*, 206dbd3593e0b0cfb04f23b9d7bce623e6e32364b3fjoshualitt const GrClip&, 207dbd3593e0b0cfb04f23b9d7bce623e6e32364b3fjoshualitt const GrPaint&, 208dbd3593e0b0cfb04f23b9d7bce623e6e32364b3fjoshualitt const SkPaint& skPaint, 209dbd3593e0b0cfb04f23b9d7bce623e6e32364b3fjoshualitt const SkMatrix& viewMatrix) { 2109bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt return this->canDrawAsDistanceFields(skPaint, viewMatrix) || 2119bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt !SkDraw::ShouldDrawTextAsPaths(skPaint, viewMatrix); 2121d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt} 2131d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 2149e36c1a9306f052331550dab4728b9875127bfb5joshualittGrColor GrAtlasTextContext::ComputeCanonicalColor(const SkPaint& paint, bool lcd) { 2159e36c1a9306f052331550dab4728b9875127bfb5joshualitt GrColor canonicalColor = paint.computeLuminanceColor(); 2169e36c1a9306f052331550dab4728b9875127bfb5joshualitt if (lcd) { 2179e36c1a9306f052331550dab4728b9875127bfb5joshualitt // This is the correct computation, but there are tons of cases where LCD can be overridden. 2189e36c1a9306f052331550dab4728b9875127bfb5joshualitt // For now we just regenerate if any run in a textblob has LCD. 2199e36c1a9306f052331550dab4728b9875127bfb5joshualitt // TODO figure out where all of these overrides are and see if we can incorporate that logic 2209e36c1a9306f052331550dab4728b9875127bfb5joshualitt // at a higher level *OR* use sRGB 2219e36c1a9306f052331550dab4728b9875127bfb5joshualitt SkASSERT(false); 2229e36c1a9306f052331550dab4728b9875127bfb5joshualitt //canonicalColor = SkMaskGamma::CanonicalColor(canonicalColor); 2239e36c1a9306f052331550dab4728b9875127bfb5joshualitt } else { 2249e36c1a9306f052331550dab4728b9875127bfb5joshualitt // A8, though can have mixed BMP text but it shouldn't matter because BMP text won't have 2259e36c1a9306f052331550dab4728b9875127bfb5joshualitt // gamma corrected masks anyways, nor color 2269e36c1a9306f052331550dab4728b9875127bfb5joshualitt U8CPU lum = SkComputeLuminance(SkColorGetR(canonicalColor), 2279e36c1a9306f052331550dab4728b9875127bfb5joshualitt SkColorGetG(canonicalColor), 2289e36c1a9306f052331550dab4728b9875127bfb5joshualitt SkColorGetB(canonicalColor)); 2299e36c1a9306f052331550dab4728b9875127bfb5joshualitt // reduce to our finite number of bits 2309e36c1a9306f052331550dab4728b9875127bfb5joshualitt canonicalColor = SkMaskGamma::CanonicalColor(SkColorSetRGB(lum, lum, lum)); 2319e36c1a9306f052331550dab4728b9875127bfb5joshualitt } 2329e36c1a9306f052331550dab4728b9875127bfb5joshualitt return canonicalColor; 2339e36c1a9306f052331550dab4728b9875127bfb5joshualitt} 2349e36c1a9306f052331550dab4728b9875127bfb5joshualitt 2359e36c1a9306f052331550dab4728b9875127bfb5joshualitt// TODO if this function ever shows up in profiling, then we can compute this value when the 2369e36c1a9306f052331550dab4728b9875127bfb5joshualitt// textblob is being built and cache it. However, for the time being textblobs mostly only have 1 2379e36c1a9306f052331550dab4728b9875127bfb5joshualitt// run so this is not a big deal to compute here. 2389e36c1a9306f052331550dab4728b9875127bfb5joshualittbool GrAtlasTextContext::HasLCD(const SkTextBlob* blob) { 2399e36c1a9306f052331550dab4728b9875127bfb5joshualitt SkTextBlob::RunIterator it(blob); 2409e36c1a9306f052331550dab4728b9875127bfb5joshualitt for (; !it.done(); it.next()) { 2419e36c1a9306f052331550dab4728b9875127bfb5joshualitt if (it.isLCD()) { 2429e36c1a9306f052331550dab4728b9875127bfb5joshualitt return true; 2439e36c1a9306f052331550dab4728b9875127bfb5joshualitt } 2449e36c1a9306f052331550dab4728b9875127bfb5joshualitt } 2459e36c1a9306f052331550dab4728b9875127bfb5joshualitt return false; 2469e36c1a9306f052331550dab4728b9875127bfb5joshualitt} 2479e36c1a9306f052331550dab4728b9875127bfb5joshualitt 2482a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualittbool GrAtlasTextContext::MustRegenerateBlob(SkScalar* outTransX, SkScalar* outTransY, 2492a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt const BitmapTextBlob& blob, const SkPaint& paint, 25053b5f4488b05c40254b24c718c2df9724a13c54ajoshualitt const SkMaskFilter::BlurRec& blurRec, 251dbd3593e0b0cfb04f23b9d7bce623e6e32364b3fjoshualitt const SkMatrix& viewMatrix, SkScalar x, SkScalar y) { 2529e36c1a9306f052331550dab4728b9875127bfb5joshualitt // If we have LCD text then our canonical color will be set to transparent, in this case we have 2539e36c1a9306f052331550dab4728b9875127bfb5joshualitt // to regenerate the blob on any color change 2549e36c1a9306f052331550dab4728b9875127bfb5joshualitt if (blob.fKey.fCanonicalColor == SK_ColorTRANSPARENT && blob.fPaintColor != paint.getColor()) { 2552a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt return true; 2562a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt } 2572a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt 2582a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt if (blob.fViewMatrix.hasPerspective() != viewMatrix.hasPerspective()) { 2592a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt return true; 2602a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt } 2612a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt 2622a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt if (blob.fViewMatrix.hasPerspective() && !blob.fViewMatrix.cheapEqualTo(viewMatrix)) { 2632a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt return true; 2642a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt } 2652a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt 26653b5f4488b05c40254b24c718c2df9724a13c54ajoshualitt // We only cache one masked version 26753b5f4488b05c40254b24c718c2df9724a13c54ajoshualitt if (blob.fKey.fHasBlur && 26853b5f4488b05c40254b24c718c2df9724a13c54ajoshualitt (blob.fBlurRec.fSigma != blurRec.fSigma || 26953b5f4488b05c40254b24c718c2df9724a13c54ajoshualitt blob.fBlurRec.fStyle != blurRec.fStyle || 27053b5f4488b05c40254b24c718c2df9724a13c54ajoshualitt blob.fBlurRec.fQuality != blurRec.fQuality)) { 27153b5f4488b05c40254b24c718c2df9724a13c54ajoshualitt return true; 27253b5f4488b05c40254b24c718c2df9724a13c54ajoshualitt } 27353b5f4488b05c40254b24c718c2df9724a13c54ajoshualitt 27453b5f4488b05c40254b24c718c2df9724a13c54ajoshualitt // Similarly, we only cache one version for each style 27553b5f4488b05c40254b24c718c2df9724a13c54ajoshualitt if (blob.fKey.fStyle != SkPaint::kFill_Style && 27653b5f4488b05c40254b24c718c2df9724a13c54ajoshualitt (blob.fStrokeInfo.fFrameWidth != paint.getStrokeWidth() || 27753b5f4488b05c40254b24c718c2df9724a13c54ajoshualitt blob.fStrokeInfo.fMiterLimit != paint.getStrokeMiter() || 27853b5f4488b05c40254b24c718c2df9724a13c54ajoshualitt blob.fStrokeInfo.fJoin != paint.getStrokeJoin())) { 27953b5f4488b05c40254b24c718c2df9724a13c54ajoshualitt return true; 28053b5f4488b05c40254b24c718c2df9724a13c54ajoshualitt } 28153b5f4488b05c40254b24c718c2df9724a13c54ajoshualitt 282fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt // Mixed blobs must be regenerated. We could probably figure out a way to do integer scrolls 283fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt // for mixed blobs if this becomes an issue. 284fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt if (blob.hasBitmap() && blob.hasDistanceField()) { 285473ffa179a8b10655fc0d38b3f4d7205de47cd81joshualitt // Identical viewmatrices and we can reuse in all cases 286473ffa179a8b10655fc0d38b3f4d7205de47cd81joshualitt if (blob.fViewMatrix.cheapEqualTo(viewMatrix) && x == blob.fX && y == blob.fY) { 287473ffa179a8b10655fc0d38b3f4d7205de47cd81joshualitt return false; 288473ffa179a8b10655fc0d38b3f4d7205de47cd81joshualitt } 2892a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt return true; 2902a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt } 2912a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt 292fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt if (blob.hasBitmap()) { 29364c99cc90e678feba473d38db420d31883cc53e6joshualitt if (blob.fViewMatrix.getScaleX() != viewMatrix.getScaleX() || 29464c99cc90e678feba473d38db420d31883cc53e6joshualitt blob.fViewMatrix.getScaleY() != viewMatrix.getScaleY() || 29564c99cc90e678feba473d38db420d31883cc53e6joshualitt blob.fViewMatrix.getSkewX() != viewMatrix.getSkewX() || 29664c99cc90e678feba473d38db420d31883cc53e6joshualitt blob.fViewMatrix.getSkewY() != viewMatrix.getSkewY()) { 29764c99cc90e678feba473d38db420d31883cc53e6joshualitt return true; 29864c99cc90e678feba473d38db420d31883cc53e6joshualitt } 29964c99cc90e678feba473d38db420d31883cc53e6joshualitt 300fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt // We can update the positions in the cachedtextblobs without regenerating the whole blob, 301fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt // but only for integer translations. 302fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt // This cool bit of math will determine the necessary translation to apply to the already 303fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt // generated vertex coordinates to move them to the correct position 304fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt SkScalar transX = viewMatrix.getTranslateX() + 305fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt viewMatrix.getScaleX() * (x - blob.fX) + 306fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt viewMatrix.getSkewX() * (y - blob.fY) - 307fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt blob.fViewMatrix.getTranslateX(); 308fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt SkScalar transY = viewMatrix.getTranslateY() + 309fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt viewMatrix.getSkewY() * (x - blob.fX) + 310fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt viewMatrix.getScaleY() * (y - blob.fY) - 311fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt blob.fViewMatrix.getTranslateY(); 312f0c000df552a3ab51da6cd4997f5878825dec97ejoshualitt if (!SkScalarIsInt(transX) || !SkScalarIsInt(transY) ) { 313fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt return true; 314fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt } 315fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt 316fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt (*outTransX) = transX; 317fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt (*outTransY) = transY; 318a7c6389ebf19cf58926f7a1616f0e5554c56aa84joshualitt } else if (blob.hasDistanceField()) { 31964c99cc90e678feba473d38db420d31883cc53e6joshualitt // A scale outside of [blob.fMaxMinScale, blob.fMinMaxScale] would result in a different 32064c99cc90e678feba473d38db420d31883cc53e6joshualitt // distance field being generated, so we have to regenerate in those cases 32164c99cc90e678feba473d38db420d31883cc53e6joshualitt SkScalar newMaxScale = viewMatrix.getMaxScale(); 32264c99cc90e678feba473d38db420d31883cc53e6joshualitt SkScalar oldMaxScale = blob.fViewMatrix.getMaxScale(); 32364c99cc90e678feba473d38db420d31883cc53e6joshualitt SkScalar scaleAdjust = newMaxScale / oldMaxScale; 32464c99cc90e678feba473d38db420d31883cc53e6joshualitt if (scaleAdjust < blob.fMaxMinScale || scaleAdjust > blob.fMinMaxScale) { 32564c99cc90e678feba473d38db420d31883cc53e6joshualitt return true; 32664c99cc90e678feba473d38db420d31883cc53e6joshualitt } 32764c99cc90e678feba473d38db420d31883cc53e6joshualitt 32864c99cc90e678feba473d38db420d31883cc53e6joshualitt (*outTransX) = x - blob.fX; 32964c99cc90e678feba473d38db420d31883cc53e6joshualitt (*outTransY) = y - blob.fY; 330fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt } 331a7c6389ebf19cf58926f7a1616f0e5554c56aa84joshualitt // It is possible that a blob has neither distanceField nor bitmaptext. This is in the case 332a7c6389ebf19cf58926f7a1616f0e5554c56aa84joshualitt // when all of the runs inside the blob are drawn as paths. In this case, we always regenerate 333a7c6389ebf19cf58926f7a1616f0e5554c56aa84joshualitt // the blob anyways at flush time, so no need to regenerate explicitly 334fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt 3352a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt return false; 3361d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt} 3371d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 3381d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 339dbd3593e0b0cfb04f23b9d7bce623e6e32364b3fjoshualittinline SkGlyphCache* GrAtlasTextContext::setupCache(BitmapTextBlob::Run* run, 340dbd3593e0b0cfb04f23b9d7bce623e6e32364b3fjoshualitt const SkPaint& skPaint, 3419bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt const SkMatrix* viewMatrix, 3429bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt bool noGamma) { 3439bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt skPaint.getScalerContextDescriptor(&run->fDescriptor, &fDeviceProperties, viewMatrix, noGamma); 3441d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt run->fTypeface.reset(SkSafeRef(skPaint.getTypeface())); 3451d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt return SkGlyphCache::DetachCache(run->fTypeface, run->fDescriptor.getDesc()); 3461d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt} 3471d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 348dbd3593e0b0cfb04f23b9d7bce623e6e32364b3fjoshualittvoid GrAtlasTextContext::drawTextBlob(GrRenderTarget* rt, const GrClip& clip, 349dbd3593e0b0cfb04f23b9d7bce623e6e32364b3fjoshualitt const SkPaint& skPaint, const SkMatrix& viewMatrix, 350dbd3593e0b0cfb04f23b9d7bce623e6e32364b3fjoshualitt const SkTextBlob* blob, SkScalar x, SkScalar y, 351dbd3593e0b0cfb04f23b9d7bce623e6e32364b3fjoshualitt SkDrawFilter* drawFilter, const SkIRect& clipBounds) { 3529b8e79eca281e62c954ae875cf99df77b94b4bbbjoshualitt // If we have been abandoned, then don't draw 3539b8e79eca281e62c954ae875cf99df77b94b4bbbjoshualitt if (!fContext->getTextTarget()) { 3549b8e79eca281e62c954ae875cf99df77b94b4bbbjoshualitt return; 3559b8e79eca281e62c954ae875cf99df77b94b4bbbjoshualitt } 3569b8e79eca281e62c954ae875cf99df77b94b4bbbjoshualitt 3572a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt SkAutoTUnref<BitmapTextBlob> cacheBlob; 35853b5f4488b05c40254b24c718c2df9724a13c54ajoshualitt SkMaskFilter::BlurRec blurRec; 35953b5f4488b05c40254b24c718c2df9724a13c54ajoshualitt BitmapTextBlob::Key key; 36053b5f4488b05c40254b24c718c2df9724a13c54ajoshualitt // It might be worth caching these things, but its not clear at this time 36153b5f4488b05c40254b24c718c2df9724a13c54ajoshualitt // TODO for animated mask filters, this will fill up our cache. We need a safeguard here 36253b5f4488b05c40254b24c718c2df9724a13c54ajoshualitt const SkMaskFilter* mf = skPaint.getMaskFilter(); 3632a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt bool canCache = !(skPaint.getPathEffect() || 36453b5f4488b05c40254b24c718c2df9724a13c54ajoshualitt (mf && !mf->asABlur(&blurRec)) || 3652a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt drawFilter); 3662a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt 3672a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt if (canCache) { 3689e36c1a9306f052331550dab4728b9875127bfb5joshualitt bool hasLCD = HasLCD(blob); 369e4cee1f283c435618343f0c7b298207d5a9a3e1cjoshualitt 370e4cee1f283c435618343f0c7b298207d5a9a3e1cjoshualitt // We canonicalize all non-lcd draws to use kUnknown_SkPixelGeometry 371e4cee1f283c435618343f0c7b298207d5a9a3e1cjoshualitt SkPixelGeometry pixelGeometry = hasLCD ? fDeviceProperties.pixelGeometry() : 372e4cee1f283c435618343f0c7b298207d5a9a3e1cjoshualitt kUnknown_SkPixelGeometry; 373e4cee1f283c435618343f0c7b298207d5a9a3e1cjoshualitt 3749e36c1a9306f052331550dab4728b9875127bfb5joshualitt // TODO we want to figure out a way to be able to use the canonical color on LCD text, 3759e36c1a9306f052331550dab4728b9875127bfb5joshualitt // see the note on ComputeCanonicalColor above. We pick a dummy value for LCD text to 3769e36c1a9306f052331550dab4728b9875127bfb5joshualitt // ensure we always match the same key 3779e36c1a9306f052331550dab4728b9875127bfb5joshualitt GrColor canonicalColor = hasLCD ? SK_ColorTRANSPARENT : 3789e36c1a9306f052331550dab4728b9875127bfb5joshualitt ComputeCanonicalColor(skPaint, hasLCD); 3799e36c1a9306f052331550dab4728b9875127bfb5joshualitt 380e4cee1f283c435618343f0c7b298207d5a9a3e1cjoshualitt key.fPixelGeometry = pixelGeometry; 38153b5f4488b05c40254b24c718c2df9724a13c54ajoshualitt key.fUniqueID = blob->uniqueID(); 38253b5f4488b05c40254b24c718c2df9724a13c54ajoshualitt key.fStyle = skPaint.getStyle(); 38353b5f4488b05c40254b24c718c2df9724a13c54ajoshualitt key.fHasBlur = SkToBool(mf); 3849e36c1a9306f052331550dab4728b9875127bfb5joshualitt key.fCanonicalColor = canonicalColor; 38553b5f4488b05c40254b24c718c2df9724a13c54ajoshualitt cacheBlob.reset(SkSafeRef(fCache->find(key))); 3862a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt } 3872a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt 3881d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkIRect clipRect; 3891d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt clip.getConservativeBounds(rt->width(), rt->height(), &clipRect); 3901d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 3912a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt SkScalar transX = 0.f; 3922a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt SkScalar transY = 0.f; 3932a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt 3949e36c1a9306f052331550dab4728b9875127bfb5joshualitt // Though for the time being runs in the textblob can override the paint, they only touch font 3959e36c1a9306f052331550dab4728b9875127bfb5joshualitt // info. 3969e36c1a9306f052331550dab4728b9875127bfb5joshualitt GrPaint grPaint; 397bed83a66f5fa5821a3a08da32157a6155960b15ebsalomon if (!SkPaint2GrPaint(fContext, rt, skPaint, viewMatrix, true, &grPaint)) { 398bed83a66f5fa5821a3a08da32157a6155960b15ebsalomon return; 399bed83a66f5fa5821a3a08da32157a6155960b15ebsalomon } 4009e36c1a9306f052331550dab4728b9875127bfb5joshualitt 401b7133bed55af8dd4ca9427892bb1a5623dbaccf0joshualitt if (cacheBlob) { 40253b5f4488b05c40254b24c718c2df9724a13c54ajoshualitt if (MustRegenerateBlob(&transX, &transY, *cacheBlob, skPaint, blurRec, viewMatrix, x, y)) { 4031d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // We have to remake the blob because changes may invalidate our masks. 4041d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // TODO we could probably get away reuse most of the time if the pointer is unique, 4051d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // but we'd have to clear the subrun information 406b7133bed55af8dd4ca9427892bb1a5623dbaccf0joshualitt fCache->remove(cacheBlob); 40753b5f4488b05c40254b24c718c2df9724a13c54ajoshualitt cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, key, blurRec, skPaint, 40853b5f4488b05c40254b24c718c2df9724a13c54ajoshualitt kGrayTextVASize))); 4099e36c1a9306f052331550dab4728b9875127bfb5joshualitt this->regenerateTextBlob(cacheBlob, skPaint, grPaint.getColor(), viewMatrix, blob, x, y, 410fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt drawFilter, clipRect, rt, clip, grPaint); 411b7133bed55af8dd4ca9427892bb1a5623dbaccf0joshualitt } else { 4129e36c1a9306f052331550dab4728b9875127bfb5joshualitt // If we can reuse the blob, then make sure we update the blob's viewmatrix, and x/y 4139e36c1a9306f052331550dab4728b9875127bfb5joshualitt // offsets 4142a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt cacheBlob->fViewMatrix = viewMatrix; 4152a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt cacheBlob->fX = x; 4162a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt cacheBlob->fY = y; 417b7133bed55af8dd4ca9427892bb1a5623dbaccf0joshualitt fCache->makeMRU(cacheBlob); 4181d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 4191d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } else { 4202a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt if (canCache) { 42153b5f4488b05c40254b24c718c2df9724a13c54ajoshualitt cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, key, blurRec, skPaint, 42253b5f4488b05c40254b24c718c2df9724a13c54ajoshualitt kGrayTextVASize))); 4232a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt } else { 4242a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt cacheBlob.reset(fCache->createBlob(blob, kGrayTextVASize)); 4252a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt } 4269e36c1a9306f052331550dab4728b9875127bfb5joshualitt this->regenerateTextBlob(cacheBlob, skPaint, grPaint.getColor(), viewMatrix, blob, x, y, 427fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt drawFilter, clipRect, rt, clip, grPaint); 4281d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 4291d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 4309e36c1a9306f052331550dab4728b9875127bfb5joshualitt cacheBlob->fPaintColor = skPaint.getColor(); 4319a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt this->flush(fContext->getTextTarget(), blob, cacheBlob, rt, skPaint, grPaint, drawFilter, 4322a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt clip, viewMatrix, clipBounds, x, y, transX, transY); 4331d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt} 4341d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 4359bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualittinline bool GrAtlasTextContext::canDrawAsDistanceFields(const SkPaint& skPaint, 4369bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt const SkMatrix& viewMatrix) { 4379bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // TODO: support perspective (need getMaxScale replacement) 4389bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (viewMatrix.hasPerspective()) { 4399bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt return false; 4409bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 4419bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 4429bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkScalar maxScale = viewMatrix.getMaxScale(); 4439bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkScalar scaledTextSize = maxScale*skPaint.getTextSize(); 4449bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // Hinted text looks far better at small resolutions 4459bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // Scaling up beyond 2x yields undesireable artifacts 446a7c6389ebf19cf58926f7a1616f0e5554c56aa84joshualitt if (scaledTextSize < kMinDFFontSize || scaledTextSize > kLargeDFFontLimit) { 4479bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt return false; 4489bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 4499bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 4509bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (!fEnableDFRendering && !skPaint.isDistanceFieldTextTEMP() && 4519bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt scaledTextSize < kLargeDFFontSize) { 4529bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt return false; 4539bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 4549bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 4559bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // rasterizers and mask filters modify alpha, which doesn't 4569bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // translate well to distance 4579bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (skPaint.getRasterizer() || skPaint.getMaskFilter() || 458e9c0fc616d2a1632c285885b9b656b68ca8d4f24jvanverth !fContext->getTextTarget()->caps()->shaderCaps()->shaderDerivativeSupport()) { 4599bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt return false; 4609bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 4619bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 4629bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // TODO: add some stroking support 4639bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (skPaint.getStyle() != SkPaint::kFill_Style) { 4649bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt return false; 4659bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 4669bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 4679bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt return true; 4689bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt} 4699bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 470dbd3593e0b0cfb04f23b9d7bce623e6e32364b3fjoshualittvoid GrAtlasTextContext::regenerateTextBlob(BitmapTextBlob* cacheBlob, 4719e36c1a9306f052331550dab4728b9875127bfb5joshualitt const SkPaint& skPaint, GrColor color, 4729e36c1a9306f052331550dab4728b9875127bfb5joshualitt const SkMatrix& viewMatrix, 473dbd3593e0b0cfb04f23b9d7bce623e6e32364b3fjoshualitt const SkTextBlob* blob, SkScalar x, SkScalar y, 474fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt SkDrawFilter* drawFilter, const SkIRect& clipRect, 475fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt GrRenderTarget* rt, const GrClip& clip, 476fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt const GrPaint& paint) { 4771d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt cacheBlob->fViewMatrix = viewMatrix; 4781d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt cacheBlob->fX = x; 4791d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt cacheBlob->fY = y; 4801d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 4811d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // Regenerate textblob 4821d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkPaint runPaint = skPaint; 4831d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkTextBlob::RunIterator it(blob); 4841d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt for (int run = 0; !it.done(); it.next(), run++) { 4851d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt int glyphCount = it.glyphCount(); 4861d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt size_t textLen = glyphCount * sizeof(uint16_t); 4871d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt const SkPoint& offset = it.offset(); 4881d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // applyFontToPaint() always overwrites the exact same attributes, 4891d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // so it is safe to not re-seed the paint for this reason. 4901d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt it.applyFontToPaint(&runPaint); 4911d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 4921d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt if (drawFilter && !drawFilter->filter(&runPaint, SkDrawFilter::kText_Type)) { 4931d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // A false return from filter() means we should abort the current draw. 4941d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt runPaint = skPaint; 4951d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt continue; 4961d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 4971d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 4981d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt runPaint.setFlags(fGpuDevice->filterTextFlags(runPaint)); 4991d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 5001d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // setup vertex / glyphIndex for the new run 5011d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt if (run > 0) { 5021d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt PerSubRunInfo& newRun = cacheBlob->fRuns[run].fSubRunInfo.back(); 5031d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt PerSubRunInfo& lastRun = cacheBlob->fRuns[run - 1].fSubRunInfo.back(); 5041d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 5051d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt newRun.fVertexStartIndex = lastRun.fVertexEndIndex; 5061d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt newRun.fVertexEndIndex = lastRun.fVertexEndIndex; 5071d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 5081d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt newRun.fGlyphStartIndex = lastRun.fGlyphEndIndex; 5091d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt newRun.fGlyphEndIndex = lastRun.fGlyphEndIndex; 5101d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 5111d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 512fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt if (this->canDrawAsDistanceFields(runPaint, viewMatrix)) { 513fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt cacheBlob->setHasDistanceField(); 514fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt SkPaint dfPaint = runPaint; 515fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt SkScalar textRatio; 51664c99cc90e678feba473d38db420d31883cc53e6joshualitt this->initDistanceFieldPaint(cacheBlob, &dfPaint, &textRatio, viewMatrix); 517fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt Run& runIdx = cacheBlob->fRuns[run]; 518fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt PerSubRunInfo& subRun = runIdx.fSubRunInfo.back(); 519fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt subRun.fUseLCDText = runPaint.isLCDRenderText(); 520fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt subRun.fDrawAsDistanceFields = true; 521fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt 522fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt SkGlyphCache* cache = this->setupCache(&cacheBlob->fRuns[run], dfPaint, NULL, true); 523fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt 524fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt SkTDArray<char> fallbackTxt; 525fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt SkTDArray<SkScalar> fallbackPos; 526fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt SkPoint dfOffset; 527fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt int scalarsPerPosition = 2; 528fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt switch (it.positioning()) { 529fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt case SkTextBlob::kDefault_Positioning: { 530fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt this->internalDrawDFText(cacheBlob, run, cache, dfPaint, color, viewMatrix, 531fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt (const char *)it.glyphs(), textLen, 532fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt x + offset.x(), y + offset.y(), clipRect, textRatio, 533fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt &fallbackTxt, &fallbackPos, &dfOffset, runPaint); 534fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt break; 535fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt } 536fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt case SkTextBlob::kHorizontal_Positioning: { 537fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt scalarsPerPosition = 1; 538fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt dfOffset = SkPoint::Make(x, y + offset.y()); 539fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt this->internalDrawDFPosText(cacheBlob, run, cache, dfPaint, color, viewMatrix, 540fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt (const char*)it.glyphs(), textLen, it.pos(), 541fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt scalarsPerPosition, dfOffset, clipRect, textRatio, 542fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt &fallbackTxt, &fallbackPos); 543fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt break; 544fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt } 545fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt case SkTextBlob::kFull_Positioning: { 546fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt dfOffset = SkPoint::Make(x, y); 547fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt this->internalDrawDFPosText(cacheBlob, run, cache, dfPaint, color, viewMatrix, 548fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt (const char*)it.glyphs(), textLen, it.pos(), 549fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt scalarsPerPosition, dfOffset, clipRect, textRatio, 550fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt &fallbackTxt, &fallbackPos); 551fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt break; 552fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt } 553fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt } 554fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt if (fallbackTxt.count()) { 555fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt this->fallbackDrawPosText(cacheBlob, run, rt, clip, paint, runPaint, viewMatrix, 556fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt fallbackTxt, fallbackPos, scalarsPerPosition, dfOffset, 557fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt clipRect); 558fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt } 5599a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt 560fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt SkGlyphCache::AttachCache(cache); 561fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt } else if (SkDraw::ShouldDrawTextAsPaths(runPaint, viewMatrix)) { 562fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt cacheBlob->fRuns[run].fDrawAsPaths = true; 563fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt } else { 564fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt cacheBlob->setHasBitmap(); 565fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt SkGlyphCache* cache = this->setupCache(&cacheBlob->fRuns[run], runPaint, &viewMatrix, 566fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt false); 567fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt switch (it.positioning()) { 568fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt case SkTextBlob::kDefault_Positioning: 569fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt this->internalDrawBMPText(cacheBlob, run, cache, runPaint, color, viewMatrix, 570fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt (const char *)it.glyphs(), textLen, 571fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt x + offset.x(), y + offset.y(), clipRect); 572fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt break; 573fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt case SkTextBlob::kHorizontal_Positioning: 574fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt this->internalDrawBMPPosText(cacheBlob, run, cache, runPaint, color, viewMatrix, 575fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt (const char*)it.glyphs(), textLen, it.pos(), 1, 576fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt SkPoint::Make(x, y + offset.y()), clipRect); 577fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt break; 578fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt case SkTextBlob::kFull_Positioning: 579fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt this->internalDrawBMPPosText(cacheBlob, run, cache, runPaint, color, viewMatrix, 580fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt (const char*)it.glyphs(), textLen, it.pos(), 2, 581fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt SkPoint::Make(x, y), clipRect); 582fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt break; 583fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt } 584fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt SkGlyphCache::AttachCache(cache); 5851d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 5861d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 5871d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt if (drawFilter) { 5881d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // A draw filter may change the paint arbitrarily, so we must re-seed in this case. 5891d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt runPaint = skPaint; 5901d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 5911d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 5921d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt} 5931d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 59464c99cc90e678feba473d38db420d31883cc53e6joshualittinline void GrAtlasTextContext::initDistanceFieldPaint(BitmapTextBlob* blob, 59564c99cc90e678feba473d38db420d31883cc53e6joshualitt SkPaint* skPaint, 59664c99cc90e678feba473d38db420d31883cc53e6joshualitt SkScalar* textRatio, 5979bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt const SkMatrix& viewMatrix) { 5989bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // getMaxScale doesn't support perspective, so neither do we at the moment 5999bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkASSERT(!viewMatrix.hasPerspective()); 6009bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkScalar maxScale = viewMatrix.getMaxScale(); 6019bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkScalar textSize = skPaint->getTextSize(); 6029bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkScalar scaledTextSize = textSize; 6039bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // if we have non-unity scale, we need to choose our base text size 6049bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // based on the SkPaint's text size multiplied by the max scale factor 6059bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // TODO: do we need to do this if we're scaling down (i.e. maxScale < 1)? 6069bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (maxScale > 0 && !SkScalarNearlyEqual(maxScale, SK_Scalar1)) { 6079bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt scaledTextSize *= maxScale; 6089bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 6099bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 61064c99cc90e678feba473d38db420d31883cc53e6joshualitt // We have three sizes of distance field text, and within each size 'bucket' there is a floor 61164c99cc90e678feba473d38db420d31883cc53e6joshualitt // and ceiling. A scale outside of this range would require regenerating the distance fields 61264c99cc90e678feba473d38db420d31883cc53e6joshualitt SkScalar dfMaskScaleFloor; 61364c99cc90e678feba473d38db420d31883cc53e6joshualitt SkScalar dfMaskScaleCeil; 6149bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (scaledTextSize <= kSmallDFFontLimit) { 61564c99cc90e678feba473d38db420d31883cc53e6joshualitt dfMaskScaleFloor = kMinDFFontSize; 616a7c6389ebf19cf58926f7a1616f0e5554c56aa84joshualitt dfMaskScaleCeil = kSmallDFFontLimit; 6179bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt *textRatio = textSize / kSmallDFFontSize; 6189bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt skPaint->setTextSize(SkIntToScalar(kSmallDFFontSize)); 6199bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } else if (scaledTextSize <= kMediumDFFontLimit) { 620a7c6389ebf19cf58926f7a1616f0e5554c56aa84joshualitt dfMaskScaleFloor = kSmallDFFontLimit; 621a7c6389ebf19cf58926f7a1616f0e5554c56aa84joshualitt dfMaskScaleCeil = kMediumDFFontLimit; 6229bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt *textRatio = textSize / kMediumDFFontSize; 6239bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt skPaint->setTextSize(SkIntToScalar(kMediumDFFontSize)); 6249bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } else { 625a7c6389ebf19cf58926f7a1616f0e5554c56aa84joshualitt dfMaskScaleFloor = kMediumDFFontLimit; 626a7c6389ebf19cf58926f7a1616f0e5554c56aa84joshualitt dfMaskScaleCeil = kLargeDFFontLimit; 6279bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt *textRatio = textSize / kLargeDFFontSize; 6289bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt skPaint->setTextSize(SkIntToScalar(kLargeDFFontSize)); 6299bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 6309bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 63164c99cc90e678feba473d38db420d31883cc53e6joshualitt // Because there can be multiple runs in the blob, we want the overall maxMinScale, and 63264c99cc90e678feba473d38db420d31883cc53e6joshualitt // minMaxScale to make regeneration decisions. Specifically, we want the maximum minimum scale 63364c99cc90e678feba473d38db420d31883cc53e6joshualitt // we can tolerate before we'd drop to a lower mip size, and the minimum maximum scale we can 63464c99cc90e678feba473d38db420d31883cc53e6joshualitt // tolerate before we'd have to move to a large mip size. When we actually test these values 63564c99cc90e678feba473d38db420d31883cc53e6joshualitt // we look at the delta in scale between the new viewmatrix and the old viewmatrix, and test 63664c99cc90e678feba473d38db420d31883cc53e6joshualitt // against these values to decide if we can reuse or not(ie, will a given scale change our mip 63764c99cc90e678feba473d38db420d31883cc53e6joshualitt // level) 638a7c6389ebf19cf58926f7a1616f0e5554c56aa84joshualitt SkASSERT(dfMaskScaleFloor <= scaledTextSize && scaledTextSize <= dfMaskScaleCeil); 63964c99cc90e678feba473d38db420d31883cc53e6joshualitt blob->fMaxMinScale = SkMaxScalar(dfMaskScaleFloor / scaledTextSize, blob->fMaxMinScale); 64064c99cc90e678feba473d38db420d31883cc53e6joshualitt blob->fMinMaxScale = SkMinScalar(dfMaskScaleCeil / scaledTextSize, blob->fMinMaxScale); 64164c99cc90e678feba473d38db420d31883cc53e6joshualitt 6429bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt skPaint->setLCDRenderText(false); 6439bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt skPaint->setAutohinted(false); 6449bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt skPaint->setHinting(SkPaint::kNormal_Hinting); 6459bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt skPaint->setSubpixelText(true); 6469bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt} 6479bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 648fec19e1751d1a20748e9beaf0a948c01ffe89f04joshualittinline void GrAtlasTextContext::fallbackDrawPosText(BitmapTextBlob* blob, 649fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt int runIndex, 650fec19e1751d1a20748e9beaf0a948c01ffe89f04joshualitt GrRenderTarget* rt, const GrClip& clip, 6519bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt const GrPaint& paint, 6529bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt const SkPaint& skPaint, 6539bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt const SkMatrix& viewMatrix, 6549bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt const SkTDArray<char>& fallbackTxt, 6559bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt const SkTDArray<SkScalar>& fallbackPos, 6569bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt int scalarsPerPosition, 6579bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt const SkPoint& offset, 6589bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt const SkIRect& clipRect) { 659fec19e1751d1a20748e9beaf0a948c01ffe89f04joshualitt SkASSERT(fallbackTxt.count()); 660fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt blob->setHasBitmap(); 661fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt Run& run = blob->fRuns[runIndex]; 66297202d2821c2b9e997d36146ecb9711e02fd7734joshualitt // Push back a new subrun to fill and set the override descriptor 66397202d2821c2b9e997d36146ecb9711e02fd7734joshualitt run.push_back(); 66497202d2821c2b9e997d36146ecb9711e02fd7734joshualitt run.fOverrideDescriptor.reset(SkNEW(SkAutoDescriptor)); 66597202d2821c2b9e997d36146ecb9711e02fd7734joshualitt skPaint.getScalerContextDescriptor(run.fOverrideDescriptor, 666fec19e1751d1a20748e9beaf0a948c01ffe89f04joshualitt &fDeviceProperties, &viewMatrix, false); 667fec19e1751d1a20748e9beaf0a948c01ffe89f04joshualitt SkGlyphCache* cache = SkGlyphCache::DetachCache(run.fTypeface, 66897202d2821c2b9e997d36146ecb9711e02fd7734joshualitt run.fOverrideDescriptor->getDesc()); 669fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt this->internalDrawBMPPosText(blob, runIndex, cache, skPaint, paint.getColor(), viewMatrix, 6709bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt fallbackTxt.begin(), fallbackTxt.count(), 6719bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt fallbackPos.begin(), scalarsPerPosition, offset, clipRect); 6729bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkGlyphCache::AttachCache(cache); 6739bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt} 6749bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 6759bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualittinline GrAtlasTextContext::BitmapTextBlob* 6769bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualittGrAtlasTextContext::setupDFBlob(int glyphCount, const SkPaint& origPaint, 6779bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt const SkMatrix& viewMatrix, SkGlyphCache** cache, 6789bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkPaint* dfPaint, SkScalar* textRatio) { 6799bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt BitmapTextBlob* blob = fCache->createBlob(glyphCount, 1, kGrayTextVASize); 6809bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 6819bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt *dfPaint = origPaint; 68264c99cc90e678feba473d38db420d31883cc53e6joshualitt this->initDistanceFieldPaint(blob, dfPaint, textRatio, viewMatrix); 6839bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt blob->fViewMatrix = viewMatrix; 684fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt Run& run = blob->fRuns[0]; 685fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt PerSubRunInfo& subRun = run.fSubRunInfo.back(); 686fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt subRun.fUseLCDText = origPaint.isLCDRenderText(); 687fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt subRun.fDrawAsDistanceFields = true; 6889bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 6899bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt *cache = this->setupCache(&blob->fRuns[0], *dfPaint, NULL, true); 6909bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt return blob; 6919bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt} 6929bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 69379dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualittinline GrAtlasTextContext::BitmapTextBlob* 69479dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualittGrAtlasTextContext::createDrawTextBlob(GrRenderTarget* rt, const GrClip& clip, 69579dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt const GrPaint& paint, const SkPaint& skPaint, 69679dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt const SkMatrix& viewMatrix, 69779dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt const char text[], size_t byteLength, 69879dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt SkScalar x, SkScalar y, const SkIRect& regionClipBounds) { 6991d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt int glyphCount = skPaint.countText(text, byteLength); 7001d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkIRect clipRect; 7011d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt clip.getConservativeBounds(rt->width(), rt->height(), &clipRect); 7021d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 70379dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt BitmapTextBlob* blob; 7049bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (this->canDrawAsDistanceFields(skPaint, viewMatrix)) { 7059bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkPaint dfPaint; 7069bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkScalar textRatio; 7079bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkGlyphCache* cache; 70879dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt blob = this->setupDFBlob(glyphCount, skPaint, viewMatrix, &cache, &dfPaint, &textRatio); 7099bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 7109bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkTDArray<char> fallbackTxt; 7119bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkTDArray<SkScalar> fallbackPos; 7129bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkPoint offset; 7139bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt this->internalDrawDFText(blob, 0, cache, dfPaint, paint.getColor(), viewMatrix, text, 7149bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt byteLength, x, y, clipRect, textRatio, &fallbackTxt, &fallbackPos, 7159bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt &offset, skPaint); 7169bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkGlyphCache::AttachCache(cache); 7179bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (fallbackTxt.count()) { 718fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt this->fallbackDrawPosText(blob, 0, rt, clip, paint, skPaint, viewMatrix, fallbackTxt, 7199bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt fallbackPos, 2, offset, clipRect); 7209bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 7219bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } else { 72279dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt blob = fCache->createBlob(glyphCount, 1, kGrayTextVASize); 7239bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt blob->fViewMatrix = viewMatrix; 7241d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 7259bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkGlyphCache* cache = this->setupCache(&blob->fRuns[0], skPaint, &viewMatrix, false); 7269bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt this->internalDrawBMPText(blob, 0, cache, skPaint, paint.getColor(), viewMatrix, text, 7279bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt byteLength, x, y, clipRect); 7289bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkGlyphCache::AttachCache(cache); 7299bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 73079dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt return blob; 7311d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt} 7321d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 73379dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualittinline GrAtlasTextContext::BitmapTextBlob* 73479dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualittGrAtlasTextContext::createDrawPosTextBlob(GrRenderTarget* rt, const GrClip& clip, 73579dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt const GrPaint& paint, const SkPaint& skPaint, 73679dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt const SkMatrix& viewMatrix, 73779dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt const char text[], size_t byteLength, 73879dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt const SkScalar pos[], int scalarsPerPosition, 73979dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt const SkPoint& offset, const SkIRect& regionClipBounds) { 7409bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt int glyphCount = skPaint.countText(text, byteLength); 7419bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 7429bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkIRect clipRect; 7439bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt clip.getConservativeBounds(rt->width(), rt->height(), &clipRect); 7449bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 74579dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt BitmapTextBlob* blob; 7469bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (this->canDrawAsDistanceFields(skPaint, viewMatrix)) { 7479bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkPaint dfPaint; 7489bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkScalar textRatio; 7499bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkGlyphCache* cache; 75079dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt blob = this->setupDFBlob(glyphCount, skPaint, viewMatrix, &cache, &dfPaint, &textRatio); 7519bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 7529bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkTDArray<char> fallbackTxt; 7539bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkTDArray<SkScalar> fallbackPos; 7549bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt this->internalDrawDFPosText(blob, 0, cache, dfPaint, paint.getColor(), viewMatrix, text, 7559bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt byteLength, pos, scalarsPerPosition, offset, clipRect, 7569bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt textRatio, &fallbackTxt, &fallbackPos); 7579bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkGlyphCache::AttachCache(cache); 7589bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (fallbackTxt.count()) { 759fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt this->fallbackDrawPosText(blob, 0, rt, clip, paint, skPaint, viewMatrix, fallbackTxt, 7609bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt fallbackPos, scalarsPerPosition, offset, clipRect); 7619bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 7629bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } else { 76379dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt blob = fCache->createBlob(glyphCount, 1, kGrayTextVASize); 7649bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt blob->fViewMatrix = viewMatrix; 7659bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkGlyphCache* cache = this->setupCache(&blob->fRuns[0], skPaint, &viewMatrix, false); 7669bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt this->internalDrawBMPPosText(blob, 0, cache, skPaint, paint.getColor(), viewMatrix, text, 7679bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt byteLength, pos, scalarsPerPosition, offset, clipRect); 7689bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkGlyphCache::AttachCache(cache); 7699bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 77079dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt return blob; 77179dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt} 77279dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt 77379dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualittvoid GrAtlasTextContext::onDrawText(GrRenderTarget* rt, const GrClip& clip, 77479dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt const GrPaint& paint, const SkPaint& skPaint, 77579dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt const SkMatrix& viewMatrix, 77679dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt const char text[], size_t byteLength, 77779dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt SkScalar x, SkScalar y, const SkIRect& regionClipBounds) { 77879dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt SkAutoTUnref<BitmapTextBlob> blob( 77979dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt this->createDrawTextBlob(rt, clip, paint, skPaint, viewMatrix, 78079dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt text, byteLength, x, y, regionClipBounds)); 7811107e901c9dac3098e2915213f171ff62d007aa7joshualitt this->flush(fContext->getTextTarget(), blob, rt, skPaint, paint, clip, regionClipBounds); 78279dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt} 78379dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt 78479dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualittvoid GrAtlasTextContext::onDrawPosText(GrRenderTarget* rt, const GrClip& clip, 78579dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt const GrPaint& paint, const SkPaint& skPaint, 78679dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt const SkMatrix& viewMatrix, 78779dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt const char text[], size_t byteLength, 78879dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt const SkScalar pos[], int scalarsPerPosition, 78979dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt const SkPoint& offset, const SkIRect& regionClipBounds) { 79079dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt SkAutoTUnref<BitmapTextBlob> blob( 79179dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt this->createDrawPosTextBlob(rt, clip, paint, skPaint, viewMatrix, 79279dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt text, byteLength, 79379dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt pos, scalarsPerPosition, 79479dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt offset, regionClipBounds)); 79579dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt 7961107e901c9dac3098e2915213f171ff62d007aa7joshualitt this->flush(fContext->getTextTarget(), blob, rt, skPaint, paint, clip, regionClipBounds); 7979bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt} 7989bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 7999bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualittvoid GrAtlasTextContext::internalDrawBMPText(BitmapTextBlob* blob, int runIndex, 8009bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkGlyphCache* cache, const SkPaint& skPaint, 8019bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt GrColor color, 8029bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt const SkMatrix& viewMatrix, 8039bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt const char text[], size_t byteLength, 8049bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkScalar x, SkScalar y, const SkIRect& clipRect) { 8051d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkASSERT(byteLength == 0 || text != NULL); 8061d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 8071d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // nothing to draw 8081d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt if (text == NULL || byteLength == 0) { 8091d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt return; 8101d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 8111d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 8121d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt fCurrStrike = NULL; 8131d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkDrawCacheProc glyphCacheProc = skPaint.getDrawCacheProc(); 8141d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 8151d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // Get GrFontScaler from cache 8161d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt GrFontScaler* fontScaler = GetGrFontScaler(cache); 8171d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 8181d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // transform our starting point 8191d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt { 8201d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkPoint loc; 8211d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt viewMatrix.mapXY(x, y, &loc); 8221d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt x = loc.fX; 8231d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt y = loc.fY; 8241d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 8251d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 8261d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // need to measure first 8271d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt if (skPaint.getTextAlign() != SkPaint::kLeft_Align) { 8281d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkVector stopVector; 8291d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt MeasureText(cache, glyphCacheProc, text, byteLength, &stopVector); 8301d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 8311d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkScalar stopX = stopVector.fX; 8321d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkScalar stopY = stopVector.fY; 8331d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 8341d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt if (skPaint.getTextAlign() == SkPaint::kCenter_Align) { 8351d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt stopX = SkScalarHalf(stopX); 8361d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt stopY = SkScalarHalf(stopY); 8371d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 8381d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt x -= stopX; 8391d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt y -= stopY; 8401d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 8411d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 8421d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt const char* stop = text + byteLength; 8431d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 8441d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkAutoKern autokern; 8451d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 8461d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkFixed fxMask = ~0; 8471d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkFixed fyMask = ~0; 8481d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkScalar halfSampleX, halfSampleY; 8491d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt if (cache->isSubpixel()) { 8501d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt halfSampleX = halfSampleY = SkFixedToScalar(SkGlyph::kSubpixelRound); 8511d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(viewMatrix); 8521d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt if (kX_SkAxisAlignment == baseline) { 8531d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt fyMask = 0; 8541d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt halfSampleY = SK_ScalarHalf; 8551d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } else if (kY_SkAxisAlignment == baseline) { 8561d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt fxMask = 0; 8571d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt halfSampleX = SK_ScalarHalf; 8581d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 8591d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } else { 8601d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt halfSampleX = halfSampleY = SK_ScalarHalf; 8611d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 8621d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 8631d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt Sk48Dot16 fx = SkScalarTo48Dot16(x + halfSampleX); 8641d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt Sk48Dot16 fy = SkScalarTo48Dot16(y + halfSampleY); 8651d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 8661d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt while (text < stop) { 8671d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask); 8681d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 8691d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt fx += autokern.adjust(glyph); 8701d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 8711d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt if (glyph.fWidth) { 8729bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt this->bmpAppendGlyph(blob, 8739bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt runIndex, 8749bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt GrGlyph::Pack(glyph.getGlyphID(), 8759bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt glyph.getSubXFixed(), 8769bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt glyph.getSubYFixed(), 8779bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt GrGlyph::kCoverage_MaskStyle), 8789bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt Sk48Dot16FloorToInt(fx), 8799bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt Sk48Dot16FloorToInt(fy), 8809bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt color, 8819bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt fontScaler, 8829bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt clipRect); 8831d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 8841d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 8851d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt fx += glyph.fAdvanceX; 8861d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt fy += glyph.fAdvanceY; 8871d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 8881d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt} 8891d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 8909bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualittvoid GrAtlasTextContext::internalDrawBMPPosText(BitmapTextBlob* blob, int runIndex, 8919bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkGlyphCache* cache, const SkPaint& skPaint, 8929bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt GrColor color, 8939bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt const SkMatrix& viewMatrix, 8949bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt const char text[], size_t byteLength, 8959bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt const SkScalar pos[], int scalarsPerPosition, 8969bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt const SkPoint& offset, const SkIRect& clipRect) { 8971d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkASSERT(byteLength == 0 || text != NULL); 8981d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); 8991d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 9001d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // nothing to draw 9011d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt if (text == NULL || byteLength == 0) { 9021d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt return; 9031d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 9041d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 9051d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt fCurrStrike = NULL; 9061d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkDrawCacheProc glyphCacheProc = skPaint.getDrawCacheProc(); 9071d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 9081d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // Get GrFontScaler from cache 9091d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt GrFontScaler* fontScaler = GetGrFontScaler(cache); 9101d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 9111d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt const char* stop = text + byteLength; 9121d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkTextAlignProc alignProc(skPaint.getTextAlign()); 9131d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkTextMapStateProc tmsProc(viewMatrix, offset, scalarsPerPosition); 9141d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 9151d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt if (cache->isSubpixel()) { 9161d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // maybe we should skip the rounding if linearText is set 9171d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(viewMatrix); 9181d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 9191d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkFixed fxMask = ~0; 9201d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkFixed fyMask = ~0; 9211d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkScalar halfSampleX = SkFixedToScalar(SkGlyph::kSubpixelRound); 9221d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkScalar halfSampleY = SkFixedToScalar(SkGlyph::kSubpixelRound); 9231d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt if (kX_SkAxisAlignment == baseline) { 9241d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt fyMask = 0; 9251d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt halfSampleY = SK_ScalarHalf; 9261d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } else if (kY_SkAxisAlignment == baseline) { 9271d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt fxMask = 0; 9281d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt halfSampleX = SK_ScalarHalf; 9291d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 9301d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 9311d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt if (SkPaint::kLeft_Align == skPaint.getTextAlign()) { 9321d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt while (text < stop) { 9331d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkPoint tmsLoc; 9341d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt tmsProc(pos, &tmsLoc); 9351d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt Sk48Dot16 fx = SkScalarTo48Dot16(tmsLoc.fX + halfSampleX); 9361d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt Sk48Dot16 fy = SkScalarTo48Dot16(tmsLoc.fY + halfSampleY); 9371d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 9381d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt const SkGlyph& glyph = glyphCacheProc(cache, &text, 9391d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt fx & fxMask, fy & fyMask); 9401d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 9411d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt if (glyph.fWidth) { 9429bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt this->bmpAppendGlyph(blob, 9439bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt runIndex, 9449bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt GrGlyph::Pack(glyph.getGlyphID(), 9459bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt glyph.getSubXFixed(), 9469bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt glyph.getSubYFixed(), 9479bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt GrGlyph::kCoverage_MaskStyle), 9489bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt Sk48Dot16FloorToInt(fx), 9499bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt Sk48Dot16FloorToInt(fy), 9509bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt color, 9519bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt fontScaler, 9529bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt clipRect); 9531d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 9541d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt pos += scalarsPerPosition; 9551d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 9561d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } else { 9571d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt while (text < stop) { 9581d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt const char* currentText = text; 9591d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt const SkGlyph& metricGlyph = glyphCacheProc(cache, &text, 0, 0); 9601d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 9611d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt if (metricGlyph.fWidth) { 9621d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkDEBUGCODE(SkFixed prevAdvX = metricGlyph.fAdvanceX;) 9631d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkDEBUGCODE(SkFixed prevAdvY = metricGlyph.fAdvanceY;) 9641d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkPoint tmsLoc; 9651d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt tmsProc(pos, &tmsLoc); 9661d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkPoint alignLoc; 9671d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt alignProc(tmsLoc, metricGlyph, &alignLoc); 9681d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 9691d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt Sk48Dot16 fx = SkScalarTo48Dot16(alignLoc.fX + halfSampleX); 9701d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt Sk48Dot16 fy = SkScalarTo48Dot16(alignLoc.fY + halfSampleY); 9711d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 9721d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // have to call again, now that we've been "aligned" 9731d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt const SkGlyph& glyph = glyphCacheProc(cache, ¤tText, 9741d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt fx & fxMask, fy & fyMask); 9751d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // the assumption is that the metrics haven't changed 9761d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkASSERT(prevAdvX == glyph.fAdvanceX); 9771d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkASSERT(prevAdvY == glyph.fAdvanceY); 9781d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkASSERT(glyph.fWidth); 9791d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 9809bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt this->bmpAppendGlyph(blob, 9819bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt runIndex, 9829bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt GrGlyph::Pack(glyph.getGlyphID(), 9839bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt glyph.getSubXFixed(), 9849bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt glyph.getSubYFixed(), 9859bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt GrGlyph::kCoverage_MaskStyle), 9869bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt Sk48Dot16FloorToInt(fx), 9879bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt Sk48Dot16FloorToInt(fy), 9889bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt color, 9899bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt fontScaler, 9909bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt clipRect); 9911d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 9921d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt pos += scalarsPerPosition; 9931d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 9941d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 9951d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } else { // not subpixel 9961d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 9971d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt if (SkPaint::kLeft_Align == skPaint.getTextAlign()) { 9981d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt while (text < stop) { 9991d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // the last 2 parameters are ignored 10001d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); 10011d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 10021d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt if (glyph.fWidth) { 10031d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkPoint tmsLoc; 10041d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt tmsProc(pos, &tmsLoc); 10051d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 10061d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt Sk48Dot16 fx = SkScalarTo48Dot16(tmsLoc.fX + SK_ScalarHalf); //halfSampleX; 10071d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt Sk48Dot16 fy = SkScalarTo48Dot16(tmsLoc.fY + SK_ScalarHalf); //halfSampleY; 10089bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt this->bmpAppendGlyph(blob, 10099bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt runIndex, 10109bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt GrGlyph::Pack(glyph.getGlyphID(), 10119bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt glyph.getSubXFixed(), 10129bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt glyph.getSubYFixed(), 10139bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt GrGlyph::kCoverage_MaskStyle), 10149bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt Sk48Dot16FloorToInt(fx), 10159bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt Sk48Dot16FloorToInt(fy), 10169bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt color, 10179bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt fontScaler, 10189bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt clipRect); 10191d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 10201d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt pos += scalarsPerPosition; 10211d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 10221d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } else { 10231d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt while (text < stop) { 10241d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // the last 2 parameters are ignored 10251d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); 10261d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 10271d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt if (glyph.fWidth) { 10281d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkPoint tmsLoc; 10291d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt tmsProc(pos, &tmsLoc); 10301d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 10311d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkPoint alignLoc; 10321d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt alignProc(tmsLoc, glyph, &alignLoc); 10331d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 10341d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt Sk48Dot16 fx = SkScalarTo48Dot16(alignLoc.fX + SK_ScalarHalf); //halfSampleX; 10351d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt Sk48Dot16 fy = SkScalarTo48Dot16(alignLoc.fY + SK_ScalarHalf); //halfSampleY; 10369bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt this->bmpAppendGlyph(blob, 10379bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt runIndex, 10389bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt GrGlyph::Pack(glyph.getGlyphID(), 10399bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt glyph.getSubXFixed(), 10409bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt glyph.getSubYFixed(), 10419bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt GrGlyph::kCoverage_MaskStyle), 10429bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt Sk48Dot16FloorToInt(fx), 10439bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt Sk48Dot16FloorToInt(fy), 10449bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt color, 10459bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt fontScaler, 10469bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt clipRect); 10471d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 10481d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt pos += scalarsPerPosition; 10491d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 10501d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 10511d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 10521d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt} 10531d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 10549bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 10559bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualittvoid GrAtlasTextContext::internalDrawDFText(BitmapTextBlob* blob, int runIndex, 10569bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkGlyphCache* cache, const SkPaint& skPaint, 10579bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt GrColor color, 10589bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt const SkMatrix& viewMatrix, 10599bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt const char text[], size_t byteLength, 10609bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkScalar x, SkScalar y, const SkIRect& clipRect, 10619bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkScalar textRatio, 10629bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkTDArray<char>* fallbackTxt, 10639bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkTDArray<SkScalar>* fallbackPos, 10649bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkPoint* offset, 10659bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt const SkPaint& origPaint) { 10669bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkASSERT(byteLength == 0 || text != NULL); 10679bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 10689bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // nothing to draw 10699bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (text == NULL || byteLength == 0) { 10709bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt return; 10719bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 10729bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 10739bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkDrawCacheProc glyphCacheProc = origPaint.getDrawCacheProc(); 10749bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkAutoDescriptor desc; 10759bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt origPaint.getScalerContextDescriptor(&desc, &fDeviceProperties, NULL, true); 10769bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkGlyphCache* origPaintCache = SkGlyphCache::DetachCache(origPaint.getTypeface(), 10779bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt desc.getDesc()); 10789bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 10799bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkTArray<SkScalar> positions; 10809bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 10819bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt const char* textPtr = text; 10829bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkFixed stopX = 0; 10839bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkFixed stopY = 0; 10849bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkFixed origin = 0; 10859bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt switch (origPaint.getTextAlign()) { 10869bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt case SkPaint::kRight_Align: origin = SK_Fixed1; break; 10879bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt case SkPaint::kCenter_Align: origin = SK_FixedHalf; break; 10889bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt case SkPaint::kLeft_Align: origin = 0; break; 10899bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 10909bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 10919bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkAutoKern autokern; 10929bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt const char* stop = text + byteLength; 10939bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt while (textPtr < stop) { 10949bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // don't need x, y here, since all subpixel variants will have the 10959bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // same advance 10969bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt const SkGlyph& glyph = glyphCacheProc(origPaintCache, &textPtr, 0, 0); 10979bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 10989bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkFixed width = glyph.fAdvanceX + autokern.adjust(glyph); 10999bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt positions.push_back(SkFixedToScalar(stopX + SkFixedMul(origin, width))); 11009bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 11019bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkFixed height = glyph.fAdvanceY; 11029bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt positions.push_back(SkFixedToScalar(stopY + SkFixedMul(origin, height))); 11039bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 11049bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt stopX += width; 11059bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt stopY += height; 11069bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 11079bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkASSERT(textPtr == stop); 11089bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 11099bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // now adjust starting point depending on alignment 11109bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkScalar alignX = SkFixedToScalar(stopX); 11119bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkScalar alignY = SkFixedToScalar(stopY); 11129bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (origPaint.getTextAlign() == SkPaint::kCenter_Align) { 11139bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt alignX = SkScalarHalf(alignX); 11149bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt alignY = SkScalarHalf(alignY); 11159bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } else if (origPaint.getTextAlign() == SkPaint::kLeft_Align) { 11169bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt alignX = 0; 11179bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt alignY = 0; 11189bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 11199bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt x -= alignX; 11209bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt y -= alignY; 11219bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt *offset = SkPoint::Make(x, y); 11229bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 11239bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt this->internalDrawDFPosText(blob, runIndex, cache, skPaint, color, viewMatrix, text, byteLength, 11249bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt positions.begin(), 2, *offset, clipRect, textRatio, fallbackTxt, 11259bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt fallbackPos); 11269bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkGlyphCache::AttachCache(origPaintCache); 11279bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt} 11289bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 11299bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualittvoid GrAtlasTextContext::internalDrawDFPosText(BitmapTextBlob* blob, int runIndex, 11309bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkGlyphCache* cache, const SkPaint& skPaint, 11319bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt GrColor color, 11329bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt const SkMatrix& viewMatrix, 11339bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt const char text[], size_t byteLength, 11349bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt const SkScalar pos[], int scalarsPerPosition, 11359bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt const SkPoint& offset, const SkIRect& clipRect, 11369bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkScalar textRatio, 11379bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkTDArray<char>* fallbackTxt, 11389bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkTDArray<SkScalar>* fallbackPos) { 11399bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 11409bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkASSERT(byteLength == 0 || text != NULL); 11419bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); 11429bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 11439bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // nothing to draw 11449bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (text == NULL || byteLength == 0) { 11459bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt return; 11469bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 11479bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 11489bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt fCurrStrike = NULL; 11499bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 11509bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkDrawCacheProc glyphCacheProc = skPaint.getDrawCacheProc(); 11519bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt GrFontScaler* fontScaler = GetGrFontScaler(cache); 11529bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 11539bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt const char* stop = text + byteLength; 11549bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 11559bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (SkPaint::kLeft_Align == skPaint.getTextAlign()) { 11569bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt while (text < stop) { 11579bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt const char* lastText = text; 11589bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // the last 2 parameters are ignored 11599bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); 11609bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 11619bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (glyph.fWidth) { 11629bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkScalar x = offset.x() + pos[0]; 11639bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkScalar y = offset.y() + (2 == scalarsPerPosition ? pos[1] : 0); 11649bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 11659bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (!this->dfAppendGlyph(blob, 11669bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt runIndex, 11679bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt GrGlyph::Pack(glyph.getGlyphID(), 11689bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt glyph.getSubXFixed(), 11699bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt glyph.getSubYFixed(), 11709bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt GrGlyph::kDistance_MaskStyle), 11719bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt x, y, color, fontScaler, clipRect, 11729bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt textRatio, viewMatrix)) { 11739bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // couldn't append, send to fallback 11749bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt fallbackTxt->append(SkToInt(text-lastText), lastText); 11759bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt *fallbackPos->append() = pos[0]; 11769bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (2 == scalarsPerPosition) { 11779bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt *fallbackPos->append() = pos[1]; 11789bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 11799bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 11809bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 11819bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt pos += scalarsPerPosition; 11829bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 11839bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } else { 11849bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkScalar alignMul = SkPaint::kCenter_Align == skPaint.getTextAlign() ? SK_ScalarHalf 11859bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt : SK_Scalar1; 11869bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt while (text < stop) { 11879bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt const char* lastText = text; 11889bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // the last 2 parameters are ignored 11899bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); 11909bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 11919bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (glyph.fWidth) { 11929bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkScalar x = offset.x() + pos[0]; 11939bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkScalar y = offset.y() + (2 == scalarsPerPosition ? pos[1] : 0); 11949bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 11959bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkScalar advanceX = SkFixedToScalar(glyph.fAdvanceX) * alignMul * textRatio; 11969bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkScalar advanceY = SkFixedToScalar(glyph.fAdvanceY) * alignMul * textRatio; 11979bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 11989bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (!this->dfAppendGlyph(blob, 11999bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt runIndex, 12009bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt GrGlyph::Pack(glyph.getGlyphID(), 12019bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt glyph.getSubXFixed(), 12029bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt glyph.getSubYFixed(), 12039bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt GrGlyph::kDistance_MaskStyle), 12049bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt x - advanceX, y - advanceY, color, 12059bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt fontScaler, 12069bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt clipRect, 12079bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt textRatio, 12089bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt viewMatrix)) { 12099bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // couldn't append, send to fallback 12109bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt fallbackTxt->append(SkToInt(text-lastText), lastText); 12119bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt *fallbackPos->append() = pos[0]; 12129bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (2 == scalarsPerPosition) { 12139bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt *fallbackPos->append() = pos[1]; 12149bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 12159bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 12169bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 12179bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt pos += scalarsPerPosition; 12189bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 12199bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 12209bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt} 12219bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 12229bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualittvoid GrAtlasTextContext::bmpAppendGlyph(BitmapTextBlob* blob, int runIndex, 12239bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt GrGlyph::PackedID packed, 12249bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt int vx, int vy, GrColor color, GrFontScaler* scaler, 12259bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt const SkIRect& clipRect) { 1226ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt Run& run = blob->fRuns[runIndex]; 12279bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (!fCurrStrike) { 12281d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt fCurrStrike = fContext->getBatchFontCache()->getStrike(scaler); 1229ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt run.fStrike.reset(SkRef(fCurrStrike)); 12301d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 12311d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 12321d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt GrGlyph* glyph = fCurrStrike->getGlyph(packed, scaler); 1233010db5346e425be8ce659b23b75943ee8ef9d537joshualitt if (!glyph) { 12341d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt return; 12351d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 12361d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 12371d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt int x = vx + glyph->fBounds.fLeft; 12381d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt int y = vy + glyph->fBounds.fTop; 12391d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 12401d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // keep them as ints until we've done the clip-test 12411d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt int width = glyph->fBounds.width(); 12421d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt int height = glyph->fBounds.height(); 12431d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 12442a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt#if 0 12452a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt // Not checking the clip bounds might introduce a performance regression. However, its not 12462a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt // clear if this is still true today with the larger tiles we use in Chrome. For repositionable 12472a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt // blobs, we want to make sure we have all of the glyphs, so clipping them out is not ideal. 12482a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt // We could store the cliprect in the key, but then we'd lose the ability to do integer scrolls 12492a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt // TODO verify this 12501d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // check if we clipped out 12511d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt if (clipRect.quickReject(x, y, x + width, y + height)) { 12521d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt return; 12531d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 12542a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt#endif 12551d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 12561d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // If the glyph is too large we fall back to paths 1257010db5346e425be8ce659b23b75943ee8ef9d537joshualitt if (glyph->fTooLargeForAtlas) { 125819e4c02a4112f9a9c63247613c201dbba84110b4joshualitt this->appendGlyphPath(blob, glyph, scaler, SkIntToScalar(vx), SkIntToScalar(vy)); 12591d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt return; 12601d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 12611d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 12621d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt GrMaskFormat format = glyph->fMaskFormat; 12631d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 12641d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt PerSubRunInfo* subRun = &run.fSubRunInfo.back(); 12651d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt if (run.fInitialized && subRun->fMaskFormat != format) { 1266fec19e1751d1a20748e9beaf0a948c01ffe89f04joshualitt subRun = &run.fSubRunInfo.push_back(); 12671d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 12681d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 12691d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt run.fInitialized = true; 12701d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 12711d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt size_t vertexStride = get_vertex_stride(format); 12721d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 12731d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkRect r; 12741d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt r.fLeft = SkIntToScalar(x); 12751d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt r.fTop = SkIntToScalar(y); 12761d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt r.fRight = r.fLeft + SkIntToScalar(width); 12771d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt r.fBottom = r.fTop + SkIntToScalar(height); 12789bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt subRun->fMaskFormat = format; 12799bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt this->appendGlyphCommon(blob, &run, subRun, r, color, vertexStride, kA8_GrMaskFormat == format, 1280ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt glyph); 12819bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt} 12829bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 12839bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualittbool GrAtlasTextContext::dfAppendGlyph(BitmapTextBlob* blob, int runIndex, 12849bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt GrGlyph::PackedID packed, 12859bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkScalar sx, SkScalar sy, GrColor color, 12869bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt GrFontScaler* scaler, 12879bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt const SkIRect& clipRect, 12889bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkScalar textRatio, const SkMatrix& viewMatrix) { 1289ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt Run& run = blob->fRuns[runIndex]; 12909bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (!fCurrStrike) { 12919bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt fCurrStrike = fContext->getBatchFontCache()->getStrike(scaler); 1292ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt run.fStrike.reset(SkRef(fCurrStrike)); 12939bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 12949bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 12959bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt GrGlyph* glyph = fCurrStrike->getGlyph(packed, scaler); 1296010db5346e425be8ce659b23b75943ee8ef9d537joshualitt if (!glyph) { 12979bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt return true; 12989bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 12999bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 13009bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // fallback to color glyph support 13019bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (kA8_GrMaskFormat != glyph->fMaskFormat) { 13029bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt return false; 13039bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 13049bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 13059bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkScalar dx = SkIntToScalar(glyph->fBounds.fLeft + SK_DistanceFieldInset); 13069bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkScalar dy = SkIntToScalar(glyph->fBounds.fTop + SK_DistanceFieldInset); 13079bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkScalar width = SkIntToScalar(glyph->fBounds.width() - 2 * SK_DistanceFieldInset); 13089bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkScalar height = SkIntToScalar(glyph->fBounds.height() - 2 * SK_DistanceFieldInset); 13099bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 13109bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkScalar scale = textRatio; 13119bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt dx *= scale; 13129bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt dy *= scale; 13139bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt width *= scale; 13149bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt height *= scale; 13159bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt sx += dx; 13169bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt sy += dy; 13179bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkRect glyphRect = SkRect::MakeXYWH(sx, sy, width, height); 13189bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 13199bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt#if 0 13209bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // check if we clipped out 13219bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkRect dstRect; 13229bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt viewMatrix.mapRect(&dstRect, glyphRect); 13239bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (clipRect.quickReject(SkScalarTruncToInt(dstRect.left()), 13249bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkScalarTruncToInt(dstRect.top()), 13259bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkScalarTruncToInt(dstRect.right()), 13269bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkScalarTruncToInt(dstRect.bottom()))) { 13279bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt return true; 13289bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 13299bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt#endif 13309bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 13319bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // TODO combine with the above 13329bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // If the glyph is too large we fall back to paths 1333010db5346e425be8ce659b23b75943ee8ef9d537joshualitt if (glyph->fTooLargeForAtlas) { 133419e4c02a4112f9a9c63247613c201dbba84110b4joshualitt this->appendGlyphPath(blob, glyph, scaler, sx - dx, sy - dy); 13359bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt return true; 13369bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 13379bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 13389bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt PerSubRunInfo* subRun = &run.fSubRunInfo.back(); 13399bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkASSERT(glyph->fMaskFormat == kA8_GrMaskFormat); 13409bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt subRun->fMaskFormat = kA8_GrMaskFormat; 13419bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 13429bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt size_t vertexStride = get_vertex_stride_df(kA8_GrMaskFormat, subRun->fUseLCDText); 13439bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 13449bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt bool useColorVerts = !subRun->fUseLCDText; 13459bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt this->appendGlyphCommon(blob, &run, subRun, glyphRect, color, vertexStride, useColorVerts, 1346ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt glyph); 13479bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt return true; 13489bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt} 13499bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 13509bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualittinline void GrAtlasTextContext::appendGlyphPath(BitmapTextBlob* blob, GrGlyph* glyph, 135119e4c02a4112f9a9c63247613c201dbba84110b4joshualitt GrFontScaler* scaler, SkScalar x, SkScalar y) { 13529bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (NULL == glyph->fPath) { 13539bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkPath* path = SkNEW(SkPath); 13549bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (!scaler->getGlyphPath(glyph->glyphID(), path)) { 13559bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // flag the glyph as being dead? 13569bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkDELETE(path); 13579bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt return; 13589bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 13599bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt glyph->fPath = path; 13609bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 13619bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkASSERT(glyph->fPath); 13629bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt blob->fBigGlyphs.push_back(BitmapTextBlob::BigGlyph(*glyph->fPath, x, y)); 13639bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt} 13641d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 13659bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualittinline void GrAtlasTextContext::appendGlyphCommon(BitmapTextBlob* blob, Run* run, 13669bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt Run::SubRunInfo* subRun, 13679bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt const SkRect& positions, GrColor color, 13689bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt size_t vertexStride, bool useVertexColor, 1369ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt GrGlyph* glyph) { 1370ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt blob->fGlyphs[subRun->fGlyphEndIndex] = glyph; 13719bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt run->fVertexBounds.joinNonEmptyArg(positions); 13729bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt run->fColor = color; 13731d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 13741d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVertices + subRun->fVertexEndIndex); 13751d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 13769bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (useVertexColor) { 1377010db5346e425be8ce659b23b75943ee8ef9d537joshualitt // V0 1378010db5346e425be8ce659b23b75943ee8ef9d537joshualitt SkPoint* position = reinterpret_cast<SkPoint*>(vertex); 1379010db5346e425be8ce659b23b75943ee8ef9d537joshualitt position->set(positions.fLeft, positions.fTop); 13801d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkColor* colorPtr = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint)); 13811d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt *colorPtr = color; 1382010db5346e425be8ce659b23b75943ee8ef9d537joshualitt vertex += vertexStride; 13839bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 1384010db5346e425be8ce659b23b75943ee8ef9d537joshualitt // V1 1385010db5346e425be8ce659b23b75943ee8ef9d537joshualitt position = reinterpret_cast<SkPoint*>(vertex); 1386010db5346e425be8ce659b23b75943ee8ef9d537joshualitt position->set(positions.fLeft, positions.fBottom); 1387010db5346e425be8ce659b23b75943ee8ef9d537joshualitt colorPtr = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint)); 13881d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt *colorPtr = color; 1389010db5346e425be8ce659b23b75943ee8ef9d537joshualitt vertex += vertexStride; 13901d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 1391010db5346e425be8ce659b23b75943ee8ef9d537joshualitt // V2 1392010db5346e425be8ce659b23b75943ee8ef9d537joshualitt position = reinterpret_cast<SkPoint*>(vertex); 1393010db5346e425be8ce659b23b75943ee8ef9d537joshualitt position->set(positions.fRight, positions.fBottom); 1394010db5346e425be8ce659b23b75943ee8ef9d537joshualitt colorPtr = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint)); 13951d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt *colorPtr = color; 1396010db5346e425be8ce659b23b75943ee8ef9d537joshualitt vertex += vertexStride; 13971d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 1398010db5346e425be8ce659b23b75943ee8ef9d537joshualitt // V3 1399010db5346e425be8ce659b23b75943ee8ef9d537joshualitt position = reinterpret_cast<SkPoint*>(vertex); 1400010db5346e425be8ce659b23b75943ee8ef9d537joshualitt position->set(positions.fRight, positions.fTop); 1401010db5346e425be8ce659b23b75943ee8ef9d537joshualitt colorPtr = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint)); 14021d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt *colorPtr = color; 1403010db5346e425be8ce659b23b75943ee8ef9d537joshualitt } else { 1404010db5346e425be8ce659b23b75943ee8ef9d537joshualitt // V0 1405010db5346e425be8ce659b23b75943ee8ef9d537joshualitt SkPoint* position = reinterpret_cast<SkPoint*>(vertex); 1406010db5346e425be8ce659b23b75943ee8ef9d537joshualitt position->set(positions.fLeft, positions.fTop); 1407010db5346e425be8ce659b23b75943ee8ef9d537joshualitt vertex += vertexStride; 1408010db5346e425be8ce659b23b75943ee8ef9d537joshualitt 1409010db5346e425be8ce659b23b75943ee8ef9d537joshualitt // V1 1410010db5346e425be8ce659b23b75943ee8ef9d537joshualitt position = reinterpret_cast<SkPoint*>(vertex); 1411010db5346e425be8ce659b23b75943ee8ef9d537joshualitt position->set(positions.fLeft, positions.fBottom); 1412010db5346e425be8ce659b23b75943ee8ef9d537joshualitt vertex += vertexStride; 1413010db5346e425be8ce659b23b75943ee8ef9d537joshualitt 1414010db5346e425be8ce659b23b75943ee8ef9d537joshualitt // V2 1415010db5346e425be8ce659b23b75943ee8ef9d537joshualitt position = reinterpret_cast<SkPoint*>(vertex); 1416010db5346e425be8ce659b23b75943ee8ef9d537joshualitt position->set(positions.fRight, positions.fBottom); 1417010db5346e425be8ce659b23b75943ee8ef9d537joshualitt vertex += vertexStride; 1418010db5346e425be8ce659b23b75943ee8ef9d537joshualitt 1419010db5346e425be8ce659b23b75943ee8ef9d537joshualitt // V3 1420010db5346e425be8ce659b23b75943ee8ef9d537joshualitt position = reinterpret_cast<SkPoint*>(vertex); 1421010db5346e425be8ce659b23b75943ee8ef9d537joshualitt position->set(positions.fRight, positions.fTop); 14221d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 14231d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 14241d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt subRun->fGlyphEndIndex++; 14251d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt subRun->fVertexEndIndex += vertexStride * kVerticesPerGlyph; 14261d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt} 14271d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 14281d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualittclass BitmapTextBatch : public GrBatch { 14291d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualittpublic: 14309bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt typedef GrAtlasTextContext::DistanceAdjustTable DistanceAdjustTable; 1431dbd3593e0b0cfb04f23b9d7bce623e6e32364b3fjoshualitt typedef GrAtlasTextContext::BitmapTextBlob Blob; 14321d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt typedef Blob::Run Run; 14331d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt typedef Run::SubRunInfo TextInfo; 14341d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt struct Geometry { 1435ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt Blob* fBlob; 14361d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt int fRun; 14371d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt int fSubRun; 14381d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt GrColor fColor; 14392a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt SkScalar fTransX; 14402a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt SkScalar fTransY; 14411d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt }; 14421d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 1443ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt static BitmapTextBatch* Create(GrMaskFormat maskFormat, int glyphCount, 1444ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt GrBatchFontCache* fontCache) { 1445ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt return SkNEW_ARGS(BitmapTextBatch, (maskFormat, glyphCount, fontCache)); 14461d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 14471d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 14489bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt static BitmapTextBatch* Create(GrMaskFormat maskFormat, int glyphCount, 14499bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt GrBatchFontCache* fontCache, 14509bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt DistanceAdjustTable* distanceAdjustTable, 14519bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkColor filteredColor, bool useLCDText, 14529bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt bool useBGR, float gamma) { 14539bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt return SkNEW_ARGS(BitmapTextBatch, (maskFormat, glyphCount, fontCache, distanceAdjustTable, 14549bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt filteredColor, useLCDText, useBGR, gamma)); 14559bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 14569bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 14571d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt const char* name() const override { return "BitmapTextBatch"; } 14581d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 14591d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt void getInvariantOutputColor(GrInitInvariantOutput* out) const override { 14601d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt if (kARGB_GrMaskFormat == fMaskFormat) { 14611d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt out->setUnknownFourComponents(); 14621d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } else { 14631d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt out->setKnownFourComponents(fBatch.fColor); 14641d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 14651d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 14661d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 14671d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override { 14689bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (!fUseDistanceFields) { 14699bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // Bitmap Text 14709bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (kARGB_GrMaskFormat != fMaskFormat) { 14719bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (GrPixelConfigIsAlphaOnly(fPixelConfig)) { 14729bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt out->setUnknownSingleComponent(); 14739bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } else if (GrPixelConfigIsOpaque(fPixelConfig)) { 14749bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt out->setUnknownOpaqueFourComponents(); 14759bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt out->setUsingLCDCoverage(); 14769bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } else { 14779bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt out->setUnknownFourComponents(); 14789bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt out->setUsingLCDCoverage(); 14799bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 14809bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } else { 14819bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt out->setKnownSingleComponent(0xff); 14829bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 14839bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } else { 14849bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // Distance fields 14859bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (!fUseLCDText) { 14861d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt out->setUnknownSingleComponent(); 14871d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } else { 14881d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt out->setUnknownFourComponents(); 14891d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt out->setUsingLCDCoverage(); 14901d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 14911d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 14921d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 14931d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 14941d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt void initBatchTracker(const GrPipelineInfo& init) override { 14951d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // Handle any color overrides 14961d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt if (init.fColorIgnored) { 14971d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt fBatch.fColor = GrColor_ILLEGAL; 14981d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } else if (GrColor_ILLEGAL != init.fOverrideColor) { 14991d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt fBatch.fColor = init.fOverrideColor; 15001d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 15011d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 15021d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // setup batch properties 15031d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt fBatch.fColorIgnored = init.fColorIgnored; 15041d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt fBatch.fUsesLocalCoords = init.fUsesLocalCoords; 15051d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt fBatch.fCoverageIgnored = init.fCoverageIgnored; 15061d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 15071d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 1508b5238a7571c243ba4a154a62575570c3078b3741bsalomon struct FlushInfo { 1509b5238a7571c243ba4a154a62575570c3078b3741bsalomon SkAutoTUnref<const GrVertexBuffer> fVertexBuffer; 1510b5238a7571c243ba4a154a62575570c3078b3741bsalomon SkAutoTUnref<const GrIndexBuffer> fIndexBuffer; 1511b5238a7571c243ba4a154a62575570c3078b3741bsalomon int fGlyphsToFlush; 1512b5238a7571c243ba4a154a62575570c3078b3741bsalomon int fVertexOffset; 1513b5238a7571c243ba4a154a62575570c3078b3741bsalomon }; 1514b5238a7571c243ba4a154a62575570c3078b3741bsalomon 15151d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) override { 15161d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // if we have RGB, then we won't have any SkShaders so no need to use a localmatrix. 15171d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // TODO actually only invert if we don't have RGBA 15181d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkMatrix localMatrix; 15191d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt if (this->usesLocalCoords() && !this->viewMatrix().invert(&localMatrix)) { 15201d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkDebugf("Cannot invert viewmatrix\n"); 15211d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt return; 15221d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 15231d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 152462db8ba68b980245e0927b792747864ebd6fcb6ajoshualitt GrTexture* texture = fFontCache->getTexture(fMaskFormat); 152562db8ba68b980245e0927b792747864ebd6fcb6ajoshualitt if (!texture) { 152662db8ba68b980245e0927b792747864ebd6fcb6ajoshualitt SkDebugf("Could not allocate backing texture for atlas\n"); 152762db8ba68b980245e0927b792747864ebd6fcb6ajoshualitt return; 152862db8ba68b980245e0927b792747864ebd6fcb6ajoshualitt } 152962db8ba68b980245e0927b792747864ebd6fcb6ajoshualitt 15309bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkAutoTUnref<const GrGeometryProcessor> gp; 15319bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (fUseDistanceFields) { 15329bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt gp.reset(this->setupDfProcessor(this->viewMatrix(), fFilteredColor, this->color(), 15339bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt texture)); 15349bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } else { 15359bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kNone_FilterMode); 15369bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt gp.reset(GrBitmapTextGeoProc::Create(this->color(), 15379bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt texture, 15389bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt params, 15399bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt fMaskFormat, 15409bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt localMatrix)); 15419bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 15421d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 1543b5238a7571c243ba4a154a62575570c3078b3741bsalomon FlushInfo flushInfo; 1544b5238a7571c243ba4a154a62575570c3078b3741bsalomon flushInfo.fGlyphsToFlush = 0; 15451d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt size_t vertexStride = gp->getVertexStride(); 15469bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkASSERT(vertexStride == (fUseDistanceFields ? 15479bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt get_vertex_stride_df(fMaskFormat, fUseLCDText) : 15489bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt get_vertex_stride(fMaskFormat))); 15491d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 15501d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt this->initDraw(batchTarget, gp, pipeline); 15511d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 15521d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt int glyphCount = this->numGlyphs(); 1553ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt int instanceCount = fInstanceCount; 15548415abe44cf205ac214b7793c076fd8c13272240bsalomon const GrVertexBuffer* vertexBuffer; 1555b5238a7571c243ba4a154a62575570c3078b3741bsalomon 1556e40d39725908d99d255496025411e5c9ca32663erobertphillips void* vertices = batchTarget->makeVertSpace(vertexStride, 1557e40d39725908d99d255496025411e5c9ca32663erobertphillips glyphCount * kVerticesPerGlyph, 1558e40d39725908d99d255496025411e5c9ca32663erobertphillips &vertexBuffer, 1559e40d39725908d99d255496025411e5c9ca32663erobertphillips &flushInfo.fVertexOffset); 1560b5238a7571c243ba4a154a62575570c3078b3741bsalomon flushInfo.fVertexBuffer.reset(SkRef(vertexBuffer)); 1561b5238a7571c243ba4a154a62575570c3078b3741bsalomon flushInfo.fIndexBuffer.reset(batchTarget->resourceProvider()->refQuadIndexBuffer()); 1562b5238a7571c243ba4a154a62575570c3078b3741bsalomon if (!vertices || !flushInfo.fVertexBuffer) { 15631d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkDebugf("Could not allocate vertices\n"); 15641d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt return; 15651d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 15661d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 15671d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt unsigned char* currVertex = reinterpret_cast<unsigned char*>(vertices); 15681d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 156925ba7ea2ed4e8795767a69619d972242313d94d7joshualitt // We cache some values to avoid going to the glyphcache for the same fontScaler twice 157025ba7ea2ed4e8795767a69619d972242313d94d7joshualitt // in a row 157125ba7ea2ed4e8795767a69619d972242313d94d7joshualitt const SkDescriptor* desc = NULL; 157225ba7ea2ed4e8795767a69619d972242313d94d7joshualitt SkGlyphCache* cache = NULL; 157325ba7ea2ed4e8795767a69619d972242313d94d7joshualitt GrFontScaler* scaler = NULL; 157425ba7ea2ed4e8795767a69619d972242313d94d7joshualitt SkTypeface* typeface = NULL; 157525ba7ea2ed4e8795767a69619d972242313d94d7joshualitt 15761d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt for (int i = 0; i < instanceCount; i++) { 15771d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt Geometry& args = fGeoData[i]; 15781d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt Blob* blob = args.fBlob; 15791d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt Run& run = blob->fRuns[args.fRun]; 15801d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt TextInfo& info = run.fSubRunInfo[args.fSubRun]; 15811d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 15821d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt uint64_t currentAtlasGen = fFontCache->atlasGeneration(fMaskFormat); 15831d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt bool regenerateTextureCoords = info.fAtlasGeneration != currentAtlasGen; 15849bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt bool regenerateColors; 15859bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (fUseDistanceFields) { 1586fcfb9fc4bde43fd375ce8e0d6583282dad4a1226joshualitt regenerateColors = !fUseLCDText && run.fColor != args.fColor; 15879bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } else { 15889bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt regenerateColors = kA8_GrMaskFormat == fMaskFormat && run.fColor != args.fColor; 15899bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 15902a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt bool regeneratePositions = args.fTransX != 0.f || args.fTransY != 0.f; 15911d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt int glyphCount = info.fGlyphEndIndex - info.fGlyphStartIndex; 15921d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 15931d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // We regenerate both texture coords and colors in the blob itself, and update the 15941d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // atlas generation. If we don't end up purging any unused plots, we can avoid 15951d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // regenerating the coords. We could take a finer grained approach to updating texture 15961d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // coords but its not clear if the extra bookkeeping would offset any gains. 15971d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // To avoid looping over the glyphs twice, we do one loop and conditionally update color 15981d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // or coords as needed. One final note, if we have to break a run for an atlas eviction 15991d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // then we can't really trust the atlas has all of the correct data. Atlas evictions 16001d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // should be pretty rare, so we just always regenerate in those cases 16012a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt if (regenerateTextureCoords || regenerateColors || regeneratePositions) { 16021d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // first regenerate texture coordinates / colors if need be 16031d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt bool brokenRun = false; 1604ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt 1605ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt // Because the GrBatchFontCache may evict the strike a blob depends on using for 1606ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt // generating its texture coords, we have to track whether or not the strike has 1607ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt // been abandoned. If it hasn't been abandoned, then we can use the GrGlyph*s as is 1608ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt // otherwise we have to get the new strike, and use that to get the correct glyphs. 1609ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt // Because we do not have the packed ids, and thus can't look up our glyphs in the 1610ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt // new strike, we instead keep our ref to the old strike and use the packed ids from 1611ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt // it. These ids will still be valid as long as we hold the ref. When we are done 1612ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt // updating our cache of the GrGlyph*s, we drop our ref on the old strike 1613ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt bool regenerateGlyphs = false; 1614ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt GrBatchTextStrike* strike = NULL; 16151d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt if (regenerateTextureCoords) { 1616b4c507e03386f2105e33f0c4c09b4a9d0a23196djoshualitt info.fBulkUseToken.reset(); 161725ba7ea2ed4e8795767a69619d972242313d94d7joshualitt 161825ba7ea2ed4e8795767a69619d972242313d94d7joshualitt // We can reuse if we have a valid strike and our descriptors / typeface are the 161925ba7ea2ed4e8795767a69619d972242313d94d7joshualitt // same 162097202d2821c2b9e997d36146ecb9711e02fd7734joshualitt const SkDescriptor* newDesc = run.fOverrideDescriptor ? 162197202d2821c2b9e997d36146ecb9711e02fd7734joshualitt run.fOverrideDescriptor->getDesc() : 162225ba7ea2ed4e8795767a69619d972242313d94d7joshualitt run.fDescriptor.getDesc(); 162325ba7ea2ed4e8795767a69619d972242313d94d7joshualitt if (!cache || !SkTypeface::Equal(typeface, run.fTypeface) || 162425ba7ea2ed4e8795767a69619d972242313d94d7joshualitt !(desc->equals(*newDesc))) { 162525ba7ea2ed4e8795767a69619d972242313d94d7joshualitt if (cache) { 162625ba7ea2ed4e8795767a69619d972242313d94d7joshualitt SkGlyphCache::AttachCache(cache); 162725ba7ea2ed4e8795767a69619d972242313d94d7joshualitt } 162825ba7ea2ed4e8795767a69619d972242313d94d7joshualitt desc = newDesc; 162925ba7ea2ed4e8795767a69619d972242313d94d7joshualitt cache = SkGlyphCache::DetachCache(run.fTypeface, desc); 163025ba7ea2ed4e8795767a69619d972242313d94d7joshualitt scaler = GrTextContext::GetGrFontScaler(cache); 1631ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt strike = run.fStrike; 163225ba7ea2ed4e8795767a69619d972242313d94d7joshualitt typeface = run.fTypeface; 163325ba7ea2ed4e8795767a69619d972242313d94d7joshualitt } 1634ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt 1635ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt if (run.fStrike->isAbandoned()) { 1636ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt regenerateGlyphs = true; 1637ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt strike = fFontCache->getStrike(scaler); 1638ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt } else { 1639ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt strike = run.fStrike; 1640ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt } 16411d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 16421d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 1643ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt for (int glyphIdx = 0; glyphIdx < glyphCount; glyphIdx++) { 16441d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt if (regenerateTextureCoords) { 1645ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt size_t glyphOffset = glyphIdx + info.fGlyphStartIndex; 1646ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt GrGlyph* glyph; 1647ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt if (regenerateGlyphs) { 1648ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt // Get the id from the old glyph, and use the new strike to lookup 1649ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt // the glyph. 1650ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt glyph = blob->fGlyphs[glyphOffset]; 1651ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt blob->fGlyphs[glyphOffset] = strike->getGlyph(glyph->fPackedID, 1652ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt scaler); 1653ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt } 1654ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt glyph = blob->fGlyphs[glyphOffset]; 16551d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkASSERT(glyph); 16561d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 16571d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt if (!fFontCache->hasGlyph(glyph) && 16581d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt !strike->addGlyphToAtlas(batchTarget, glyph, scaler)) { 1659b5238a7571c243ba4a154a62575570c3078b3741bsalomon this->flush(batchTarget, &flushInfo); 16601d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt this->initDraw(batchTarget, gp, pipeline); 16611d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt brokenRun = glyphIdx > 0; 16621d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 1663ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt SkDEBUGCODE(bool success =) strike->addGlyphToAtlas(batchTarget, 1664ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt glyph, 16651d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt scaler); 16661d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkASSERT(success); 16671d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 1668b4c507e03386f2105e33f0c4c09b4a9d0a23196djoshualitt fFontCache->addGlyphToBulkAndSetUseToken(&info.fBulkUseToken, glyph, 1669b4c507e03386f2105e33f0c4c09b4a9d0a23196djoshualitt batchTarget->currentToken()); 16701d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 16711d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // Texture coords are the last vertex attribute so we get a pointer to the 16721d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // first one and then map with stride in regenerateTextureCoords 16731d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVertices); 16741d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt vertex += info.fVertexStartIndex; 16751d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt vertex += vertexStride * glyphIdx * kVerticesPerGlyph; 16761d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt vertex += vertexStride - sizeof(SkIPoint16); 16771d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 16781d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt this->regenerateTextureCoords(glyph, vertex, vertexStride); 16791d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 16801d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 16811d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt if (regenerateColors) { 16821d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVertices); 16831d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt vertex += info.fVertexStartIndex; 16841d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt vertex += vertexStride * glyphIdx * kVerticesPerGlyph + sizeof(SkPoint); 16851d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt this->regenerateColors(vertex, vertexStride, args.fColor); 16861d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 16871d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 16882a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt if (regeneratePositions) { 16892a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVertices); 16902a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt vertex += info.fVertexStartIndex; 16912a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt vertex += vertexStride * glyphIdx * kVerticesPerGlyph; 16922a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt SkScalar transX = args.fTransX; 16932a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt SkScalar transY = args.fTransY; 16942a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt this->regeneratePositions(vertex, vertexStride, transX, transY); 16952a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt } 1696b5238a7571c243ba4a154a62575570c3078b3741bsalomon flushInfo.fGlyphsToFlush++; 16971d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 16981d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 16992a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt // We my have changed the color so update it here 17002a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt run.fColor = args.fColor; 17011d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt if (regenerateTextureCoords) { 1702ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt if (regenerateGlyphs) { 1703ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt run.fStrike.reset(SkRef(strike)); 1704ae32c102e70577bff1432ef4b4b63ca6835012f6joshualitt } 17051d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt info.fAtlasGeneration = brokenRun ? GrBatchAtlas::kInvalidAtlasGeneration : 17061d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt fFontCache->atlasGeneration(fMaskFormat); 17071d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 17081d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } else { 1709b5238a7571c243ba4a154a62575570c3078b3741bsalomon flushInfo.fGlyphsToFlush += glyphCount; 1710b4c507e03386f2105e33f0c4c09b4a9d0a23196djoshualitt 1711b4c507e03386f2105e33f0c4c09b4a9d0a23196djoshualitt // set use tokens for all of the glyphs in our subrun. This is only valid if we 1712b4c507e03386f2105e33f0c4c09b4a9d0a23196djoshualitt // have a valid atlas generation 1713b4c507e03386f2105e33f0c4c09b4a9d0a23196djoshualitt fFontCache->setUseTokenBulk(info.fBulkUseToken, 1714b4c507e03386f2105e33f0c4c09b4a9d0a23196djoshualitt batchTarget->currentToken(), 1715b4c507e03386f2105e33f0c4c09b4a9d0a23196djoshualitt fMaskFormat); 17161d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 17171d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 17181d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // now copy all vertices 17191d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt size_t byteCount = info.fVertexEndIndex - info.fVertexStartIndex; 17201d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt memcpy(currVertex, blob->fVertices + info.fVertexStartIndex, byteCount); 17211d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 17221d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt currVertex += byteCount; 17231d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 172425ba7ea2ed4e8795767a69619d972242313d94d7joshualitt // Make sure to attach the last cache if applicable 172525ba7ea2ed4e8795767a69619d972242313d94d7joshualitt if (cache) { 172625ba7ea2ed4e8795767a69619d972242313d94d7joshualitt SkGlyphCache::AttachCache(cache); 172725ba7ea2ed4e8795767a69619d972242313d94d7joshualitt } 1728b5238a7571c243ba4a154a62575570c3078b3741bsalomon this->flush(batchTarget, &flushInfo); 17291d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 17301d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 1731ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt // The minimum number of Geometry we will try to allocate. 1732ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt static const int kMinAllocated = 32; 1733ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt 1734ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt // Total number of Geometry this Batch owns 1735ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt int instanceCount() const { return fInstanceCount; } 1736ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt SkAutoSTMalloc<kMinAllocated, Geometry>* geoData() { return &fGeoData; } 1737ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt 1738ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt // to avoid even the initial copy of the struct, we have a getter for the first item which 1739ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt // is used to seed the batch with its initial geometry. After seeding, the client should call 1740ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt // init() so the Batch can initialize itself 1741ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt Geometry& geometry() { return fGeoData[0]; } 1742ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt void init() { 1743444987fea8e6be1ff89ecce14ef0d934e7d3eb04joshualitt const Geometry& geo = fGeoData[0]; 1744444987fea8e6be1ff89ecce14ef0d934e7d3eb04joshualitt fBatch.fColor = geo.fColor; 1745444987fea8e6be1ff89ecce14ef0d934e7d3eb04joshualitt fBatch.fViewMatrix = geo.fBlob->fViewMatrix; 1746444987fea8e6be1ff89ecce14ef0d934e7d3eb04joshualitt 1747444987fea8e6be1ff89ecce14ef0d934e7d3eb04joshualitt // We don't yet position distance field text on the cpu, so we have to map the vertex bounds 1748444987fea8e6be1ff89ecce14ef0d934e7d3eb04joshualitt // into device space 1749444987fea8e6be1ff89ecce14ef0d934e7d3eb04joshualitt const Run& run = geo.fBlob->fRuns[geo.fRun]; 1750444987fea8e6be1ff89ecce14ef0d934e7d3eb04joshualitt if (run.fSubRunInfo[geo.fSubRun].fDrawAsDistanceFields) { 1751444987fea8e6be1ff89ecce14ef0d934e7d3eb04joshualitt SkRect bounds = run.fVertexBounds; 1752444987fea8e6be1ff89ecce14ef0d934e7d3eb04joshualitt fBatch.fViewMatrix.mapRect(&bounds); 1753444987fea8e6be1ff89ecce14ef0d934e7d3eb04joshualitt this->setBounds(bounds); 1754444987fea8e6be1ff89ecce14ef0d934e7d3eb04joshualitt } else { 1755444987fea8e6be1ff89ecce14ef0d934e7d3eb04joshualitt this->setBounds(run.fVertexBounds); 1756444987fea8e6be1ff89ecce14ef0d934e7d3eb04joshualitt } 1757ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt } 17581d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 17591d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualittprivate: 17609bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt BitmapTextBatch(GrMaskFormat maskFormat, int glyphCount, GrBatchFontCache* fontCache) 17619bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt : fMaskFormat(maskFormat) 17629bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt , fPixelConfig(fontCache->getPixelConfig(maskFormat)) 17639bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt , fFontCache(fontCache) 17649bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt , fUseDistanceFields(false) { 17659bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt this->initClassID<BitmapTextBatch>(); 17669bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt fBatch.fNumGlyphs = glyphCount; 17679bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt fInstanceCount = 1; 17689bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt fAllocatedCount = kMinAllocated; 17699bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 17709bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 17719bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt BitmapTextBatch(GrMaskFormat maskFormat, int glyphCount, GrBatchFontCache* fontCache, 17729bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt DistanceAdjustTable* distanceAdjustTable, SkColor filteredColor, 17739bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt bool useLCDText, bool useBGR, float gamma) 17741d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt : fMaskFormat(maskFormat) 17751d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt , fPixelConfig(fontCache->getPixelConfig(maskFormat)) 17769bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt , fFontCache(fontCache) 17779bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt , fDistanceAdjustTable(SkRef(distanceAdjustTable)) 17789bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt , fFilteredColor(filteredColor) 17799bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt , fUseDistanceFields(true) 17809bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt , fUseLCDText(useLCDText) 17819bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt , fUseBGR(useBGR) 17829bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt , fGamma(gamma) { 17831d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt this->initClassID<BitmapTextBatch>(); 17841d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt fBatch.fNumGlyphs = glyphCount; 1785ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt fInstanceCount = 1; 1786ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt fAllocatedCount = kMinAllocated; 17879bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkASSERT(fMaskFormat == kA8_GrMaskFormat); 1788ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt } 1789ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt 1790ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt ~BitmapTextBatch() { 1791ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt for (int i = 0; i < fInstanceCount; i++) { 1792ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt fGeoData[i].fBlob->unref(); 1793ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt } 17941d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 17951d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 17961d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt void regenerateTextureCoords(GrGlyph* glyph, intptr_t vertex, size_t vertexStride) { 17971d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt int width = glyph->fBounds.width(); 17981d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt int height = glyph->fBounds.height(); 17991d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 18009bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt int u0, v0, u1, v1; 18019bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (fUseDistanceFields) { 18029bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt u0 = glyph->fAtlasLocation.fX + SK_DistanceFieldInset; 18039bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt v0 = glyph->fAtlasLocation.fY + SK_DistanceFieldInset; 18049bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt u1 = u0 + width - 2 * SK_DistanceFieldInset; 18059bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt v1 = v0 + height - 2 * SK_DistanceFieldInset; 18069bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } else { 18079bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt u0 = glyph->fAtlasLocation.fX; 18089bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt v0 = glyph->fAtlasLocation.fY; 18099bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt u1 = u0 + width; 18109bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt v1 = v0 + height; 18119bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 18129bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 18131d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkIPoint16* textureCoords; 18141d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // V0 18151d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt textureCoords = reinterpret_cast<SkIPoint16*>(vertex); 18161d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt textureCoords->set(u0, v0); 18171d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt vertex += vertexStride; 18181d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 18191d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // V1 18201d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt textureCoords = reinterpret_cast<SkIPoint16*>(vertex); 18211d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt textureCoords->set(u0, v1); 18221d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt vertex += vertexStride; 18231d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 18241d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // V2 18251d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt textureCoords = reinterpret_cast<SkIPoint16*>(vertex); 18261d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt textureCoords->set(u1, v1); 18271d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt vertex += vertexStride; 18281d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 18291d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // V3 18301d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt textureCoords = reinterpret_cast<SkIPoint16*>(vertex); 18311d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt textureCoords->set(u1, v0); 18321d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 18331d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 18341d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt void regenerateColors(intptr_t vertex, size_t vertexStride, GrColor color) { 18351d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt for (int i = 0; i < kVerticesPerGlyph; i++) { 18361d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkColor* vcolor = reinterpret_cast<SkColor*>(vertex); 18371d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt *vcolor = color; 18381d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt vertex += vertexStride; 18391d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 18401d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 18411d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 18422a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt void regeneratePositions(intptr_t vertex, size_t vertexStride, SkScalar transX, 18432a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt SkScalar transY) { 18442a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt for (int i = 0; i < kVerticesPerGlyph; i++) { 18452a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt SkPoint* point = reinterpret_cast<SkPoint*>(vertex); 18462a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt point->fX += transX; 18472a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt point->fY += transY; 18482a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt vertex += vertexStride; 18492a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt } 18502a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt } 18512a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt 18521d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt void initDraw(GrBatchTarget* batchTarget, 18531d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt const GrGeometryProcessor* gp, 18541d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt const GrPipeline* pipeline) { 18551d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt batchTarget->initDraw(gp, pipeline); 18561d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 18571d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt // TODO remove this when batch is everywhere 18581d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt GrPipelineInfo init; 18591d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt init.fColorIgnored = fBatch.fColorIgnored; 18601d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt init.fOverrideColor = GrColor_ILLEGAL; 18611d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt init.fCoverageIgnored = fBatch.fCoverageIgnored; 18621d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt init.fUsesLocalCoords = this->usesLocalCoords(); 18631d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt gp->initBatchTracker(batchTarget->currentBatchTracker(), init); 18641d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 18651d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 1866b5238a7571c243ba4a154a62575570c3078b3741bsalomon void flush(GrBatchTarget* batchTarget, FlushInfo* flushInfo) { 1867cb8979d088a66ebaf41f10ba6f5c830615aa0e03bsalomon GrVertices vertices; 1868b5238a7571c243ba4a154a62575570c3078b3741bsalomon int maxGlyphsPerDraw = flushInfo->fIndexBuffer->maxQuads(); 1869cb8979d088a66ebaf41f10ba6f5c830615aa0e03bsalomon vertices.initInstanced(kTriangles_GrPrimitiveType, flushInfo->fVertexBuffer, 1870b5238a7571c243ba4a154a62575570c3078b3741bsalomon flushInfo->fIndexBuffer, flushInfo->fVertexOffset, 1871e64eb570a5b9480bc24d0656ccabcff1ab13a229bsalomon kVerticesPerGlyph, kIndicesPerGlyph, flushInfo->fGlyphsToFlush, 1872b5238a7571c243ba4a154a62575570c3078b3741bsalomon maxGlyphsPerDraw); 1873e64eb570a5b9480bc24d0656ccabcff1ab13a229bsalomon batchTarget->draw(vertices); 1874b5238a7571c243ba4a154a62575570c3078b3741bsalomon flushInfo->fVertexOffset += kVerticesPerGlyph * flushInfo->fGlyphsToFlush; 1875b5238a7571c243ba4a154a62575570c3078b3741bsalomon flushInfo->fGlyphsToFlush = 0; 18761d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 18771d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 18781d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt GrColor color() const { return fBatch.fColor; } 18791d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt const SkMatrix& viewMatrix() const { return fBatch.fViewMatrix; } 18801d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; } 18811d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt int numGlyphs() const { return fBatch.fNumGlyphs; } 18821d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 18831d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt bool onCombineIfPossible(GrBatch* t) override { 18841d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt BitmapTextBatch* that = t->cast<BitmapTextBatch>(); 18851d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 18869bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (fUseDistanceFields != that->fUseDistanceFields) { 18871d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt return false; 18881d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 18891d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 18909bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (!fUseDistanceFields) { 18919bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // Bitmap Text 18929bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (fMaskFormat != that->fMaskFormat) { 18939bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt return false; 18949bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 18951d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 18969bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // TODO we can often batch across LCD text if we have dual source blending and don't 18979bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // have to use the blend constant 18989bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (fMaskFormat != kA8_GrMaskFormat && this->color() != that->color()) { 18999bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt return false; 19009bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 19019bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 19029bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->viewMatrix())) { 19039bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt return false; 19049bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 19059bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } else { 19069bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // Distance Fields 19079bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkASSERT(this->fMaskFormat == that->fMaskFormat && 19089bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt this->fMaskFormat == kA8_GrMaskFormat); 19099bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 19109bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) { 19119bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt return false; 19129bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 19139bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 19149bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (fFilteredColor != that->fFilteredColor) { 19159bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt return false; 19169bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 19179bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 19189bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (fUseLCDText != that->fUseLCDText) { 19199bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt return false; 19209bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 19219bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 19229bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (fUseBGR != that->fUseBGR) { 19239bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt return false; 19249bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 19259bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 19269bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (fGamma != that->fGamma) { 19279bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt return false; 19289bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 19299bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 19309bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // TODO see note above 19319bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (fUseLCDText && this->color() != that->color()) { 19329bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt return false; 19339bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 19341d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 19351d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 19361d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt fBatch.fNumGlyphs += that->numGlyphs(); 1937ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt 1938ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt // copy that->geoData(). We do this manually for performance reasons 1939ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt SkAutoSTMalloc<kMinAllocated, Geometry>* otherGeoData = that->geoData(); 1940ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt int otherInstanceCount = that->instanceCount(); 1941ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt int allocSize = otherInstanceCount + fInstanceCount; 1942ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt if (allocSize > fAllocatedCount) { 1943ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt while (allocSize > fAllocatedCount) { 1944ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt fAllocatedCount = fAllocatedCount << 1; 1945ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt } 1946ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt fGeoData.realloc(fAllocatedCount); 1947ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt } 1948ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt 1949ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt memcpy(&fGeoData[fInstanceCount], otherGeoData->get(), 1950ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt otherInstanceCount * sizeof(Geometry)); 1951ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt int total = fInstanceCount + otherInstanceCount; 1952ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt for (int i = fInstanceCount; i < total; i++) { 1953ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt fGeoData[i].fBlob->ref(); 1954ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt } 1955ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt fInstanceCount = total; 195699c7c07e0f1f7b78980eb21d84bebda8b45a7178joshualitt 195799c7c07e0f1f7b78980eb21d84bebda8b45a7178joshualitt this->joinBounds(that->bounds()); 19581d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt return true; 19591d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 19601d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 19619bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // TODO just use class params 19629bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // TODO trying to figure out why lcd is so whack 19639bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt GrGeometryProcessor* setupDfProcessor(const SkMatrix& viewMatrix, SkColor filteredColor, 19649bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt GrColor color, GrTexture* texture) { 19659bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBilerp_FilterMode); 19669bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 19679bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // set up any flags 19689bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt uint32_t flags = 0; 19699bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt flags |= viewMatrix.isSimilarity() ? kSimilarity_DistanceFieldEffectFlag : 0; 19709bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt flags |= fUseLCDText ? kUseLCD_DistanceFieldEffectFlag : 0; 19719bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt flags |= fUseLCDText && viewMatrix.rectStaysRect() ? 19729bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt kRectToRect_DistanceFieldEffectFlag : 0; 19739bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt flags |= fUseLCDText && fUseBGR ? kBGR_DistanceFieldEffectFlag : 0; 19749bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 19759bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // see if we need to create a new effect 19769bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt if (fUseLCDText) { 19779bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredColor); 19789bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 19799bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt float redCorrection = 19809bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt (*fDistanceAdjustTable)[GrColorUnpackR(colorNoPreMul) >> kDistanceAdjustLumShift]; 19819bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt float greenCorrection = 19829bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt (*fDistanceAdjustTable)[GrColorUnpackG(colorNoPreMul) >> kDistanceAdjustLumShift]; 19839bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt float blueCorrection = 19849bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt (*fDistanceAdjustTable)[GrColorUnpackB(colorNoPreMul) >> kDistanceAdjustLumShift]; 19859bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt GrDistanceFieldLCDTextGeoProc::DistanceAdjust widthAdjust = 19869bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt GrDistanceFieldLCDTextGeoProc::DistanceAdjust::Make(redCorrection, 19879bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt greenCorrection, 19889bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt blueCorrection); 19899bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 19909bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt return GrDistanceFieldLCDTextGeoProc::Create(color, 19919bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt viewMatrix, 19929bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt texture, 19939bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt params, 19949bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt widthAdjust, 19959bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt flags); 19969bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } else { 19979bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt flags |= kColorAttr_DistanceFieldEffectFlag; 19989bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt#ifdef SK_GAMMA_APPLY_TO_A8 19999bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt U8CPU lum = SkColorSpaceLuminance::computeLuminance(fGamma, filteredColor); 20009bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt float correction = (*fDistanceAdjustTable)[lum >> kDistanceAdjustLumShift]; 20019bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt return GrDistanceFieldA8TextGeoProc::Create(color, 20029bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt viewMatrix, 20039bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt texture, 20049bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt params, 20059bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt correction, 20061ba8cc9193f13a812401e14b8037fdcf3f3acbacjoshualitt flags); 20079bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt#else 20089bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt return GrDistanceFieldA8TextGeoProc::Create(color, 20099bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt viewMatrix, 20109bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt texture, 20119bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt params, 20121ba8cc9193f13a812401e14b8037fdcf3f3acbacjoshualitt flags); 20139bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt#endif 20149bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 20159bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 20169bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt } 20179bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 20181d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt struct BatchTracker { 20191d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt GrColor fColor; 20201d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt SkMatrix fViewMatrix; 20211d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt bool fUsesLocalCoords; 20221d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt bool fColorIgnored; 20231d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt bool fCoverageIgnored; 20241d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt int fNumGlyphs; 20251d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt }; 20261d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 20271d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt BatchTracker fBatch; 2028ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt SkAutoSTMalloc<kMinAllocated, Geometry> fGeoData; 2029ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt int fInstanceCount; 2030ad802c66c96e40016d4ba13b6dac3e6c6f17a774joshualitt int fAllocatedCount; 20311d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt GrMaskFormat fMaskFormat; 20321d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt GrPixelConfig fPixelConfig; 20331d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt GrBatchFontCache* fFontCache; 20349bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt 20359bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt // Distance field properties 20369bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkAutoTUnref<DistanceAdjustTable> fDistanceAdjustTable; 20379bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkColor fFilteredColor; 20389bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt bool fUseDistanceFields; 20399bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt bool fUseLCDText; 20409bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt bool fUseBGR; 20419bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt float fGamma; 20421d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt}; 20431d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 20449a27e639481882b59a8ef123e0b69a9a719f08b9joshualittvoid GrAtlasTextContext::flushRunAsPaths(const SkTextBlob::RunIterator& it, const SkPaint& skPaint, 20459a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt SkDrawFilter* drawFilter, const SkMatrix& viewMatrix, 20469a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt const SkIRect& clipBounds, SkScalar x, SkScalar y) { 20479a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt SkPaint runPaint = skPaint; 20481d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 20499a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt size_t textLen = it.glyphCount() * sizeof(uint16_t); 20509a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt const SkPoint& offset = it.offset(); 20511d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 20529a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt it.applyFontToPaint(&runPaint); 20539a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt 20549a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt if (drawFilter && !drawFilter->filter(&runPaint, SkDrawFilter::kText_Type)) { 20559a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt return; 20569a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt } 20579a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt 20589a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt runPaint.setFlags(fGpuDevice->filterTextFlags(runPaint)); 20599a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt 20609a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt switch (it.positioning()) { 20619a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt case SkTextBlob::kDefault_Positioning: 20629a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt this->drawTextAsPath(runPaint, viewMatrix, (const char *)it.glyphs(), 20639a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt textLen, x + offset.x(), y + offset.y(), clipBounds); 20649a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt break; 20659a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt case SkTextBlob::kHorizontal_Positioning: 20669a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt this->drawPosTextAsPath(runPaint, viewMatrix, (const char*)it.glyphs(), 20679a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt textLen, it.pos(), 1, SkPoint::Make(x, y + offset.y()), 20689a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt clipBounds); 20699a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt break; 20709a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt case SkTextBlob::kFull_Positioning: 20719a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt this->drawPosTextAsPath(runPaint, viewMatrix, (const char*)it.glyphs(), 20729a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt textLen, it.pos(), 2, SkPoint::Make(x, y), clipBounds); 20739a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt break; 20749a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt } 20759a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt} 20769a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt 207779dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt 207879dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualittinline BitmapTextBatch* 207979dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualittGrAtlasTextContext::createBatch(BitmapTextBlob* cacheBlob, const PerSubRunInfo& info, 208079dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt int glyphCount, int run, int subRun, 208179dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt GrColor color, SkScalar transX, SkScalar transY, 208279dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt const SkPaint& skPaint) { 208379dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt GrMaskFormat format = info.fMaskFormat; 208479dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt GrColor subRunColor; 208579dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt if (kARGB_GrMaskFormat == format) { 208679dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt uint8_t paintAlpha = skPaint.getAlpha(); 208779dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt subRunColor = SkColorSetARGB(paintAlpha, paintAlpha, paintAlpha, paintAlpha); 208879dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt } else { 208979dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt subRunColor = color; 209079dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt } 209179dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt 209279dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt BitmapTextBatch* batch; 209379dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt if (info.fDrawAsDistanceFields) { 209479dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt SkColor filteredColor; 209579dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt SkColorFilter* colorFilter = skPaint.getColorFilter(); 209679dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt if (colorFilter) { 209779dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt filteredColor = colorFilter->filterColor(skPaint.getColor()); 209879dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt } else { 209979dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt filteredColor = skPaint.getColor(); 210079dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt } 210179dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt bool useBGR = SkPixelGeometryIsBGR(fDeviceProperties.pixelGeometry()); 210279dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt float gamma = fDeviceProperties.gamma(); 210379dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt batch = BitmapTextBatch::Create(format, glyphCount, fContext->getBatchFontCache(), 210479dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt fDistanceAdjustTable, filteredColor, 210579dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt info.fUseLCDText, useBGR, 210679dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt gamma); 210779dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt } else { 210879dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt batch = BitmapTextBatch::Create(format, glyphCount, fContext->getBatchFontCache()); 210979dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt } 211079dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt BitmapTextBatch::Geometry& geometry = batch->geometry(); 211179dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt geometry.fBlob = SkRef(cacheBlob); 211279dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt geometry.fRun = run; 211379dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt geometry.fSubRun = subRun; 211479dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt geometry.fColor = subRunColor; 211579dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt geometry.fTransX = transX; 211679dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt geometry.fTransY = transY; 211779dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt batch->init(); 211879dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt 211979dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt return batch; 212079dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt} 212179dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt 21229a27e639481882b59a8ef123e0b69a9a719f08b9joshualittinline void GrAtlasTextContext::flushRun(GrDrawTarget* target, GrPipelineBuilder* pipelineBuilder, 21239a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt BitmapTextBlob* cacheBlob, int run, GrColor color, 21249bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt SkScalar transX, SkScalar transY, const SkPaint& skPaint) { 21259a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt for (int subRun = 0; subRun < cacheBlob->fRuns[run].fSubRunInfo.count(); subRun++) { 21269a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt const PerSubRunInfo& info = cacheBlob->fRuns[run].fSubRunInfo[subRun]; 21279a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt int glyphCount = info.fGlyphEndIndex - info.fGlyphStartIndex; 21289a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt if (0 == glyphCount) { 21299a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt continue; 21301d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 21319a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt 213279dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt SkAutoTUnref<BitmapTextBatch> batch(this->createBatch(cacheBlob, info, glyphCount, run, 213379dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt subRun, color, transX, transY, 213479dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt skPaint)); 213599c7c07e0f1f7b78980eb21d84bebda8b45a7178joshualitt target->drawBatch(pipelineBuilder, batch); 21361d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 21379a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt} 21381d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt 21399a27e639481882b59a8ef123e0b69a9a719f08b9joshualittinline void GrAtlasTextContext::flushBigGlyphs(BitmapTextBlob* cacheBlob, GrRenderTarget* rt, 21401107e901c9dac3098e2915213f171ff62d007aa7joshualitt const SkPaint& skPaint, 21411107e901c9dac3098e2915213f171ff62d007aa7joshualitt SkScalar transX, SkScalar transY, 21421107e901c9dac3098e2915213f171ff62d007aa7joshualitt const SkIRect& clipBounds) { 2143fc0725645cee5dabc8d282da4c1fab7335152e15joshualitt if (!cacheBlob->fBigGlyphs.count()) { 2144fc0725645cee5dabc8d282da4c1fab7335152e15joshualitt return; 2145fc0725645cee5dabc8d282da4c1fab7335152e15joshualitt } 2146fc0725645cee5dabc8d282da4c1fab7335152e15joshualitt 2147fc0725645cee5dabc8d282da4c1fab7335152e15joshualitt SkMatrix pathMatrix; 2148fc0725645cee5dabc8d282da4c1fab7335152e15joshualitt if (!cacheBlob->fViewMatrix.invert(&pathMatrix)) { 2149fc0725645cee5dabc8d282da4c1fab7335152e15joshualitt SkDebugf("could not invert viewmatrix\n"); 2150fc0725645cee5dabc8d282da4c1fab7335152e15joshualitt return; 2151fc0725645cee5dabc8d282da4c1fab7335152e15joshualitt } 2152fc0725645cee5dabc8d282da4c1fab7335152e15joshualitt 21539a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt for (int i = 0; i < cacheBlob->fBigGlyphs.count(); i++) { 21542a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt BitmapTextBlob::BigGlyph& bigGlyph = cacheBlob->fBigGlyphs[i]; 215519e4c02a4112f9a9c63247613c201dbba84110b4joshualitt bigGlyph.fVx += transX; 215619e4c02a4112f9a9c63247613c201dbba84110b4joshualitt bigGlyph.fVy += transY; 2157fc0725645cee5dabc8d282da4c1fab7335152e15joshualitt SkMatrix translate = cacheBlob->fViewMatrix; 2158fc0725645cee5dabc8d282da4c1fab7335152e15joshualitt translate.postTranslate(bigGlyph.fVx, bigGlyph.fVy); 2159fc0725645cee5dabc8d282da4c1fab7335152e15joshualitt 2160fc0725645cee5dabc8d282da4c1fab7335152e15joshualitt fGpuDevice->internalDrawPath(bigGlyph.fPath, skPaint, translate, &pathMatrix, clipBounds, 21611107e901c9dac3098e2915213f171ff62d007aa7joshualitt false); 21621d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt } 21631d89e8d1a46dfd8dd0a417edec5409721a1600a6joshualitt} 21649a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt 21659a27e639481882b59a8ef123e0b69a9a719f08b9joshualittvoid GrAtlasTextContext::flush(GrDrawTarget* target, 21669a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt const SkTextBlob* blob, 21679a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt BitmapTextBlob* cacheBlob, 21689a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt GrRenderTarget* rt, 21699a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt const SkPaint& skPaint, 21709a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt const GrPaint& grPaint, 21719a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt SkDrawFilter* drawFilter, 21729a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt const GrClip& clip, 21739a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt const SkMatrix& viewMatrix, 21749a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt const SkIRect& clipBounds, 21752a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt SkScalar x, SkScalar y, 21762a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt SkScalar transX, SkScalar transY) { 21779a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt // We loop through the runs of the blob, flushing each. If any run is too large, then we flush 21789a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt // it as paths 21799a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt GrPipelineBuilder pipelineBuilder; 21809a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt pipelineBuilder.setFromPaint(grPaint, rt, clip); 21819a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt 21829a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt GrColor color = grPaint.getColor(); 21839a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt 21849a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt SkTextBlob::RunIterator it(blob); 21859a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt for (int run = 0; !it.done(); it.next(), run++) { 21869a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt if (cacheBlob->fRuns[run].fDrawAsPaths) { 21879a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt this->flushRunAsPaths(it, skPaint, drawFilter, viewMatrix, clipBounds, x, y); 21889a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt continue; 21899a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt } 21902a0e9f36c6e823d2c0472ef23b4c5a247427807fjoshualitt cacheBlob->fRuns[run].fVertexBounds.offset(transX, transY); 21919bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt this->flushRun(target, &pipelineBuilder, cacheBlob, run, color, transX, transY, skPaint); 21929a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt } 21939a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt 21949a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt // Now flush big glyphs 21951107e901c9dac3098e2915213f171ff62d007aa7joshualitt this->flushBigGlyphs(cacheBlob, rt, skPaint, transX, transY, clipBounds); 21969a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt} 21979a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt 21989a27e639481882b59a8ef123e0b69a9a719f08b9joshualittvoid GrAtlasTextContext::flush(GrDrawTarget* target, 21999a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt BitmapTextBlob* cacheBlob, 22009a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt GrRenderTarget* rt, 22019a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt const SkPaint& skPaint, 22029a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt const GrPaint& grPaint, 22031107e901c9dac3098e2915213f171ff62d007aa7joshualitt const GrClip& clip, 22041107e901c9dac3098e2915213f171ff62d007aa7joshualitt const SkIRect& clipBounds) { 22059a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt GrPipelineBuilder pipelineBuilder; 22069a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt pipelineBuilder.setFromPaint(grPaint, rt, clip); 22079a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt 22089a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt GrColor color = grPaint.getColor(); 22099a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt for (int run = 0; run < cacheBlob->fRunCount; run++) { 22109bd2daff8e53a6f02c7e5d1e6aa330f89b8542a3joshualitt this->flushRun(target, &pipelineBuilder, cacheBlob, run, color, 0, 0, skPaint); 22119a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt } 22129a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt 22139a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt // Now flush big glyphs 22141107e901c9dac3098e2915213f171ff62d007aa7joshualitt this->flushBigGlyphs(cacheBlob, rt, skPaint, 0, 0, clipBounds); 22159a27e639481882b59a8ef123e0b69a9a719f08b9joshualitt} 221679dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt 221779dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt/////////////////////////////////////////////////////////////////////////////////////////////////// 221879dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt 221979dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt#ifdef GR_TEST_UTILS 222079dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt 22216c891107ce0a8431f2327cb8b2f1bfd363cabbbejoshualittBATCH_TEST_DEFINE(TextBlobBatch) { 222279dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt static uint32_t gContextID = SK_InvalidGenID; 222379dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt static GrAtlasTextContext* gTextContext = NULL; 222479dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt static SkDeviceProperties gDeviceProperties(SkDeviceProperties::kLegacyLCD_InitType); 222579dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt 222679dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt if (context->uniqueID() != gContextID) { 222779dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt gContextID = context->uniqueID(); 222879dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt SkDELETE(gTextContext); 222979dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt // We don't yet test the fall back to paths in the GrTextContext base class. This is mostly 223079dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt // because we don't really want to have a gpu device here. 223179dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt // We enable distance fields by twiddling a knob on the paint 223279dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt gTextContext = GrAtlasTextContext::Create(context, NULL, gDeviceProperties, false); 223379dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt } 223479dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt 223579dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt // create dummy render target 223679dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt GrSurfaceDesc desc; 223779dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt desc.fFlags = kRenderTarget_GrSurfaceFlag; 223879dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt desc.fWidth = 1024; 223979dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt desc.fHeight = 1024; 224079dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt desc.fConfig = kRGBA_8888_GrPixelConfig; 22411573206f202c6d2ffcffab78b17160da95a80466joshualitt desc.fSampleCnt = 0; 224279dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt SkAutoTUnref<GrTexture> texture(context->textureProvider()->createTexture(desc, true, NULL, 0)); 224379dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt SkASSERT(texture); 224479dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt SkASSERT(NULL != texture->asRenderTarget()); 224579dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt GrRenderTarget* rt = texture->asRenderTarget(); 224679dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt 224779dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt // Setup dummy SkPaint / GrPaint 224879dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt GrColor color = GrRandomColor(random); 22496c891107ce0a8431f2327cb8b2f1bfd363cabbbejoshualitt SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random); 225079dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt SkPaint skPaint; 225179dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt skPaint.setDistanceFieldTextTEMP(random->nextBool()); 225279dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt skPaint.setColor(color); 225379dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt skPaint.setLCDRenderText(random->nextBool()); 225479dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt skPaint.setAntiAlias(skPaint.isLCDRenderText() ? true : random->nextBool()); 225579dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt skPaint.setSubpixelText(random->nextBool()); 225679dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt 225779dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt GrPaint grPaint; 225879dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt if (!SkPaint2GrPaint(context, rt, skPaint, viewMatrix, true, &grPaint)) { 225979dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt SkFAIL("couldn't convert paint\n"); 226079dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt } 226179dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt 226279dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt const char* text = "The quick brown fox jumps over the lazy dog."; 226379dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt int textLen = (int)strlen(text); 226479dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt 226579dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt // Setup clip 226679dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt GrClip clip; 226779dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt SkIRect noClip = SkIRect::MakeLargest(); 226879dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt 226979dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt // right now we don't handle textblobs, nor do we handle drawPosText. Since we only 227079dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt // intend to test the batch with this unit test, that is okay. 227179dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt SkAutoTUnref<GrAtlasTextContext::BitmapTextBlob> blob( 227279dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt gTextContext->createDrawTextBlob(rt, clip, grPaint, skPaint, viewMatrix, text, 227379dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt static_cast<size_t>(textLen), 0, 0, noClip)); 227479dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt 227579dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt SkScalar transX = static_cast<SkScalar>(random->nextU()); 227679dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt SkScalar transY = static_cast<SkScalar>(random->nextU()); 227779dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt const GrAtlasTextContext::BitmapTextBlob::Run::SubRunInfo& info = blob->fRuns[0].fSubRunInfo[0]; 227879dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt return gTextContext->createBatch(blob, info, textLen, 0, 0, color, transX, transY, skPaint); 227979dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt} 228079dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt 228179dfb2b6b6db7b2e703810d26dbdc90cf3ea40f9joshualitt#endif 2282