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

Side by Side Diff: src/ports/SkFontHost_win.cpp

Issue 17435003: Fix limit on size of glyph paths. (Closed) Base URL: http://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 | « no previous file | no next file » | 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 "SkAdvancedTypefaceMetrics.h" 9 #include "SkAdvancedTypefaceMetrics.h"
10 #include "SkBase64.h" 10 #include "SkBase64.h"
11 #include "SkColorPriv.h" 11 #include "SkColorPriv.h"
12 #include "SkData.h" 12 #include "SkData.h"
13 #include "SkDescriptor.h" 13 #include "SkDescriptor.h"
14 #include "SkFontDescriptor.h" 14 #include "SkFontDescriptor.h"
15 #include "SkFontHost.h" 15 #include "SkFontHost.h"
16 #include "SkGlyph.h" 16 #include "SkGlyph.h"
17 #include "SkMaskGamma.h" 17 #include "SkMaskGamma.h"
18 #include "SkOTUtils.h" 18 #include "SkOTUtils.h"
19 #include "SkPath.h" 19 #include "SkPath.h"
20 #include "SkStream.h" 20 #include "SkStream.h"
21 #include "SkString.h" 21 #include "SkString.h"
22 #include "SkTemplates.h"
22 #include "SkThread.h" 23 #include "SkThread.h"
23 #include "SkTypeface_win.h" 24 #include "SkTypeface_win.h"
24 #include "SkTypefaceCache.h" 25 #include "SkTypefaceCache.h"
25 #include "SkUtils.h" 26 #include "SkUtils.h"
26 27
27 #include "SkTypes.h" 28 #include "SkTypes.h"
28 #include <tchar.h> 29 #include <tchar.h>
29 #include <usp10.h> 30 #include <usp10.h>
30 #include <objbase.h> 31 #include <objbase.h>
31 32
32 static void (*gEnsureLOGFONTAccessibleProc)(const LOGFONT&); 33 static void (*gEnsureLOGFONTAccessibleProc)(const LOGFONT&);
33 34
34 void SkTypeface_SetEnsureLOGFONTAccessibleProc(void (*proc)(const LOGFONT&)) { 35 void SkTypeface_SetEnsureLOGFONTAccessibleProc(void (*proc)(const LOGFONT&)) {
35 gEnsureLOGFONTAccessibleProc = proc; 36 gEnsureLOGFONTAccessibleProc = proc;
36 } 37 }
37 38
38 static void call_ensure_accessible(const LOGFONT& lf) { 39 static void call_ensure_accessible(const LOGFONT& lf) {
39 if (gEnsureLOGFONTAccessibleProc) { 40 if (gEnsureLOGFONTAccessibleProc) {
40 gEnsureLOGFONTAccessibleProc(lf); 41 gEnsureLOGFONTAccessibleProc(lf);
41 } 42 }
42 } 43 }
43 44
44 /////////////////////////////////////////////////////////////////////////////// 45 ///////////////////////////////////////////////////////////////////////////////
45 46
46 // always packed xxRRGGBB 47 // always packed xxRRGGBB
47 typedef uint32_t SkGdiRGB; 48 typedef uint32_t SkGdiRGB;
48 49
49 template <typename T> T* SkTAddByteOffset(T* ptr, size_t byteOffset) {
50 return (T*)((char*)ptr + byteOffset);
51 }
52
53 // define this in your Makefile or .gyp to enforce AA requests 50 // define this in your Makefile or .gyp to enforce AA requests
54 // which GDI ignores at small sizes. This flag guarantees AA 51 // which GDI ignores at small sizes. This flag guarantees AA
55 // for rotated text, regardless of GDI's notions. 52 // for rotated text, regardless of GDI's notions.
56 //#define SK_ENFORCE_ROTATED_TEXT_AA_ON_WINDOWS 53 //#define SK_ENFORCE_ROTATED_TEXT_AA_ON_WINDOWS
57 54
58 // client3d has to undefine this for now
59 #define CAN_USE_LOGFONT_NAME
60
61 static bool isLCD(const SkScalerContext::Rec& rec) { 55 static bool isLCD(const SkScalerContext::Rec& rec) {
62 return SkMask::kLCD16_Format == rec.fMaskFormat || 56 return SkMask::kLCD16_Format == rec.fMaskFormat ||
63 SkMask::kLCD32_Format == rec.fMaskFormat; 57 SkMask::kLCD32_Format == rec.fMaskFormat;
64 } 58 }
65 59
66 static bool bothZero(SkScalar a, SkScalar b) { 60 static bool bothZero(SkScalar a, SkScalar b) {
67 return 0 == a && 0 == b; 61 return 0 == a && 0 == b;
68 } 62 }
69 63
70 // returns false if there is any non-90-rotation or skew 64 // returns false if there is any non-90-rotation or skew
(...skipping 13 matching lines...) Expand all
84 if (SkMask::kA8_Format == rec.fMaskFormat && !isAxisAligned(rec)) { 78 if (SkMask::kA8_Format == rec.fMaskFormat && !isAxisAligned(rec)) {
85 return true; 79 return true;
86 } 80 }
87 #endif 81 #endif
88 // false means allow GDI to generate the bits 82 // false means allow GDI to generate the bits
89 return false; 83 return false;
90 } 84 }
91 85
92 using namespace skia_advanced_typeface_metrics_utils; 86 using namespace skia_advanced_typeface_metrics_utils;
93 87
94 static const uint16_t BUFFERSIZE = (16384 - 32);
95 static uint8_t glyphbuf[BUFFERSIZE];
96
97 /** 88 /**
98 * Since LOGFONT wants its textsize as an int, and we support fractional sizes, 89 * Since LOGFONT wants its textsize as an int, and we support fractional sizes,
99 * and since we have a cache of LOGFONTs for our tyepfaces, we always set the 90 * and since we have a cache of LOGFONTs for our tyepfaces, we always set the
100 * lfHeight to a canonical size, and then we use the 2x2 matrix to achieve the 91 * lfHeight to a canonical size, and then we use the 2x2 matrix to achieve the
101 * actual requested size. 92 * actual requested size.
102 * 93 *
103 * Not critical to match the font's upem, but we want it big enough to avoid 94 * Not critical to match the font's upem, but we want it big enough to avoid
104 * precision loss for GDI calls that return ints (e.g. GetOutlineFontMetrics). 95 * precision loss for GDI calls that return ints (e.g. GetOutlineFontMetrics).
105 */ 96 */
106 static const int gCanonicalTextSize = 2048; 97 static const int gCanonicalTextSize = 2048;
(...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after
547 }; 538 };
548 539
549 static float mul2float(SkScalar a, SkScalar b) { 540 static float mul2float(SkScalar a, SkScalar b) {
550 return SkScalarToFloat(SkScalarMul(a, b)); 541 return SkScalarToFloat(SkScalarMul(a, b));
551 } 542 }
552 543
553 static FIXED float2FIXED(float x) { 544 static FIXED float2FIXED(float x) {
554 return SkFixedToFIXED(SkFloatToFixed(x)); 545 return SkFixedToFIXED(SkFloatToFixed(x));
555 } 546 }
556 547
557 SK_DECLARE_STATIC_MUTEX(gFTMutex);
558
559 #define HIRES_TEXTSIZE 2048 548 #define HIRES_TEXTSIZE 2048
560 #define HIRES_SHIFT 11 549 #define HIRES_SHIFT 11
561 static inline SkFixed HiResToFixed(int value) { 550 static inline SkFixed HiResToFixed(int value) {
562 return value << (16 - HIRES_SHIFT); 551 return value << (16 - HIRES_SHIFT);
563 } 552 }
564 553
565 static bool needHiResMetrics(const SkScalar mat[2][2]) { 554 static bool needHiResMetrics(const SkScalar mat[2][2]) {
566 return mat[1][0] || mat[0][1]; 555 return mat[1][0] || mat[0][1];
567 } 556 }
568 557
(...skipping 13 matching lines...) Expand all
582 } 571 }
583 } 572 }
584 573
585 SkScalerContext_Windows::SkScalerContext_Windows(SkTypeface* rawTypeface, 574 SkScalerContext_Windows::SkScalerContext_Windows(SkTypeface* rawTypeface,
586 const SkDescriptor* desc) 575 const SkDescriptor* desc)
587 : SkScalerContext(rawTypeface, desc) 576 : SkScalerContext(rawTypeface, desc)
588 , fDDC(0) 577 , fDDC(0)
589 , fFont(0) 578 , fFont(0)
590 , fSavefont(0) 579 , fSavefont(0)
591 , fSC(0) 580 , fSC(0)
592 , fGlyphCount(-1) { 581 , fGlyphCount(-1)
593 SkAutoMutexAcquire ac(gFTMutex); 582 {
594
595 LogFontTypeface* typeface = reinterpret_cast<LogFontTypeface*>(rawTypeface); 583 LogFontTypeface* typeface = reinterpret_cast<LogFontTypeface*>(rawTypeface);
596 584
597 fDDC = ::CreateCompatibleDC(NULL); 585 fDDC = ::CreateCompatibleDC(NULL);
598 SetGraphicsMode(fDDC, GM_ADVANCED); 586 SetGraphicsMode(fDDC, GM_ADVANCED);
599 SetBkMode(fDDC, TRANSPARENT); 587 SetBkMode(fDDC, TRANSPARENT);
600 588
601 // Scaling by the DPI is inconsistent with how Skia draws elsewhere 589 // Scaling by the DPI is inconsistent with how Skia draws elsewhere
602 //SkScalar height = -(fRec.fTextSize * GetDeviceCaps(ddc, LOGPIXELSY) / 72); 590 //SkScalar height = -(fRec.fTextSize * GetDeviceCaps(ddc, LOGPIXELSY) / 72);
603 LOGFONT lf = typeface->fLogFont; 591 LOGFONT lf = typeface->fLogFont;
604 lf.lfHeight = -gCanonicalTextSize; 592 lf.lfHeight = -gCanonicalTextSize;
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after
917 * can get linear values. 905 * can get linear values.
918 * 906 *
919 * GDI grayscale appears to use a hard-coded gamma of 2.3. 907 * GDI grayscale appears to use a hard-coded gamma of 2.3.
920 * 908 *
921 * GDI grayscale appears to draw using the black and white rasterizer at four 909 * GDI grayscale appears to draw using the black and white rasterizer at four
922 * times the size and then downsamples to compute the coverage mask. As a 910 * times the size and then downsamples to compute the coverage mask. As a
923 * result there are only seventeen total grays. This lack of fidelity means 911 * result there are only seventeen total grays. This lack of fidelity means
924 * that shifting into other color spaces is imprecise. 912 * that shifting into other color spaces is imprecise.
925 */ 913 */
926 static const uint8_t* getInverseGammaTableGDI() { 914 static const uint8_t* getInverseGammaTableGDI() {
915 // Since build_power_table is idempotent, many threads can build gTableGdi
916 // simultaneously.
927 static bool gInited; 917 static bool gInited;
928 static uint8_t gTableGdi[256]; 918 static uint8_t gTableGdi[256];
929 if (!gInited) { 919 if (gInited) {
920 // Need a L/L (read) barrier (acquire not needed). If gInited is observe d
921 // true then gTableGdi is observable, but it must be requested.
922 } else {
930 build_power_table(gTableGdi, 2.3f); 923 build_power_table(gTableGdi, 2.3f);
924 // Need a S/S (write) barrier (release not needed) here so that this
925 // write to gInited becomes observable after gTableGdi.
931 gInited = true; 926 gInited = true;
932 } 927 }
933 return gTableGdi; 928 return gTableGdi;
934 } 929 }
935 930
936 /** 931 /**
937 * This will invert the gamma applied by GDI ClearType, so we can get linear 932 * This will invert the gamma applied by GDI ClearType, so we can get linear
938 * values. 933 * values.
939 * 934 *
940 * GDI ClearType uses SPI_GETFONTSMOOTHINGCONTRAST / 1000 as the gamma value. 935 * GDI ClearType uses SPI_GETFONTSMOOTHINGCONTRAST / 1000 as the gamma value.
941 * If this value is not specified, the default is a gamma of 1.4. 936 * If this value is not specified, the default is a gamma of 1.4.
942 */ 937 */
943 static const uint8_t* getInverseGammaTableClearType() { 938 static const uint8_t* getInverseGammaTableClearType() {
939 // We don't expect SPI_GETFONTSMOOTHINGCONTRAST to ever change, so building
940 // gTableClearType with build_power_table is effectively idempotent.
944 static bool gInited; 941 static bool gInited;
945 static uint8_t gTableClearType[256]; 942 static uint8_t gTableClearType[256];
946 if (!gInited) { 943 if (gInited) {
944 // Need a L/L (read) barrier (acquire not needed). If gInited is observe d
945 // true then gTableClearType is observable, but it must be requested.
946 } else {
947 UINT level = 0; 947 UINT level = 0;
948 if (!SystemParametersInfo(SPI_GETFONTSMOOTHINGCONTRAST, 0, &level, 0) || !level) { 948 if (!SystemParametersInfo(SPI_GETFONTSMOOTHINGCONTRAST, 0, &level, 0) || !level) {
949 // can't get the data, so use a default 949 // can't get the data, so use a default
950 level = 1400; 950 level = 1400;
951 } 951 }
952 build_power_table(gTableClearType, level / 1000.0f); 952 build_power_table(gTableClearType, level / 1000.0f);
953 // Need a S/S (write) barrier (release not needed) here so that this
954 // write to gInited becomes observable after gTableClearType.
953 gInited = true; 955 gInited = true;
954 } 956 }
955 return gTableClearType; 957 return gTableClearType;
956 } 958 }
957 959
958 #include "SkColorPriv.h" 960 #include "SkColorPriv.h"
959 961
960 //Cannot assume that the input rgb is gray due to possible setting of kGenA8From LCD_Flag. 962 //Cannot assume that the input rgb is gray due to possible setting of kGenA8From LCD_Flag.
961 template<bool APPLY_PREBLEND> 963 template<bool APPLY_PREBLEND>
962 static inline uint8_t rgb_to_a8(SkGdiRGB rgb, const uint8_t* table8) { 964 static inline uint8_t rgb_to_a8(SkGdiRGB rgb, const uint8_t* table8) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
998 return (c + (c & 1)) & 0x00FFFFFF; 1000 return (c + (c & 1)) & 0x00FFFFFF;
999 } 1001 }
1000 1002
1001 static bool is_rgb_really_bw(const SkGdiRGB* src, int width, int height, int src RB) { 1003 static bool is_rgb_really_bw(const SkGdiRGB* src, int width, int height, int src RB) {
1002 for (int y = 0; y < height; ++y) { 1004 for (int y = 0; y < height; ++y) {
1003 for (int x = 0; x < width; ++x) { 1005 for (int x = 0; x < width; ++x) {
1004 if (is_not_black_or_white(src[x])) { 1006 if (is_not_black_or_white(src[x])) {
1005 return false; 1007 return false;
1006 } 1008 }
1007 } 1009 }
1008 src = SkTAddByteOffset(src, srcRB); 1010 src = SkTAddOffset<const SkGdiRGB>(src, srcRB);
1009 } 1011 }
1010 return true; 1012 return true;
1011 } 1013 }
1012 1014
1013 // gdi's bitmap is upside-down, so we reverse dst walking in Y 1015 // gdi's bitmap is upside-down, so we reverse dst walking in Y
1014 // whenever we copy it into skia's buffer 1016 // whenever we copy it into skia's buffer
1015 static void rgb_to_bw(const SkGdiRGB* SK_RESTRICT src, size_t srcRB, 1017 static void rgb_to_bw(const SkGdiRGB* SK_RESTRICT src, size_t srcRB,
1016 const SkGlyph& glyph) { 1018 const SkGlyph& glyph) {
1017 const int width = glyph.fWidth; 1019 const int width = glyph.fWidth;
1018 const size_t dstRB = (width + 7) >> 3; 1020 const size_t dstRB = (width + 7) >> 3;
(...skipping 24 matching lines...) Expand all
1043 } 1045 }
1044 if (bitCount > 0) { 1046 if (bitCount > 0) {
1045 unsigned byte = 0; 1047 unsigned byte = 0;
1046 unsigned mask = 0x80; 1048 unsigned mask = 0x80;
1047 for (int i = 0; i < bitCount; i++) { 1049 for (int i = 0; i < bitCount; i++) {
1048 byte |= src[i] & mask; 1050 byte |= src[i] & mask;
1049 mask >>= 1; 1051 mask >>= 1;
1050 } 1052 }
1051 dst[byteCount] = byte; 1053 dst[byteCount] = byte;
1052 } 1054 }
1053 src = SkTAddByteOffset(src, srcRB); 1055 src = SkTAddOffset<const SkGdiRGB>(src, srcRB);
1054 dst -= dstRB; 1056 dst -= dstRB;
1055 } 1057 }
1056 } 1058 }
1057 1059
1058 template<bool APPLY_PREBLEND> 1060 template<bool APPLY_PREBLEND>
1059 static void rgb_to_a8(const SkGdiRGB* SK_RESTRICT src, size_t srcRB, 1061 static void rgb_to_a8(const SkGdiRGB* SK_RESTRICT src, size_t srcRB,
1060 const SkGlyph& glyph, const uint8_t* table8) { 1062 const SkGlyph& glyph, const uint8_t* table8) {
1061 const size_t dstRB = glyph.rowBytes(); 1063 const size_t dstRB = glyph.rowBytes();
1062 const int width = glyph.fWidth; 1064 const int width = glyph.fWidth;
1063 uint8_t* SK_RESTRICT dst = (uint8_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB); 1065 uint8_t* SK_RESTRICT dst = (uint8_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB);
1064 1066
1065 for (int y = 0; y < glyph.fHeight; y++) { 1067 for (int y = 0; y < glyph.fHeight; y++) {
1066 for (int i = 0; i < width; i++) { 1068 for (int i = 0; i < width; i++) {
1067 dst[i] = rgb_to_a8<APPLY_PREBLEND>(src[i], table8); 1069 dst[i] = rgb_to_a8<APPLY_PREBLEND>(src[i], table8);
1068 } 1070 }
1069 src = SkTAddByteOffset(src, srcRB); 1071 src = SkTAddOffset<const SkGdiRGB>(src, srcRB);
1070 dst -= dstRB; 1072 dst -= dstRB;
1071 } 1073 }
1072 } 1074 }
1073 1075
1074 template<bool APPLY_PREBLEND> 1076 template<bool APPLY_PREBLEND>
1075 static void rgb_to_lcd16(const SkGdiRGB* SK_RESTRICT src, size_t srcRB, const Sk Glyph& glyph, 1077 static void rgb_to_lcd16(const SkGdiRGB* SK_RESTRICT src, size_t srcRB, const Sk Glyph& glyph,
1076 const uint8_t* tableR, const uint8_t* tableG, const uin t8_t* tableB) { 1078 const uint8_t* tableR, const uint8_t* tableG, const uin t8_t* tableB) {
1077 const size_t dstRB = glyph.rowBytes(); 1079 const size_t dstRB = glyph.rowBytes();
1078 const int width = glyph.fWidth; 1080 const int width = glyph.fWidth;
1079 uint16_t* SK_RESTRICT dst = (uint16_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB); 1081 uint16_t* SK_RESTRICT dst = (uint16_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB);
1080 1082
1081 for (int y = 0; y < glyph.fHeight; y++) { 1083 for (int y = 0; y < glyph.fHeight; y++) {
1082 for (int i = 0; i < width; i++) { 1084 for (int i = 0; i < width; i++) {
1083 dst[i] = rgb_to_lcd16<APPLY_PREBLEND>(src[i], tableR, tableG, tableB ); 1085 dst[i] = rgb_to_lcd16<APPLY_PREBLEND>(src[i], tableR, tableG, tableB );
1084 } 1086 }
1085 src = SkTAddByteOffset(src, srcRB); 1087 src = SkTAddOffset<const SkGdiRGB>(src, srcRB);
1086 dst = (uint16_t*)((char*)dst - dstRB); 1088 dst = (uint16_t*)((char*)dst - dstRB);
1087 } 1089 }
1088 } 1090 }
1089 1091
1090 template<bool APPLY_PREBLEND> 1092 template<bool APPLY_PREBLEND>
1091 static void rgb_to_lcd32(const SkGdiRGB* SK_RESTRICT src, size_t srcRB, const Sk Glyph& glyph, 1093 static void rgb_to_lcd32(const SkGdiRGB* SK_RESTRICT src, size_t srcRB, const Sk Glyph& glyph,
1092 const uint8_t* tableR, const uint8_t* tableG, const uin t8_t* tableB) { 1094 const uint8_t* tableR, const uint8_t* tableG, const uin t8_t* tableB) {
1093 const size_t dstRB = glyph.rowBytes(); 1095 const size_t dstRB = glyph.rowBytes();
1094 const int width = glyph.fWidth; 1096 const int width = glyph.fWidth;
1095 uint32_t* SK_RESTRICT dst = (uint32_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB); 1097 uint32_t* SK_RESTRICT dst = (uint32_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB);
1096 1098
1097 for (int y = 0; y < glyph.fHeight; y++) { 1099 for (int y = 0; y < glyph.fHeight; y++) {
1098 for (int i = 0; i < width; i++) { 1100 for (int i = 0; i < width; i++) {
1099 dst[i] = rgb_to_lcd32<APPLY_PREBLEND>(src[i], tableR, tableG, tableB ); 1101 dst[i] = rgb_to_lcd32<APPLY_PREBLEND>(src[i], tableR, tableG, tableB );
1100 } 1102 }
1101 src = SkTAddByteOffset(src, srcRB); 1103 src = SkTAddOffset<const SkGdiRGB>(src, srcRB);
1102 dst = (uint32_t*)((char*)dst - dstRB); 1104 dst = (uint32_t*)((char*)dst - dstRB);
1103 } 1105 }
1104 } 1106 }
1105 1107
1106 static inline unsigned clamp255(unsigned x) { 1108 static inline unsigned clamp255(unsigned x) {
1107 SkASSERT(x <= 256); 1109 SkASSERT(x <= 256);
1108 return x - (x >> 8); 1110 return x - (x >> 8);
1109 } 1111 }
1110 1112
1111 void SkScalerContext_Windows::generateImage(const SkGlyph& glyph) { 1113 void SkScalerContext_Windows::generateImage(const SkGlyph& glyph) {
1112 SkAutoMutexAcquire ac(gFTMutex);
1113 SkASSERT(fDDC); 1114 SkASSERT(fDDC);
1114 1115
1115 const bool isBW = SkMask::kBW_Format == fRec.fMaskFormat; 1116 const bool isBW = SkMask::kBW_Format == fRec.fMaskFormat;
1116 const bool isAA = !isLCD(fRec); 1117 const bool isAA = !isLCD(fRec);
1117 1118
1118 size_t srcRB; 1119 size_t srcRB;
1119 const void* bits = fOffscreen.draw(glyph, isBW, &srcRB); 1120 const void* bits = fOffscreen.draw(glyph, isBW, &srcRB);
1120 if (NULL == bits) { 1121 if (NULL == bits) {
1121 LogFontTypeface::EnsureAccessible(this->getTypeface()); 1122 LogFontTypeface::EnsureAccessible(this->getTypeface());
1122 bits = fOffscreen.draw(glyph, isBW, &srcRB); 1123 bits = fOffscreen.draw(glyph, isBW, &srcRB);
(...skipping 18 matching lines...) Expand all
1141 //Other code may also be applying the pre-blend, so we'd need another 1142 //Other code may also be applying the pre-blend, so we'd need another
1142 //one with this and one without. 1143 //one with this and one without.
1143 SkGdiRGB* addr = (SkGdiRGB*)bits; 1144 SkGdiRGB* addr = (SkGdiRGB*)bits;
1144 for (int y = 0; y < glyph.fHeight; ++y) { 1145 for (int y = 0; y < glyph.fHeight; ++y) {
1145 for (int x = 0; x < glyph.fWidth; ++x) { 1146 for (int x = 0; x < glyph.fWidth; ++x) {
1146 int r = (addr[x] >> 16) & 0xFF; 1147 int r = (addr[x] >> 16) & 0xFF;
1147 int g = (addr[x] >> 8) & 0xFF; 1148 int g = (addr[x] >> 8) & 0xFF;
1148 int b = (addr[x] >> 0) & 0xFF; 1149 int b = (addr[x] >> 0) & 0xFF;
1149 addr[x] = (table[r] << 16) | (table[g] << 8) | table[b]; 1150 addr[x] = (table[r] << 16) | (table[g] << 8) | table[b];
1150 } 1151 }
1151 addr = SkTAddByteOffset(addr, srcRB); 1152 addr = SkTAddOffset<SkGdiRGB>(addr, srcRB);
1152 } 1153 }
1153 } 1154 }
1154 1155
1155 int width = glyph.fWidth; 1156 int width = glyph.fWidth;
1156 size_t dstRB = glyph.rowBytes(); 1157 size_t dstRB = glyph.rowBytes();
1157 if (isBW) { 1158 if (isBW) {
1158 const uint8_t* src = (const uint8_t*)bits; 1159 const uint8_t* src = (const uint8_t*)bits;
1159 uint8_t* dst = (uint8_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * ds tRB); 1160 uint8_t* dst = (uint8_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * ds tRB);
1160 for (int y = 0; y < glyph.fHeight; y++) { 1161 for (int y = 0; y < glyph.fHeight; y++) {
1161 memcpy(dst, src, dstRB); 1162 memcpy(dst, src, dstRB);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1193 } else { 1194 } else {
1194 rgb_to_lcd32<false>(src, srcRB, glyph, 1195 rgb_to_lcd32<false>(src, srcRB, glyph,
1195 fPreBlend.fR, fPreBlend.fG, fPreBlend.fB ); 1196 fPreBlend.fR, fPreBlend.fG, fPreBlend.fB );
1196 } 1197 }
1197 } 1198 }
1198 } 1199 }
1199 } 1200 }
1200 } 1201 }
1201 1202
1202 void SkScalerContext_Windows::generatePath(const SkGlyph& glyph, SkPath* path) { 1203 void SkScalerContext_Windows::generatePath(const SkGlyph& glyph, SkPath* path) {
1203
1204 SkAutoMutexAcquire ac(gFTMutex);
1205
1206 SkASSERT(&glyph && path); 1204 SkASSERT(&glyph && path);
1207 SkASSERT(fDDC); 1205 SkASSERT(fDDC);
1208 1206
1209 path->reset(); 1207 path->reset();
1210 1208
1211 GLYPHMETRICS gm; 1209 GLYPHMETRICS gm;
1212 uint32_t total_size = GetGlyphOutlineW(fDDC, glyph.fID, GGO_NATIVE | GGO_GLY PH_INDEX, &gm, BUFFERSIZE, glyphbuf, &fMat22); 1210
1211 // Out of all the fonts on a typical Windows box,
1212 // 25% of glyphs require more than 2KB.
1213 // 1% of glyphs require more than 4KB.
1214 // 0.01% of glyphs require more than 8KB.
1215 // 8KB is less than 1% of the normal 1MB stack on Windows.
1216 // Note that some web fonts glyphs require more than 20KB.
1217 static const uint16_t BUFFERSIZE = (1 << 13);
1218 SkAutoSTMalloc<BUFFERSIZE, uint8_t> glyphbuf(BUFFERSIZE);
1219
1220 const UINT flags = GGO_NATIVE | GGO_GLYPH_INDEX;
1221 DWORD total_size = GetGlyphOutlineW(fDDC, glyph.fID, flags, &gm, BUFFERSIZE, glyphbuf, &fMat22);
1213 if (GDI_ERROR == total_size) { 1222 if (GDI_ERROR == total_size) {
1214 LogFontTypeface::EnsureAccessible(this->getTypeface()); 1223 // GDI_ERROR because the BUFFERSIZE was too small, or because the data w as not accessible.
1215 total_size = GetGlyphOutlineW(fDDC, glyph.fID, GGO_NATIVE | GGO_GLYPH_IN DEX, &gm, BUFFERSIZE, glyphbuf, &fMat22); 1224 // When the data is not accessable GetGlyphOutlineW fails rather quickly ,
1225 // so just try to get the size. If that fails then ensure the data is ac cessible.
1226 total_size = GetGlyphOutlineW(fDDC, glyph.fID, flags, &gm, 0, NULL, &fMa t22);
1216 if (GDI_ERROR == total_size) { 1227 if (GDI_ERROR == total_size) {
1217 SkASSERT(false); 1228 LogFontTypeface::EnsureAccessible(this->getTypeface());
1218 return; 1229 total_size = GetGlyphOutlineW(fDDC, glyph.fID, flags, &gm, 0, NULL, &fMat22);
1230 if (GDI_ERROR == total_size) {
1231 SkASSERT(false);
1232 return;
1233 }
1234 }
1235
1236 glyphbuf.reset(total_size);
1237
1238 DWORD ret = GetGlyphOutlineW(fDDC, glyph.fID, flags, &gm, total_size, gl yphbuf, &fMat22);
1239 if (GDI_ERROR == ret) {
1240 LogFontTypeface::EnsureAccessible(this->getTypeface());
1241 ret = GetGlyphOutlineW(fDDC, glyph.fID, flags, &gm, total_size, glyp hbuf, &fMat22);
1242 if (GDI_ERROR == ret) {
1243 SkASSERT(false);
1244 return;
1245 }
1219 } 1246 }
1220 } 1247 }
1221 1248
1222 const uint8_t* cur_glyph = glyphbuf; 1249 const uint8_t* cur_glyph = glyphbuf;
1223 const uint8_t* end_glyph = glyphbuf + total_size; 1250 const uint8_t* end_glyph = glyphbuf + total_size;
1224 1251
1225 while (cur_glyph < end_glyph) { 1252 while (cur_glyph < end_glyph) {
1226 const TTPOLYGONHEADER* th = (TTPOLYGONHEADER*)cur_glyph; 1253 const TTPOLYGONHEADER* th = (TTPOLYGONHEADER*)cur_glyph;
1227 1254
1228 const uint8_t* end_poly = cur_glyph + th->cb; 1255 const uint8_t* end_poly = cur_glyph + th->cb;
(...skipping 637 matching lines...) Expand 10 before | Expand all | Expand 10 after
1866 return this->createFromStream(stream); 1893 return this->createFromStream(stream);
1867 } 1894 }
1868 1895
1869 private: 1896 private:
1870 SkTDArray<ENUMLOGFONTEX> fLogFontArray; 1897 SkTDArray<ENUMLOGFONTEX> fLogFontArray;
1871 }; 1898 };
1872 1899
1873 SkFontMgr* SkFontMgr::Factory() { 1900 SkFontMgr* SkFontMgr::Factory() {
1874 return SkNEW(SkFontMgrGDI); 1901 return SkNEW(SkFontMgrGDI);
1875 } 1902 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698