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 "SkAdvancedTypefaceMetrics.h" | 9 #include "SkAdvancedTypefaceMetrics.h" |
10 #include "SkBase64.h" | 10 #include "SkBase64.h" |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
260 } | 260 } |
261 | 261 |
262 protected: | 262 protected: |
263 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE; | 263 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE; |
264 virtual SkScalerContext* onCreateScalerContext(const SkDescriptor*) const SK
_OVERRIDE; | 264 virtual SkScalerContext* onCreateScalerContext(const SkDescriptor*) const SK
_OVERRIDE; |
265 virtual void onFilterRec(SkScalerContextRec*) const SK_OVERRIDE; | 265 virtual void onFilterRec(SkScalerContextRec*) const SK_OVERRIDE; |
266 virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics( | 266 virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics( |
267 SkAdvancedTypefaceMetrics::PerGlyphInfo, | 267 SkAdvancedTypefaceMetrics::PerGlyphInfo, |
268 const uint32_t*, uint32_t) const SK_OVERRIDE; | 268 const uint32_t*, uint32_t) const SK_OVERRIDE; |
269 virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE
; | 269 virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE
; |
| 270 virtual int onCharsToGlyphs(const void* chars, Encoding encoding, |
| 271 uint16_t glyphs[], int glyphCount) const SK_OVER
RIDE; |
270 virtual int onCountGlyphs() const SK_OVERRIDE; | 272 virtual int onCountGlyphs() const SK_OVERRIDE; |
271 virtual int onGetUPEM() const SK_OVERRIDE; | 273 virtual int onGetUPEM() const SK_OVERRIDE; |
272 virtual SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const SK_
OVERRIDE; | 274 virtual SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const SK_
OVERRIDE; |
273 virtual int onGetTableTags(SkFontTableTag tags[]) const SK_OVERRIDE; | 275 virtual int onGetTableTags(SkFontTableTag tags[]) const SK_OVERRIDE; |
274 virtual size_t onGetTableData(SkFontTableTag, size_t offset, | 276 virtual size_t onGetTableData(SkFontTableTag, size_t offset, |
275 size_t length, void* data) const SK_OVERRIDE; | 277 size_t length, void* data) const SK_OVERRIDE; |
276 virtual SkTypeface* onRefMatchingStyle(Style) const SK_OVERRIDE; | 278 virtual SkTypeface* onRefMatchingStyle(Style) const SK_OVERRIDE; |
277 }; | 279 }; |
278 | 280 |
279 class FontMemResourceTypeface : public LogFontTypeface { | 281 class FontMemResourceTypeface : public LogFontTypeface { |
(...skipping 1792 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2072 } | 2074 } |
2073 } | 2075 } |
2074 | 2076 |
2075 SelectObject(hdc, savefont); | 2077 SelectObject(hdc, savefont); |
2076 DeleteObject(font); | 2078 DeleteObject(font); |
2077 DeleteDC(hdc); | 2079 DeleteDC(hdc); |
2078 | 2080 |
2079 return stream; | 2081 return stream; |
2080 } | 2082 } |
2081 | 2083 |
| 2084 static void bmpCharsToGlyphs(HDC hdc, const WCHAR* bmpChars, int count, uint16_t
* glyphs, |
| 2085 bool Ox1FHack) |
| 2086 { |
| 2087 DWORD result = GetGlyphIndicesW(hdc, bmpChars, count, glyphs, GGI_MARK_NONEX
ISTING_GLYPHS); |
| 2088 if (GDI_ERROR == result) { |
| 2089 for (int i = 0; i < count; ++i) { |
| 2090 glyphs[i] = 0; |
| 2091 } |
| 2092 return; |
| 2093 } |
| 2094 |
| 2095 if (Ox1FHack) { |
| 2096 for (int i = 0; i < count; ++i) { |
| 2097 if (0xFFFF == glyphs[i] || 0x1F == glyphs[i]) { |
| 2098 glyphs[i] = 0; |
| 2099 } |
| 2100 } |
| 2101 } else { |
| 2102 for (int i = 0; i < count; ++i) { |
| 2103 if (0xFFFF == glyphs[i]){ |
| 2104 glyphs[i] = 0; |
| 2105 } |
| 2106 } |
| 2107 } |
| 2108 } |
| 2109 |
| 2110 static uint16_t nonBmpCharToGlyph(HDC hdc, SCRIPT_CACHE* scriptCache, const WCHA
R utf16[2]) { |
| 2111 uint16_t index = 0; |
| 2112 // Use uniscribe to detemine glyph index for non-BMP characters. |
| 2113 static const int numWCHAR = 2; |
| 2114 static const int maxItems = 2; |
| 2115 // MSDN states that this can be NULL, but some things don't work then. |
| 2116 SCRIPT_CONTROL scriptControl = { 0 }; |
| 2117 // Add extra item to SCRIPT_ITEM to work around a bug (now documented). |
| 2118 // https://bugzilla.mozilla.org/show_bug.cgi?id=366643 |
| 2119 SCRIPT_ITEM si[maxItems + 1]; |
| 2120 int numItems; |
| 2121 HRZM(ScriptItemize(utf16, numWCHAR, maxItems, &scriptControl, NULL, si, &num
Items), |
| 2122 "Could not itemize character."); |
| 2123 |
| 2124 // Sometimes ScriptShape cannot find a glyph for a non-BMP and returns 2 spa
ce glyphs. |
| 2125 static const int maxGlyphs = 2; |
| 2126 SCRIPT_VISATTR vsa[maxGlyphs]; |
| 2127 WORD outGlyphs[maxGlyphs]; |
| 2128 WORD logClust[numWCHAR]; |
| 2129 int numGlyphs; |
| 2130 HRZM(ScriptShape(hdc, scriptCache, utf16, numWCHAR, maxGlyphs, &si[0].a, |
| 2131 outGlyphs, logClust, vsa, &numGlyphs), |
| 2132 "Could not shape character."); |
| 2133 if (1 == numGlyphs) { |
| 2134 index = outGlyphs[0]; |
| 2135 } |
| 2136 return index; |
| 2137 } |
| 2138 |
| 2139 class SkAutoHDC { |
| 2140 public: |
| 2141 SkAutoHDC(const LOGFONT& lf) |
| 2142 : fHdc(::CreateCompatibleDC(NULL)) |
| 2143 , fFont(::CreateFontIndirect(&lf)) |
| 2144 , fSavefont((HFONT)SelectObject(fHdc, fFont)) |
| 2145 { } |
| 2146 ~SkAutoHDC() { |
| 2147 SelectObject(fHdc, fSavefont); |
| 2148 DeleteObject(fFont); |
| 2149 DeleteDC(fHdc); |
| 2150 } |
| 2151 operator HDC() { return fHdc; } |
| 2152 private: |
| 2153 HDC fHdc; |
| 2154 HFONT fFont; |
| 2155 HFONT fSavefont; |
| 2156 }; |
| 2157 |
| 2158 int LogFontTypeface::onCharsToGlyphs(const void* chars, Encoding encoding, |
| 2159 uint16_t userGlyphs[], int glyphCount) cons
t |
| 2160 { |
| 2161 SkAutoHDC hdc(fLogFont); |
| 2162 |
| 2163 TEXTMETRIC tm; |
| 2164 if (0 == GetTextMetrics(hdc, &tm)) { |
| 2165 call_ensure_accessible(fLogFont); |
| 2166 if (0 == GetTextMetrics(hdc, &tm)) { |
| 2167 tm.tmPitchAndFamily = TMPF_TRUETYPE; |
| 2168 } |
| 2169 } |
| 2170 bool Ox1FHack = !(tm.tmPitchAndFamily & TMPF_VECTOR) /*&& winVer < Vista */; |
| 2171 |
| 2172 SkAutoSTMalloc<256, uint16_t> scratchGlyphs; |
| 2173 uint16_t* glyphs; |
| 2174 if (userGlyphs != NULL) { |
| 2175 glyphs = userGlyphs; |
| 2176 } else { |
| 2177 glyphs = scratchGlyphs.reset(glyphCount); |
| 2178 } |
| 2179 |
| 2180 SCRIPT_CACHE sc = 0; |
| 2181 switch (encoding) { |
| 2182 case SkTypeface::kUTF8_Encoding: { |
| 2183 static const int scratchCount = 256; |
| 2184 WCHAR scratch[scratchCount]; |
| 2185 int glyphIndex = 0; |
| 2186 const char* currentUtf8 = reinterpret_cast<const char*>(chars); |
| 2187 SkUnichar currentChar; |
| 2188 if (glyphCount) { |
| 2189 currentChar = SkUTF8_NextUnichar(¤tUtf8); |
| 2190 } |
| 2191 while (glyphIndex < glyphCount) { |
| 2192 // Try a run of bmp. |
| 2193 int glyphsLeft = SkTMin(glyphCount - glyphIndex, scratchCount); |
| 2194 int runLength = 0; |
| 2195 while (runLength < glyphsLeft && currentChar <= 0xFFFF) { |
| 2196 scratch[runLength] = static_cast<WCHAR>(currentChar); |
| 2197 ++runLength; |
| 2198 if (runLength < glyphsLeft) { |
| 2199 currentChar = SkUTF8_NextUnichar(¤tUtf8); |
| 2200 } |
| 2201 } |
| 2202 if (runLength) { |
| 2203 bmpCharsToGlyphs(hdc, scratch, runLength, &glyphs[glyphIndex], O
x1FHack); |
| 2204 glyphIndex += runLength; |
| 2205 } |
| 2206 |
| 2207 // Try a run of non-bmp. |
| 2208 while (glyphIndex < glyphCount && currentChar > 0xFFFF) { |
| 2209 SkUTF16_FromUnichar(currentChar, reinterpret_cast<uint16_t*>(scr
atch)); |
| 2210 glyphs[glyphIndex] = nonBmpCharToGlyph(hdc, &sc, scratch); |
| 2211 ++glyphIndex; |
| 2212 if (glyphIndex < glyphCount) { |
| 2213 currentChar = SkUTF8_NextUnichar(¤tUtf8); |
| 2214 } |
| 2215 } |
| 2216 } |
| 2217 break; |
| 2218 } |
| 2219 case SkTypeface::kUTF16_Encoding: { |
| 2220 int glyphIndex = 0; |
| 2221 const WCHAR* currentUtf16 = reinterpret_cast<const WCHAR*>(chars); |
| 2222 while (glyphIndex < glyphCount) { |
| 2223 // Try a run of bmp. |
| 2224 int glyphsLeft = glyphCount - glyphIndex; |
| 2225 int runLength = 0; |
| 2226 while (runLength < glyphsLeft && !SkUTF16_IsHighSurrogate(currentUtf
16[runLength])) { |
| 2227 ++runLength; |
| 2228 } |
| 2229 if (runLength) { |
| 2230 bmpCharsToGlyphs(hdc, currentUtf16, runLength, &glyphs[glyphInde
x], Ox1FHack); |
| 2231 glyphIndex += runLength; |
| 2232 currentUtf16 += runLength; |
| 2233 } |
| 2234 |
| 2235 // Try a run of non-bmp. |
| 2236 while (glyphIndex < glyphCount && SkUTF16_IsHighSurrogate(*currentUt
f16)) { |
| 2237 glyphs[glyphIndex] = nonBmpCharToGlyph(hdc, &sc, currentUtf16); |
| 2238 ++glyphIndex; |
| 2239 currentUtf16 += 2; |
| 2240 } |
| 2241 } |
| 2242 break; |
| 2243 } |
| 2244 case SkTypeface::kUTF32_Encoding: { |
| 2245 static const int scratchCount = 256; |
| 2246 WCHAR scratch[scratchCount]; |
| 2247 int glyphIndex = 0; |
| 2248 const uint32_t* utf32 = reinterpret_cast<const uint32_t*>(chars); |
| 2249 while (glyphIndex < glyphCount) { |
| 2250 // Try a run of bmp. |
| 2251 int glyphsLeft = SkTMin(glyphCount - glyphIndex, scratchCount); |
| 2252 int runLength = 0; |
| 2253 while (runLength < glyphsLeft && utf32[glyphIndex + runLength] <= 0x
FFFF) { |
| 2254 scratch[runLength] = static_cast<WCHAR>(utf32[glyphIndex + runLe
ngth]); |
| 2255 ++runLength; |
| 2256 } |
| 2257 if (runLength) { |
| 2258 bmpCharsToGlyphs(hdc, scratch, runLength, &glyphs[glyphIndex], O
x1FHack); |
| 2259 glyphIndex += runLength; |
| 2260 } |
| 2261 |
| 2262 // Try a run of non-bmp. |
| 2263 while (glyphIndex < glyphCount && utf32[glyphIndex] > 0xFFFF) { |
| 2264 SkUTF16_FromUnichar(utf32[glyphIndex], reinterpret_cast<uint16_t
*>(scratch)); |
| 2265 glyphs[glyphIndex] = nonBmpCharToGlyph(hdc, &sc, scratch); |
| 2266 ++glyphIndex; |
| 2267 } |
| 2268 } |
| 2269 break; |
| 2270 } |
| 2271 default: |
| 2272 SK_CRASH(); |
| 2273 } |
| 2274 |
| 2275 if (sc) { |
| 2276 ::ScriptFreeCache(&sc); |
| 2277 } |
| 2278 |
| 2279 for (int i = 0; i < glyphCount; ++i) { |
| 2280 if (0 == glyphs[i]) { |
| 2281 return i; |
| 2282 } |
| 2283 } |
| 2284 return glyphCount; |
| 2285 } |
| 2286 |
2082 int LogFontTypeface::onCountGlyphs() const { | 2287 int LogFontTypeface::onCountGlyphs() const { |
2083 HDC hdc = ::CreateCompatibleDC(NULL); | 2288 HDC hdc = ::CreateCompatibleDC(NULL); |
2084 HFONT font = CreateFontIndirect(&fLogFont); | 2289 HFONT font = CreateFontIndirect(&fLogFont); |
2085 HFONT savefont = (HFONT)SelectObject(hdc, font); | 2290 HFONT savefont = (HFONT)SelectObject(hdc, font); |
2086 | 2291 |
2087 unsigned int glyphCount = calculateGlyphCount(hdc, fLogFont); | 2292 unsigned int glyphCount = calculateGlyphCount(hdc, fLogFont); |
2088 | 2293 |
2089 SelectObject(hdc, savefont); | 2294 SelectObject(hdc, savefont); |
2090 DeleteObject(font); | 2295 DeleteObject(font); |
2091 DeleteDC(hdc); | 2296 DeleteDC(hdc); |
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2427 | 2632 |
2428 SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) { | 2633 SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) { |
2429 return create_from_stream(stream); | 2634 return create_from_stream(stream); |
2430 } | 2635 } |
2431 | 2636 |
2432 #endif | 2637 #endif |
2433 | 2638 |
2434 SkFontMgr* SkFontMgr_New_GDI() { | 2639 SkFontMgr* SkFontMgr_New_GDI() { |
2435 return SkNEW(SkFontMgrGDI); | 2640 return SkNEW(SkFontMgrGDI); |
2436 } | 2641 } |
OLD | NEW |