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

Side by Side Diff: src/core/SkPaint.cpp

Issue 16336024: add size limit for using glyphcache. above that, draw using paths (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/core/SkDraw.cpp ('k') | src/core/SkScalerContext.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 1
2 /* 2 /*
3 * Copyright 2006 The Android Open Source Project 3 * Copyright 2006 The Android Open Source Project
4 * 4 *
5 * Use of this source code is governed by a BSD-style license that can be 5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file. 6 * found in the LICENSE file.
7 */ 7 */
8 8
9 #include "SkPaint.h" 9 #include "SkPaint.h"
10 #include "SkAnnotation.h" 10 #include "SkAnnotation.h"
(...skipping 12 matching lines...) Expand all
23 #include "SkPaintDefaults.h" 23 #include "SkPaintDefaults.h"
24 #include "SkPathEffect.h" 24 #include "SkPathEffect.h"
25 #include "SkRasterizer.h" 25 #include "SkRasterizer.h"
26 #include "SkScalar.h" 26 #include "SkScalar.h"
27 #include "SkScalerContext.h" 27 #include "SkScalerContext.h"
28 #include "SkShader.h" 28 #include "SkShader.h"
29 #include "SkStringUtils.h" 29 #include "SkStringUtils.h"
30 #include "SkStroke.h" 30 #include "SkStroke.h"
31 #include "SkTextFormatParams.h" 31 #include "SkTextFormatParams.h"
32 #include "SkTextToPathIter.h" 32 #include "SkTextToPathIter.h"
33 #include "SkTLazy.h"
33 #include "SkTypeface.h" 34 #include "SkTypeface.h"
34 #include "SkXfermode.h" 35 #include "SkXfermode.h"
35 36
36 37
37 // define this to get a printf for out-of-range parameter in setters 38 // define this to get a printf for out-of-range parameter in setters
38 // e.g. setTextSize(-1) 39 // e.g. setTextSize(-1)
39 //#define SK_REPORT_API_RANGE_CHECK 40 //#define SK_REPORT_API_RANGE_CHECK
40 41
41 #ifdef SK_BUILD_FOR_ANDROID 42 #ifdef SK_BUILD_FOR_ANDROID
42 #define GEN_ID_INC fGenerationID++ 43 #define GEN_ID_INC fGenerationID++
(...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after
418 GEN_ID_INC; 419 GEN_ID_INC;
419 420
420 bool isNoDraw = annotation && annotation->isNoDraw(); 421 bool isNoDraw = annotation && annotation->isNoDraw();
421 fPrivFlags = SkSetClearMask(fPrivFlags, isNoDraw, kNoDrawAnnotation_PrivFlag ); 422 fPrivFlags = SkSetClearMask(fPrivFlags, isNoDraw, kNoDrawAnnotation_PrivFlag );
422 423
423 return annotation; 424 return annotation;
424 } 425 }
425 426
426 /////////////////////////////////////////////////////////////////////////////// 427 ///////////////////////////////////////////////////////////////////////////////
427 428
429 static SkScalar mag2(SkScalar x, SkScalar y) {
430 return x * x + y * y;
431 }
432
433 static bool tooBig(const SkMatrix& m, SkScalar ma2max) {
434 return mag2(m[SkMatrix::kMScaleX], m[SkMatrix::kMSkewY]) > ma2max
435 ||
436 mag2(m[SkMatrix::kMSkewX], m[SkMatrix::kMScaleY]) > ma2max;
437 }
438
439 bool SkPaint::TooBigToUseCache(const SkMatrix& ctm, const SkMatrix& textM) {
440 SkASSERT(!ctm.hasPerspective());
441 SkASSERT(!textM.hasPerspective());
442
443 SkMatrix matrix;
444 matrix.setConcat(ctm, textM);
445 return tooBig(matrix, MaxCacheSize2());
446 }
447
448 bool SkPaint::tooBigToUseCache(const SkMatrix& ctm) const {
449 SkMatrix textM;
450 return TooBigToUseCache(ctm, *this->setTextMatrix(&textM));
451 }
452
453 bool SkPaint::tooBigToUseCache() const {
454 SkMatrix textM;
455 return tooBig(*this->setTextMatrix(&textM), MaxCacheSize2());
456 }
457
458 ///////////////////////////////////////////////////////////////////////////////
459
428 #include "SkGlyphCache.h" 460 #include "SkGlyphCache.h"
429 #include "SkUtils.h" 461 #include "SkUtils.h"
430 462
431 static void DetachDescProc(SkTypeface* typeface, const SkDescriptor* desc, 463 static void DetachDescProc(SkTypeface* typeface, const SkDescriptor* desc,
432 void* context) { 464 void* context) {
433 *((SkGlyphCache**)context) = SkGlyphCache::DetachCache(typeface, desc); 465 *((SkGlyphCache**)context) = SkGlyphCache::DetachCache(typeface, desc);
434 } 466 }
435 467
436 #ifdef SK_BUILD_FOR_ANDROID 468 #ifdef SK_BUILD_FOR_ANDROID
437 const SkGlyph& SkPaint::getUnicharMetrics(SkUnichar text, 469 const SkGlyph& SkPaint::getUnicharMetrics(SkUnichar text,
(...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after
908 if (fFlags & kSubpixelText_Flag) { 940 if (fFlags & kSubpixelText_Flag) {
909 index += 4; 941 index += 4;
910 } 942 }
911 943
912 SkASSERT(index < SK_ARRAY_COUNT(gDrawCacheProcs)); 944 SkASSERT(index < SK_ARRAY_COUNT(gDrawCacheProcs));
913 return gDrawCacheProcs[index]; 945 return gDrawCacheProcs[index];
914 } 946 }
915 947
916 /////////////////////////////////////////////////////////////////////////////// 948 ///////////////////////////////////////////////////////////////////////////////
917 949
918 class SkAutoRestorePaintTextSizeAndFrame { 950 #define TEXT_AS_PATHS_PAINT_FLAGS_TO_IGNORE ( \
951 SkPaint::kDevKernText_Flag | \
952 SkPaint::kLinearText_Flag | \
953 SkPaint::kLCDRenderText_Flag | \
954 SkPaint::kEmbeddedBitmapText_Flag | \
955 SkPaint::kAutoHinting_Flag | \
956 SkPaint::kGenA8FromLCD_Flag )
957
958 SkScalar SkPaint::setupForAsPaths() {
959 uint32_t flags = this->getFlags();
960 // clear the flags we don't care about
961 flags &= ~TEXT_AS_PATHS_PAINT_FLAGS_TO_IGNORE;
962 // set the flags we do care about
963 flags |= SkPaint::kSubpixelText_Flag;
964
965 this->setFlags(flags);
966 this->setHinting(SkPaint::kNo_Hinting);
967
968 SkScalar textSize = fTextSize;
969 this->setTextSize(kCanonicalTextSizeForPaths);
970 return textSize / kCanonicalTextSizeForPaths;
971 }
972
973 class SkCanonicalizePaint {
919 public: 974 public:
920 SkAutoRestorePaintTextSizeAndFrame(const SkPaint* paint) 975 SkCanonicalizePaint(const SkPaint& paint) : fPaint(&paint), fScale(0) {
921 : fPaint((SkPaint*)paint) { 976 if (paint.isLinearText() || paint.tooBigToUseCache()) {
922 #ifdef SK_BUILD_FOR_ANDROID 977 SkPaint* p = fLazy.set(paint);
923 fGenerationID = fPaint->getGenerationID(); 978 fScale = p->setupForAsPaths();
924 #endif 979 fPaint = p;
925 fTextSize = paint->getTextSize(); 980 }
926 fStyle = paint->getStyle();
927 fPaint->setStyle(SkPaint::kFill_Style);
928 } 981 }
929 982
930 ~SkAutoRestorePaintTextSizeAndFrame() { 983 const SkPaint& getPaint() const { return *fPaint; }
931 fPaint->setStyle(fStyle); 984
932 fPaint->setTextSize(fTextSize); 985 /**
933 #ifdef SK_BUILD_FOR_ANDROID 986 * Returns 0 if the paint was unmodified, or the scale factor need to
934 fPaint->setGenerationID(fGenerationID); 987 * the original textSize
935 #endif 988 */
936 } 989 SkScalar getScale() const { return fScale; }
937 990
938 private: 991 private:
939 SkPaint* fPaint; 992 const SkPaint* fPaint;
940 SkScalar fTextSize; 993 SkScalar fScale;
941 SkPaint::Style fStyle; 994 SkTLazy<SkPaint> fLazy;
942 #ifdef SK_BUILD_FOR_ANDROID
943 uint32_t fGenerationID;
944 #endif
945 }; 995 };
946 996
947 static void set_bounds(const SkGlyph& g, SkRect* bounds) { 997 static void set_bounds(const SkGlyph& g, SkRect* bounds) {
948 bounds->set(SkIntToScalar(g.fLeft), 998 bounds->set(SkIntToScalar(g.fLeft),
949 SkIntToScalar(g.fTop), 999 SkIntToScalar(g.fTop),
950 SkIntToScalar(g.fLeft + g.fWidth), 1000 SkIntToScalar(g.fLeft + g.fWidth),
951 SkIntToScalar(g.fTop + g.fHeight)); 1001 SkIntToScalar(g.fTop + g.fHeight));
952 } 1002 }
953 1003
954 // 64bits wide, with a 16bit bias. Useful when accumulating lots of 16.16 so 1004 // 64bits wide, with a 16bit bias. Useful when accumulating lots of 16.16 so
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
1062 1112
1063 *count = n; 1113 *count = n;
1064 return Sk48Dot16ToScalar(x); 1114 return Sk48Dot16ToScalar(x);
1065 } 1115 }
1066 1116
1067 SkScalar SkPaint::measureText(const void* textData, size_t length, 1117 SkScalar SkPaint::measureText(const void* textData, size_t length,
1068 SkRect* bounds, SkScalar zoom) const { 1118 SkRect* bounds, SkScalar zoom) const {
1069 const char* text = (const char*)textData; 1119 const char* text = (const char*)textData;
1070 SkASSERT(text != NULL || length == 0); 1120 SkASSERT(text != NULL || length == 0);
1071 1121
1072 SkScalar scale = 0; 1122 SkCanonicalizePaint canon(*this);
1073 SkAutoRestorePaintTextSizeAndFrame restore(this); 1123 const SkPaint& paint = canon.getPaint();
1074 1124 SkScalar scale = canon.getScale();
1075 if (this->isLinearText()) {
1076 scale = fTextSize / kCanonicalTextSizeForPaths;
1077 // this gets restored by restore
1078 ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths)) ;
1079 }
1080 1125
1081 SkMatrix zoomMatrix, *zoomPtr = NULL; 1126 SkMatrix zoomMatrix, *zoomPtr = NULL;
1082 if (zoom) { 1127 if (zoom) {
1083 zoomMatrix.setScale(zoom, zoom); 1128 zoomMatrix.setScale(zoom, zoom);
1084 zoomPtr = &zoomMatrix; 1129 zoomPtr = &zoomMatrix;
1085 } 1130 }
1086 1131
1087 SkAutoGlyphCache autoCache(*this, NULL, zoomPtr); 1132 SkAutoGlyphCache autoCache(paint, NULL, zoomPtr);
1088 SkGlyphCache* cache = autoCache.getCache(); 1133 SkGlyphCache* cache = autoCache.getCache();
1089 1134
1090 SkScalar width = 0; 1135 SkScalar width = 0;
1091 1136
1092 if (length > 0) { 1137 if (length > 0) {
1093 int tempCount; 1138 int tempCount;
1094 1139
1095 width = this->measure_text(cache, text, length, &tempCount, bounds); 1140 width = paint.measure_text(cache, text, length, &tempCount, bounds);
1096 if (scale) { 1141 if (scale) {
1097 width = SkScalarMul(width, scale); 1142 width = SkScalarMul(width, scale);
1098 if (bounds) { 1143 if (bounds) {
1099 bounds->fLeft = SkScalarMul(bounds->fLeft, scale); 1144 bounds->fLeft = SkScalarMul(bounds->fLeft, scale);
1100 bounds->fTop = SkScalarMul(bounds->fTop, scale); 1145 bounds->fTop = SkScalarMul(bounds->fTop, scale);
1101 bounds->fRight = SkScalarMul(bounds->fRight, scale); 1146 bounds->fRight = SkScalarMul(bounds->fRight, scale);
1102 bounds->fBottom = SkScalarMul(bounds->fBottom, scale); 1147 bounds->fBottom = SkScalarMul(bounds->fBottom, scale);
1103 } 1148 }
1104 } 1149 }
1105 } else if (bounds) { 1150 } else if (bounds) {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1146 if (0 == fTextSize) { 1191 if (0 == fTextSize) {
1147 if (measuredWidth) { 1192 if (measuredWidth) {
1148 *measuredWidth = 0; 1193 *measuredWidth = 0;
1149 } 1194 }
1150 return length; 1195 return length;
1151 } 1196 }
1152 1197
1153 SkASSERT(textD != NULL); 1198 SkASSERT(textD != NULL);
1154 const char* text = (const char*)textD; 1199 const char* text = (const char*)textD;
1155 1200
1156 SkScalar scale = 0; 1201 SkCanonicalizePaint canon(*this);
1157 SkAutoRestorePaintTextSizeAndFrame restore(this); 1202 const SkPaint& paint = canon.getPaint();
1203 SkScalar scale = canon.getScale();
1158 1204
1159 if (this->isLinearText()) { 1205 // adjust max in case we changed the textSize in paint
1160 scale = fTextSize / kCanonicalTextSizeForPaths; 1206 if (scale) {
1161 maxWidth = SkScalarMulDiv(maxWidth, kCanonicalTextSizeForPaths, fTextSiz e); 1207 maxWidth /= scale;
1162 // this gets restored by restore
1163 ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths)) ;
1164 } 1208 }
1165 1209
1166 SkAutoGlyphCache autoCache(*this, NULL, NULL); 1210 SkAutoGlyphCache autoCache(paint, NULL, NULL);
1167 SkGlyphCache* cache = autoCache.getCache(); 1211 SkGlyphCache* cache = autoCache.getCache();
1168 1212
1169 SkMeasureCacheProc glyphCacheProc = this->getMeasureCacheProc(tbd, false); 1213 SkMeasureCacheProc glyphCacheProc = paint.getMeasureCacheProc(tbd, false);
1170 const char* stop; 1214 const char* stop;
1171 SkTextBufferPred pred = chooseTextBufferPred(tbd, &text, length, &stop); 1215 SkTextBufferPred pred = chooseTextBufferPred(tbd, &text, length, &stop);
1172 const int xyIndex = this->isVerticalText() ? 1 : 0; 1216 const int xyIndex = paint.isVerticalText() ? 1 : 0;
1173 // use 64bits for our accumulator, to avoid overflowing 16.16 1217 // use 64bits for our accumulator, to avoid overflowing 16.16
1174 Sk48Dot16 max = SkScalarToFixed(maxWidth); 1218 Sk48Dot16 max = SkScalarToFixed(maxWidth);
1175 Sk48Dot16 width = 0; 1219 Sk48Dot16 width = 0;
1176 1220
1177 SkAutoKern autokern; 1221 SkAutoKern autokern;
1178 1222
1179 if (this->isDevKernText()) { 1223 if (this->isDevKernText()) {
1180 int rsb = 0; 1224 int rsb = 0;
1181 while (pred(text, stop)) { 1225 while (pred(text, stop)) {
1182 const char* curr = text; 1226 const char* curr = text;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1220 *(SkPaint::FontMetrics*)context = cache->getFontMetrics(); 1264 *(SkPaint::FontMetrics*)context = cache->getFontMetrics();
1221 return false; // don't detach the cache 1265 return false; // don't detach the cache
1222 } 1266 }
1223 1267
1224 static void FontMetricsDescProc(SkTypeface* typeface, const SkDescriptor* desc, 1268 static void FontMetricsDescProc(SkTypeface* typeface, const SkDescriptor* desc,
1225 void* context) { 1269 void* context) {
1226 SkGlyphCache::VisitCache(typeface, desc, FontMetricsCacheProc, context); 1270 SkGlyphCache::VisitCache(typeface, desc, FontMetricsCacheProc, context);
1227 } 1271 }
1228 1272
1229 SkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const { 1273 SkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const {
1230 SkScalar scale = 0; 1274 SkCanonicalizePaint canon(*this);
1231 SkAutoRestorePaintTextSizeAndFrame restore(this); 1275 const SkPaint& paint = canon.getPaint();
1232 1276 SkScalar scale = canon.getScale();
1233 if (this->isLinearText()) { 1277
1234 scale = fTextSize / kCanonicalTextSizeForPaths;
1235 // this gets restored by restore
1236 ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths)) ;
1237 }
1238
1239 SkMatrix zoomMatrix, *zoomPtr = NULL; 1278 SkMatrix zoomMatrix, *zoomPtr = NULL;
1240 if (zoom) { 1279 if (zoom) {
1241 zoomMatrix.setScale(zoom, zoom); 1280 zoomMatrix.setScale(zoom, zoom);
1242 zoomPtr = &zoomMatrix; 1281 zoomPtr = &zoomMatrix;
1243 } 1282 }
1244 1283
1245 FontMetrics storage; 1284 FontMetrics storage;
1246 if (NULL == metrics) { 1285 if (NULL == metrics) {
1247 metrics = &storage; 1286 metrics = &storage;
1248 } 1287 }
1249 1288
1250 this->descriptorProc(NULL, zoomPtr, FontMetricsDescProc, metrics, true); 1289 paint.descriptorProc(NULL, zoomPtr, FontMetricsDescProc, metrics, true);
1251 1290
1252 if (scale) { 1291 if (scale) {
1253 metrics->fTop = SkScalarMul(metrics->fTop, scale); 1292 metrics->fTop = SkScalarMul(metrics->fTop, scale);
1254 metrics->fAscent = SkScalarMul(metrics->fAscent, scale); 1293 metrics->fAscent = SkScalarMul(metrics->fAscent, scale);
1255 metrics->fDescent = SkScalarMul(metrics->fDescent, scale); 1294 metrics->fDescent = SkScalarMul(metrics->fDescent, scale);
1256 metrics->fBottom = SkScalarMul(metrics->fBottom, scale); 1295 metrics->fBottom = SkScalarMul(metrics->fBottom, scale);
1257 metrics->fLeading = SkScalarMul(metrics->fLeading, scale); 1296 metrics->fLeading = SkScalarMul(metrics->fLeading, scale);
1258 metrics->fAvgCharWidth = SkScalarMul(metrics->fAvgCharWidth, scale); 1297 metrics->fAvgCharWidth = SkScalarMul(metrics->fAvgCharWidth, scale);
1259 metrics->fXMin = SkScalarMul(metrics->fXMin, scale); 1298 metrics->fXMin = SkScalarMul(metrics->fXMin, scale);
1260 metrics->fXMax = SkScalarMul(metrics->fXMax, scale); 1299 metrics->fXMax = SkScalarMul(metrics->fXMax, scale);
(...skipping 16 matching lines...) Expand all
1277 if (0 == byteLength) { 1316 if (0 == byteLength) {
1278 return 0; 1317 return 0;
1279 } 1318 }
1280 1319
1281 SkASSERT(NULL != textData); 1320 SkASSERT(NULL != textData);
1282 1321
1283 if (NULL == widths && NULL == bounds) { 1322 if (NULL == widths && NULL == bounds) {
1284 return this->countText(textData, byteLength); 1323 return this->countText(textData, byteLength);
1285 } 1324 }
1286 1325
1287 SkAutoRestorePaintTextSizeAndFrame restore(this); 1326 SkCanonicalizePaint canon(*this);
1288 SkScalar scale = 0; 1327 const SkPaint& paint = canon.getPaint();
1328 SkScalar scale = canon.getScale();
1289 1329
1290 if (this->isLinearText()) { 1330 SkAutoGlyphCache autoCache(paint, NULL, NULL);
1291 scale = fTextSize / kCanonicalTextSizeForPaths;
1292 // this gets restored by restore
1293 ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths)) ;
1294 }
1295
1296 SkAutoGlyphCache autoCache(*this, NULL, NULL);
1297 SkGlyphCache* cache = autoCache.getCache(); 1331 SkGlyphCache* cache = autoCache.getCache();
1298 SkMeasureCacheProc glyphCacheProc; 1332 SkMeasureCacheProc glyphCacheProc;
1299 glyphCacheProc = this->getMeasureCacheProc(kForward_TextBufferDirection, 1333 glyphCacheProc = paint.getMeasureCacheProc(kForward_TextBufferDirection,
1300 NULL != bounds); 1334 NULL != bounds);
1301 1335
1302 const char* text = (const char*)textData; 1336 const char* text = (const char*)textData;
1303 const char* stop = text + byteLength; 1337 const char* stop = text + byteLength;
1304 int count = 0; 1338 int count = 0;
1305 const int xyIndex = this->isVerticalText() ? 1 : 0; 1339 const int xyIndex = paint.isVerticalText() ? 1 : 0;
1306 1340
1307 if (this->isDevKernText()) { 1341 if (this->isDevKernText()) {
1308 // we adjust the widths returned here through auto-kerning 1342 // we adjust the widths returned here through auto-kerning
1309 SkAutoKern autokern; 1343 SkAutoKern autokern;
1310 SkFixed prevWidth = 0; 1344 SkFixed prevWidth = 0;
1311 1345
1312 if (scale) { 1346 if (scale) {
1313 while (text < stop) { 1347 while (text < stop) {
1314 const SkGlyph& g = glyphCacheProc(cache, &text); 1348 const SkGlyph& g = glyphCacheProc(cache, &text);
1315 if (widths) { 1349 if (widths) {
(...skipping 1233 matching lines...) Expand 10 before | Expand all | Expand 10 after
2549 case SkXfermode::kPlus_Mode: 2583 case SkXfermode::kPlus_Mode:
2550 return 0 == this->getAlpha(); 2584 return 0 == this->getAlpha();
2551 case SkXfermode::kDst_Mode: 2585 case SkXfermode::kDst_Mode:
2552 return true; 2586 return true;
2553 default: 2587 default:
2554 break; 2588 break;
2555 } 2589 }
2556 } 2590 }
2557 return false; 2591 return false;
2558 } 2592 }
OLDNEW
« no previous file with comments | « src/core/SkDraw.cpp ('k') | src/core/SkScalerContext.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698