OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |