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 "SkTypes.h" // Keep this before any #ifdef ... | 9 #include "SkTypes.h" // Keep this before any #ifdef ... |
10 #if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS) | 10 #if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS) |
(...skipping 24 matching lines...) Expand all Loading... |
35 #include "SkOTTable_head.h" | 35 #include "SkOTTable_head.h" |
36 #include "SkOTTable_hhea.h" | 36 #include "SkOTTable_hhea.h" |
37 #include "SkOTTable_loca.h" | 37 #include "SkOTTable_loca.h" |
38 #include "SkOTUtils.h" | 38 #include "SkOTUtils.h" |
39 #include "SkOncePtr.h" | 39 #include "SkOncePtr.h" |
40 #include "SkPaint.h" | 40 #include "SkPaint.h" |
41 #include "SkPath.h" | 41 #include "SkPath.h" |
42 #include "SkSFNTHeader.h" | 42 #include "SkSFNTHeader.h" |
43 #include "SkStream.h" | 43 #include "SkStream.h" |
44 #include "SkString.h" | 44 #include "SkString.h" |
| 45 #include "SkTemplates.h" |
45 #include "SkTypefaceCache.h" | 46 #include "SkTypefaceCache.h" |
46 #include "SkTypeface_mac.h" | 47 #include "SkTypeface_mac.h" |
47 #include "SkUtils.h" | 48 #include "SkUtils.h" |
48 #include "SkUtils.h" | 49 #include "SkUtils.h" |
49 | 50 |
50 #include <dlfcn.h> | 51 #include <dlfcn.h> |
51 | 52 |
52 // Experimental code to use a global lock whenever we access CG, to see if this
reduces | 53 // Experimental code to use a global lock whenever we access CG, to see if this
reduces |
53 // crashes in Chrome | 54 // crashes in Chrome |
54 #define USE_GLOBAL_MUTEX_FOR_CG_ACCESS | 55 #define USE_GLOBAL_MUTEX_FOR_CG_ACCESS |
(...skipping 765 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
820 } | 821 } |
821 | 822 |
822 // FIXME: lcd smoothed un-hinted rasterization unsupported. | 823 // FIXME: lcd smoothed un-hinted rasterization unsupported. |
823 if (!generateA8FromLCD && SkMask::kA8_Format == glyph.fMaskFormat) { | 824 if (!generateA8FromLCD && SkMask::kA8_Format == glyph.fMaskFormat) { |
824 doLCD = false; | 825 doLCD = false; |
825 doAA = true; | 826 doAA = true; |
826 } | 827 } |
827 | 828 |
828 // If this font might have color glyphs, disable LCD as there's no way to su
pport it. | 829 // If this font might have color glyphs, disable LCD as there's no way to su
pport it. |
829 // CoreText doesn't tell us which format it ended up using, so we can't dete
ct it. | 830 // CoreText doesn't tell us which format it ended up using, so we can't dete
ct it. |
830 // A8 will be ugly too (white on transparent), but TODO: we can detect gray
and set to A8. | 831 // A8 will end up black on transparent, but TODO: we can detect gray and set
to A8. |
831 if (SkMask::kARGB32_Format == glyph.fMaskFormat) { | 832 if (SkMask::kARGB32_Format == glyph.fMaskFormat) { |
832 doLCD = false; | 833 doLCD = false; |
833 } | 834 } |
834 | 835 |
835 size_t rowBytes = fSize.fWidth * sizeof(CGRGBPixel); | 836 size_t rowBytes = fSize.fWidth * sizeof(CGRGBPixel); |
836 if (!fCG || fSize.fWidth < glyph.fWidth || fSize.fHeight < glyph.fHeight) { | 837 if (!fCG || fSize.fWidth < glyph.fWidth || fSize.fHeight < glyph.fHeight) { |
837 if (fSize.fWidth < glyph.fWidth) { | 838 if (fSize.fWidth < glyph.fWidth) { |
838 fSize.fWidth = RoundSize(glyph.fWidth); | 839 fSize.fWidth = RoundSize(glyph.fWidth); |
839 } | 840 } |
840 if (fSize.fHeight < glyph.fHeight) { | 841 if (fSize.fHeight < glyph.fHeight) { |
(...skipping 15 matching lines...) Expand all Loading... |
856 CGContextSetShouldSubpixelQuantizeFonts(fCG, false); | 857 CGContextSetShouldSubpixelQuantizeFonts(fCG, false); |
857 | 858 |
858 // Because CG always draws from the horizontal baseline, | 859 // Because CG always draws from the horizontal baseline, |
859 // if there is a non-integral translation from the horizontal origin to
the vertical origin, | 860 // if there is a non-integral translation from the horizontal origin to
the vertical origin, |
860 // then CG cannot draw the glyph in the correct location without subpixe
l positioning. | 861 // then CG cannot draw the glyph in the correct location without subpixe
l positioning. |
861 CGContextSetAllowsFontSubpixelPositioning(fCG, true); | 862 CGContextSetAllowsFontSubpixelPositioning(fCG, true); |
862 CGContextSetShouldSubpixelPositionFonts(fCG, true); | 863 CGContextSetShouldSubpixelPositionFonts(fCG, true); |
863 | 864 |
864 CGContextSetTextDrawingMode(fCG, kCGTextFill); | 865 CGContextSetTextDrawingMode(fCG, kCGTextFill); |
865 | 866 |
| 867 #if SK_IGNORE_MAC_FONT_WEIGHT_FIX |
866 // Draw white on black to create mask. | 868 // Draw white on black to create mask. |
867 // TODO: Draw black on white and invert, CG has a special case codepath. | 869 // TODO: Draw black on white and invert, CG has a special case codepath. |
868 CGContextSetGrayFillColor(fCG, 1.0f, 1.0f); | 870 CGContextSetGrayFillColor(fCG, 1.0f, 1.0f); |
| 871 #else |
| 872 // Draw black on white to create mask. (Special path exists to speed thi
s up in CG.) |
| 873 CGContextSetGrayFillColor(fCG, 0.0f, 1.0f); |
| 874 #endif |
869 | 875 |
870 // force our checks below to happen | 876 // force our checks below to happen |
871 fDoAA = !doAA; | 877 fDoAA = !doAA; |
872 fDoLCD = !doLCD; | 878 fDoLCD = !doLCD; |
873 | 879 |
874 if (legacy_CTFontDrawGlyphs == ctFontDrawGlyphs) { | 880 if (legacy_CTFontDrawGlyphs == ctFontDrawGlyphs) { |
875 // CTFontDrawGlyphs will apply the font, font size, and font matrix
to the CGContext. | 881 // CTFontDrawGlyphs will apply the font, font size, and font matrix
to the CGContext. |
876 // Our 'fake' one does not, so set up the CGContext here. | 882 // Our 'fake' one does not, so set up the CGContext here. |
877 CGContextSetFont(fCG, context.fCGFont); | 883 CGContextSetFont(fCG, context.fCGFont); |
878 CGContextSetFontSize(fCG, CTFontGetSize(context.fCTFont)); | 884 CGContextSetFontSize(fCG, CTFontGetSize(context.fCTFont)); |
879 } | 885 } |
880 CGContextSetTextMatrix(fCG, context.fTransform); | 886 CGContextSetTextMatrix(fCG, context.fTransform); |
881 } | 887 } |
882 | 888 |
883 if (fDoAA != doAA) { | 889 if (fDoAA != doAA) { |
884 CGContextSetShouldAntialias(fCG, doAA); | 890 CGContextSetShouldAntialias(fCG, doAA); |
885 fDoAA = doAA; | 891 fDoAA = doAA; |
886 } | 892 } |
887 if (fDoLCD != doLCD) { | 893 if (fDoLCD != doLCD) { |
888 CGContextSetShouldSmoothFonts(fCG, doLCD); | 894 CGContextSetShouldSmoothFonts(fCG, doLCD); |
889 fDoLCD = doLCD; | 895 fDoLCD = doLCD; |
890 } | 896 } |
891 | 897 |
892 CGRGBPixel* image = (CGRGBPixel*)fImageStorage.get(); | 898 CGRGBPixel* image = (CGRGBPixel*)fImageStorage.get(); |
893 // skip rows based on the glyph's height | 899 // skip rows based on the glyph's height |
894 image += (fSize.fHeight - glyph.fHeight) * fSize.fWidth; | 900 image += (fSize.fHeight - glyph.fHeight) * fSize.fWidth; |
895 | 901 |
| 902 #if SK_IGNORE_MAC_FONT_WEIGHT_FIX |
896 // erase to black | 903 // erase to black |
897 sk_memset_rect32(image, 0, glyph.fWidth, glyph.fHeight, rowBytes); | 904 sk_memset_rect32(image, 0, glyph.fWidth, glyph.fHeight, rowBytes); |
| 905 #else |
| 906 // Erase to white (or transparent black if it's a color glyph, to not compos
ite against white). |
| 907 uint32_t bgColor = (SkMask::kARGB32_Format != glyph.fMaskFormat) ? 0xFFFFFFF
F : 0x00000000; |
| 908 sk_memset_rect32(image, bgColor, glyph.fWidth, glyph.fHeight, rowBytes); |
| 909 #endif |
898 | 910 |
899 float subX = 0; | 911 float subX = 0; |
900 float subY = 0; | 912 float subY = 0; |
901 if (context.fDoSubPosition) { | 913 if (context.fDoSubPosition) { |
902 subX = SkFixedToFloat(glyph.getSubXFixed()); | 914 subX = SkFixedToFloat(glyph.getSubXFixed()); |
903 subY = SkFixedToFloat(glyph.getSubYFixed()); | 915 subY = SkFixedToFloat(glyph.getSubYFixed()); |
904 } | 916 } |
905 | 917 |
906 // CoreText and CoreGraphics always draw using the horizontal baseline origi
n. | 918 // CoreText and CoreGraphics always draw using the horizontal baseline origi
n. |
907 if (context.fVertical) { | 919 if (context.fVertical) { |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1132 // Note that if this context is A8 and not back-forming from LCD, there is n
o need to outset. | 1144 // Note that if this context is A8 and not back-forming from LCD, there is n
o need to outset. |
1133 skIBounds.outset(1, 1); | 1145 skIBounds.outset(1, 1); |
1134 glyph->fLeft = SkToS16(skIBounds.fLeft); | 1146 glyph->fLeft = SkToS16(skIBounds.fLeft); |
1135 glyph->fTop = SkToS16(skIBounds.fTop); | 1147 glyph->fTop = SkToS16(skIBounds.fTop); |
1136 glyph->fWidth = SkToU16(skIBounds.width()); | 1148 glyph->fWidth = SkToU16(skIBounds.width()); |
1137 glyph->fHeight = SkToU16(skIBounds.height()); | 1149 glyph->fHeight = SkToU16(skIBounds.height()); |
1138 } | 1150 } |
1139 | 1151 |
1140 #include "SkColorPriv.h" | 1152 #include "SkColorPriv.h" |
1141 | 1153 |
1142 static void build_power_table(uint8_t table[], float ee) { | 1154 static void build_power_table(uint8_t table[]) { |
1143 for (int i = 0; i < 256; i++) { | 1155 for (int i = 0; i < 256; i++) { |
1144 float x = i / 255.f; | 1156 float x = i / 255.f; |
1145 x = sk_float_pow(x, ee); | 1157 int xx = SkScalarRoundToInt(x * x * 255); |
1146 int xx = SkScalarRoundToInt(x * 255); | |
1147 table[i] = SkToU8(xx); | 1158 table[i] = SkToU8(xx); |
1148 } | 1159 } |
1149 } | 1160 } |
1150 | 1161 |
1151 /** | 1162 /** |
1152 * This will invert the gamma applied by CoreGraphics, so we can get linear | 1163 * This will invert the gamma applied by CoreGraphics, so we can get linear |
1153 * values. | 1164 * values. |
1154 * | 1165 * |
1155 * CoreGraphics obscurely defaults to 2.0 as the smoothing gamma value. | 1166 * CoreGraphics obscurely defaults to 2.0 as the smoothing gamma value. |
1156 * The color space used does not appear to affect this choice. | 1167 * The color space used does not appear to affect this choice. |
1157 */ | 1168 */ |
1158 static const uint8_t* getInverseGammaTableCoreGraphicSmoothing() { | 1169 static const uint8_t* getInverseGammaTableCoreGraphicSmoothing() { |
1159 static bool gInited; | 1170 static bool gInited; |
1160 static uint8_t gTableCoreGraphicsSmoothing[256]; | 1171 static uint8_t gTableCoreGraphicsSmoothing[256]; |
1161 if (!gInited) { | 1172 if (!gInited) { |
1162 build_power_table(gTableCoreGraphicsSmoothing, 2.0f); | 1173 build_power_table(gTableCoreGraphicsSmoothing); |
1163 gInited = true; | 1174 gInited = true; |
1164 } | 1175 } |
1165 return gTableCoreGraphicsSmoothing; | 1176 return gTableCoreGraphicsSmoothing; |
1166 } | 1177 } |
1167 | 1178 |
1168 static void cgpixels_to_bits(uint8_t dst[], const CGRGBPixel src[], int count) { | 1179 static void cgpixels_to_bits(uint8_t dst[], const CGRGBPixel src[], int count) { |
1169 while (count > 0) { | 1180 while (count > 0) { |
1170 uint8_t mask = 0; | 1181 uint8_t mask = 0; |
1171 for (int i = 7; i >= 0; --i) { | 1182 for (int i = 7; i >= 0; --i) { |
| 1183 #if SK_IGNORE_MAC_FONT_WEIGHT_FIX |
1172 mask |= (CGRGBPixel_getAlpha(*src++) >> 7) << i; | 1184 mask |= (CGRGBPixel_getAlpha(*src++) >> 7) << i; |
| 1185 #else |
| 1186 mask |= ((CGRGBPixel_getAlpha(*src++) >> 7) ^ 0x1) << i; |
| 1187 #endif |
1173 if (0 == --count) { | 1188 if (0 == --count) { |
1174 break; | 1189 break; |
1175 } | 1190 } |
1176 } | 1191 } |
1177 *dst++ = mask; | 1192 *dst++ = mask; |
1178 } | 1193 } |
1179 } | 1194 } |
1180 | 1195 |
1181 template<bool APPLY_PREBLEND> | 1196 template<bool APPLY_PREBLEND> |
1182 static inline uint8_t rgb_to_a8(CGRGBPixel rgb, const uint8_t* table8) { | 1197 static inline uint8_t rgb_to_a8(CGRGBPixel rgb, const uint8_t* table8) { |
| 1198 #if SK_IGNORE_MAC_FONT_WEIGHT_FIX |
1183 U8CPU r = (rgb >> 16) & 0xFF; | 1199 U8CPU r = (rgb >> 16) & 0xFF; |
1184 U8CPU g = (rgb >> 8) & 0xFF; | 1200 U8CPU g = (rgb >> 8) & 0xFF; |
1185 U8CPU b = (rgb >> 0) & 0xFF; | 1201 U8CPU b = (rgb >> 0) & 0xFF; |
| 1202 #else |
| 1203 U8CPU r = 0xFF - ((rgb >> 16) & 0xFF); |
| 1204 U8CPU g = 0xFF - ((rgb >> 8) & 0xFF); |
| 1205 U8CPU b = 0xFF - ((rgb >> 0) & 0xFF); |
| 1206 #endif |
1186 U8CPU lum = sk_apply_lut_if<APPLY_PREBLEND>(SkComputeLuminance(r, g, b), tab
le8); | 1207 U8CPU lum = sk_apply_lut_if<APPLY_PREBLEND>(SkComputeLuminance(r, g, b), tab
le8); |
1187 #if SK_SHOW_TEXT_BLIT_COVERAGE | 1208 #if SK_SHOW_TEXT_BLIT_COVERAGE |
1188 lum = SkTMax(lum, (U8CPU)0x30); | 1209 lum = SkTMax(lum, (U8CPU)0x30); |
1189 #endif | 1210 #endif |
1190 return lum; | 1211 return lum; |
1191 } | 1212 } |
1192 template<bool APPLY_PREBLEND> | 1213 template<bool APPLY_PREBLEND> |
1193 static void rgb_to_a8(const CGRGBPixel* SK_RESTRICT cgPixels, size_t cgRowBytes, | 1214 static void rgb_to_a8(const CGRGBPixel* SK_RESTRICT cgPixels, size_t cgRowBytes, |
1194 const SkGlyph& glyph, const uint8_t* table8) { | 1215 const SkGlyph& glyph, const uint8_t* table8) { |
1195 const int width = glyph.fWidth; | 1216 const int width = glyph.fWidth; |
1196 size_t dstRB = glyph.rowBytes(); | 1217 size_t dstRB = glyph.rowBytes(); |
1197 uint8_t* SK_RESTRICT dst = (uint8_t*)glyph.fImage; | 1218 uint8_t* SK_RESTRICT dst = (uint8_t*)glyph.fImage; |
1198 | 1219 |
1199 for (int y = 0; y < glyph.fHeight; y++) { | 1220 for (int y = 0; y < glyph.fHeight; y++) { |
1200 for (int i = 0; i < width; ++i) { | 1221 for (int i = 0; i < width; ++i) { |
1201 dst[i] = rgb_to_a8<APPLY_PREBLEND>(cgPixels[i], table8); | 1222 dst[i] = rgb_to_a8<APPLY_PREBLEND>(cgPixels[i], table8); |
1202 } | 1223 } |
1203 cgPixels = (CGRGBPixel*)((char*)cgPixels + cgRowBytes); | 1224 cgPixels = (CGRGBPixel*)((char*)cgPixels + cgRowBytes); |
1204 dst += dstRB; | 1225 dst += dstRB; |
1205 } | 1226 } |
1206 } | 1227 } |
1207 | 1228 |
1208 template<bool APPLY_PREBLEND> | 1229 template<bool APPLY_PREBLEND> |
1209 static inline uint16_t rgb_to_lcd16(CGRGBPixel rgb, const uint8_t* tableR, | 1230 static inline uint16_t rgb_to_lcd16(CGRGBPixel rgb, const uint8_t* tableR, |
1210 const uint8_t* tableG, | 1231 const uint8_t* tableG, |
1211 const uint8_t* tableB) { | 1232 const uint8_t* tableB) { |
| 1233 #if SK_IGNORE_MAC_FONT_WEIGHT_FIX |
1212 U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 16) & 0xFF, tableR); | 1234 U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 16) & 0xFF, tableR); |
1213 U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 8) & 0xFF, tableG); | 1235 U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 8) & 0xFF, tableG); |
1214 U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 0) & 0xFF, tableB); | 1236 U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 0) & 0xFF, tableB); |
| 1237 #else |
| 1238 U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(0xFF - ((rgb >> 16) & 0xFF), table
R); |
| 1239 U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(0xFF - ((rgb >> 8) & 0xFF), table
G); |
| 1240 U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(0xFF - ((rgb >> 0) & 0xFF), table
B); |
| 1241 #endif |
1215 #if SK_SHOW_TEXT_BLIT_COVERAGE | 1242 #if SK_SHOW_TEXT_BLIT_COVERAGE |
1216 r = SkTMax(r, (U8CPU)0x30); | 1243 r = SkTMax(r, (U8CPU)0x30); |
1217 g = SkTMax(g, (U8CPU)0x30); | 1244 g = SkTMax(g, (U8CPU)0x30); |
1218 b = SkTMax(b, (U8CPU)0x30); | 1245 b = SkTMax(b, (U8CPU)0x30); |
1219 #endif | 1246 #endif |
1220 return SkPack888ToRGB16(r, g, b); | 1247 return SkPack888ToRGB16(r, g, b); |
1221 } | 1248 } |
1222 template<bool APPLY_PREBLEND> | 1249 template<bool APPLY_PREBLEND> |
1223 static void rgb_to_lcd16(const CGRGBPixel* SK_RESTRICT cgPixels, size_t cgRowByt
es, const SkGlyph& glyph, | 1250 static void rgb_to_lcd16(const CGRGBPixel* SK_RESTRICT cgPixels, size_t cgRowByt
es, const SkGlyph& glyph, |
1224 const uint8_t* tableR, const uint8_t* tableG, const uin
t8_t* tableB) { | 1251 const uint8_t* tableR, const uint8_t* tableG, const uin
t8_t* tableB) { |
(...skipping 14 matching lines...) Expand all Loading... |
1239 U8CPU a = (rgb >> 24) & 0xFF; | 1266 U8CPU a = (rgb >> 24) & 0xFF; |
1240 U8CPU r = (rgb >> 16) & 0xFF; | 1267 U8CPU r = (rgb >> 16) & 0xFF; |
1241 U8CPU g = (rgb >> 8) & 0xFF; | 1268 U8CPU g = (rgb >> 8) & 0xFF; |
1242 U8CPU b = (rgb >> 0) & 0xFF; | 1269 U8CPU b = (rgb >> 0) & 0xFF; |
1243 #if SK_SHOW_TEXT_BLIT_COVERAGE | 1270 #if SK_SHOW_TEXT_BLIT_COVERAGE |
1244 a = SkTMax(a, (U8CPU)0x30); | 1271 a = SkTMax(a, (U8CPU)0x30); |
1245 #endif | 1272 #endif |
1246 return SkPackARGB32(a, r, g, b); | 1273 return SkPackARGB32(a, r, g, b); |
1247 } | 1274 } |
1248 | 1275 |
1249 template <typename T> T* SkTAddByteOffset(T* ptr, size_t byteOffset) { | |
1250 return (T*)((char*)ptr + byteOffset); | |
1251 } | |
1252 | |
1253 void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) { | 1276 void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) { |
1254 CGGlyph cgGlyph = (CGGlyph) glyph.getGlyphID(); | 1277 CGGlyph cgGlyph = (CGGlyph) glyph.getGlyphID(); |
1255 | 1278 |
1256 // FIXME: lcd smoothed un-hinted rasterization unsupported. | 1279 // FIXME: lcd smoothed un-hinted rasterization unsupported. |
1257 bool generateA8FromLCD = fRec.getHinting() != SkPaint::kNo_Hinting; | 1280 bool generateA8FromLCD = fRec.getHinting() != SkPaint::kNo_Hinting; |
1258 | 1281 |
1259 // Draw the glyph | 1282 // Draw the glyph |
1260 size_t cgRowBytes; | 1283 size_t cgRowBytes; |
1261 CGRGBPixel* cgPixels = fOffscreen.getCG(*this, glyph, cgGlyph, &cgRowBytes,
generateA8FromLCD); | 1284 CGRGBPixel* cgPixels = fOffscreen.getCG(*this, glyph, cgGlyph, &cgRowBytes,
generateA8FromLCD); |
1262 if (cgPixels == nullptr) { | 1285 if (cgPixels == nullptr) { |
1263 return; | 1286 return; |
1264 } | 1287 } |
1265 | 1288 |
1266 //TODO: see if drawing black on white and inverting is faster (at least in | |
1267 //lcd case) as core graphics appears to have special case code for drawing | |
1268 //black text. | |
1269 | |
1270 // Fix the glyph | 1289 // Fix the glyph |
1271 const bool isLCD = isLCDFormat(glyph.fMaskFormat); | 1290 const bool isLCD = isLCDFormat(glyph.fMaskFormat); |
1272 if (isLCD || (glyph.fMaskFormat == SkMask::kA8_Format && supports_LCD() && g
enerateA8FromLCD)) { | 1291 if (isLCD || (glyph.fMaskFormat == SkMask::kA8_Format && supports_LCD() && g
enerateA8FromLCD)) { |
1273 const uint8_t* table = getInverseGammaTableCoreGraphicSmoothing(); | 1292 const uint8_t* table = getInverseGammaTableCoreGraphicSmoothing(); |
1274 | 1293 |
1275 //Note that the following cannot really be integrated into the | 1294 //Note that the following cannot really be integrated into the |
1276 //pre-blend, since we may not be applying the pre-blend; when we aren't | 1295 //pre-blend, since we may not be applying the pre-blend; when we aren't |
1277 //applying the pre-blend it means that a filter wants linear anyway. | 1296 //applying the pre-blend it means that a filter wants linear anyway. |
1278 //Other code may also be applying the pre-blend, so we'd need another | 1297 //Other code may also be applying the pre-blend, so we'd need another |
1279 //one with this and one without. | 1298 //one with this and one without. |
1280 CGRGBPixel* addr = cgPixels; | 1299 CGRGBPixel* addr = cgPixels; |
1281 for (int y = 0; y < glyph.fHeight; ++y) { | 1300 for (int y = 0; y < glyph.fHeight; ++y) { |
1282 for (int x = 0; x < glyph.fWidth; ++x) { | 1301 for (int x = 0; x < glyph.fWidth; ++x) { |
1283 int r = (addr[x] >> 16) & 0xFF; | 1302 int r = (addr[x] >> 16) & 0xFF; |
1284 int g = (addr[x] >> 8) & 0xFF; | 1303 int g = (addr[x] >> 8) & 0xFF; |
1285 int b = (addr[x] >> 0) & 0xFF; | 1304 int b = (addr[x] >> 0) & 0xFF; |
1286 addr[x] = (table[r] << 16) | (table[g] << 8) | table[b]; | 1305 addr[x] = (table[r] << 16) | (table[g] << 8) | table[b]; |
1287 } | 1306 } |
1288 addr = SkTAddByteOffset(addr, cgRowBytes); | 1307 addr = SkTAddOffset<CGRGBPixel>(addr, cgRowBytes); |
1289 } | 1308 } |
1290 } | 1309 } |
1291 | 1310 |
1292 // Convert glyph to mask | 1311 // Convert glyph to mask |
1293 switch (glyph.fMaskFormat) { | 1312 switch (glyph.fMaskFormat) { |
1294 case SkMask::kLCD16_Format: { | 1313 case SkMask::kLCD16_Format: { |
1295 if (fPreBlend.isApplicable()) { | 1314 if (fPreBlend.isApplicable()) { |
1296 rgb_to_lcd16<true>(cgPixels, cgRowBytes, glyph, | 1315 rgb_to_lcd16<true>(cgPixels, cgRowBytes, glyph, |
1297 fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); | 1316 fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); |
1298 } else { | 1317 } else { |
(...skipping 1325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2624 } | 2643 } |
2625 return face; | 2644 return face; |
2626 } | 2645 } |
2627 }; | 2646 }; |
2628 | 2647 |
2629 /////////////////////////////////////////////////////////////////////////////// | 2648 /////////////////////////////////////////////////////////////////////////////// |
2630 | 2649 |
2631 SkFontMgr* SkFontMgr::Factory() { return new SkFontMgr_Mac; } | 2650 SkFontMgr* SkFontMgr::Factory() { return new SkFontMgr_Mac; } |
2632 | 2651 |
2633 #endif//defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS) | 2652 #endif//defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS) |
OLD | NEW |