SkFontHost_win.cpp revision 7bdd614a1940935d3badeb54f7aae75d76ea830d
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 2ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com/* 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 7ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com */ 8ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 9ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com#include "SkAdvancedTypefaceMetrics.h" 10a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com#include "SkBase64.h" 111bfe01d06b896eca94c80d9af9a6bb30216b5e42bungeman@google.com#include "SkColorPriv.h" 12a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com#include "SkData.h" 13a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com#include "SkDescriptor.h" 14e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com#include "SkFontDescriptor.h" 15a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com#include "SkFontHost.h" 16bbe50131413098bffed9186660c41f047d881596bungeman@google.com#include "SkGlyph.h" 1797efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com#include "SkMaskGamma.h" 187bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com#include "SkOTTable_maxp.h" 19a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com#include "SkOTUtils.h" 2027889877c0e3c909dd4afd7b5e7b1d58cbf61ae6reed@google.com#include "SkPath.h" 21ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com#include "SkStream.h" 22a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com#include "SkString.h" 2305a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com#include "SkTemplates.h" 24ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com#include "SkThread.h" 25ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com#include "SkTypeface_win.h" 2659d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com#include "SkTypefaceCache.h" 27ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com#include "SkUtils.h" 28ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 29a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com#include "SkTypes.h" 30a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com#include <tchar.h> 31a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com#include <usp10.h> 32a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com#include <objbase.h> 33ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 34f210f505ffffccc15ae5e91f8ccb9763ba7fc152reed@google.comstatic void (*gEnsureLOGFONTAccessibleProc)(const LOGFONT&); 35f210f505ffffccc15ae5e91f8ccb9763ba7fc152reed@google.com 36f210f505ffffccc15ae5e91f8ccb9763ba7fc152reed@google.comvoid SkTypeface_SetEnsureLOGFONTAccessibleProc(void (*proc)(const LOGFONT&)) { 37f210f505ffffccc15ae5e91f8ccb9763ba7fc152reed@google.com gEnsureLOGFONTAccessibleProc = proc; 38f210f505ffffccc15ae5e91f8ccb9763ba7fc152reed@google.com} 39f210f505ffffccc15ae5e91f8ccb9763ba7fc152reed@google.com 40055180cb9c47c87e5ee8c9fa6d3f6a6079ad6f35reed@google.comstatic void call_ensure_accessible(const LOGFONT& lf) { 41055180cb9c47c87e5ee8c9fa6d3f6a6079ad6f35reed@google.com if (gEnsureLOGFONTAccessibleProc) { 42055180cb9c47c87e5ee8c9fa6d3f6a6079ad6f35reed@google.com gEnsureLOGFONTAccessibleProc(lf); 43055180cb9c47c87e5ee8c9fa6d3f6a6079ad6f35reed@google.com } 44055180cb9c47c87e5ee8c9fa6d3f6a6079ad6f35reed@google.com} 45055180cb9c47c87e5ee8c9fa6d3f6a6079ad6f35reed@google.com 46055180cb9c47c87e5ee8c9fa6d3f6a6079ad6f35reed@google.com/////////////////////////////////////////////////////////////////////////////// 47055180cb9c47c87e5ee8c9fa6d3f6a6079ad6f35reed@google.com 486f5df48c1d07295b75c1955a69142fb5e66b8647reed@google.com// always packed xxRRGGBB 496f5df48c1d07295b75c1955a69142fb5e66b8647reed@google.comtypedef uint32_t SkGdiRGB; 506f5df48c1d07295b75c1955a69142fb5e66b8647reed@google.com 51a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com// define this in your Makefile or .gyp to enforce AA requests 52a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com// which GDI ignores at small sizes. This flag guarantees AA 53a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com// for rotated text, regardless of GDI's notions. 54a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com//#define SK_ENFORCE_ROTATED_TEXT_AA_ON_WINDOWS 55a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com 5682a34d83f646d069ef2d1d7b649d0a0b1829d62freed@google.comstatic bool isLCD(const SkScalerContext::Rec& rec) { 5782a34d83f646d069ef2d1d7b649d0a0b1829d62freed@google.com return SkMask::kLCD16_Format == rec.fMaskFormat || 5882a34d83f646d069ef2d1d7b649d0a0b1829d62freed@google.com SkMask::kLCD32_Format == rec.fMaskFormat; 5982a34d83f646d069ef2d1d7b649d0a0b1829d62freed@google.com} 6082a34d83f646d069ef2d1d7b649d0a0b1829d62freed@google.com 61a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.comstatic bool bothZero(SkScalar a, SkScalar b) { 62a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com return 0 == a && 0 == b; 63a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com} 64a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com 65a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com// returns false if there is any non-90-rotation or skew 66a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.comstatic bool isAxisAligned(const SkScalerContext::Rec& rec) { 67a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com return 0 == rec.fPreSkewX && 68a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com (bothZero(rec.fPost2x2[0][1], rec.fPost2x2[1][0]) || 69a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com bothZero(rec.fPost2x2[0][0], rec.fPost2x2[1][1])); 70a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com} 71a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com 72a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.comstatic bool needToRenderWithSkia(const SkScalerContext::Rec& rec) { 73a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com#ifdef SK_ENFORCE_ROTATED_TEXT_AA_ON_WINDOWS 74a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com // What we really want to catch is when GDI will ignore the AA request and give 75a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com // us BW instead. Smallish rotated text is one heuristic, so this code is just 76a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com // an approximation. We shouldn't need to do this for larger sizes, but at those 77a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com // sizes, the quality difference gets less and less between our general 78a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com // scanconverter and GDI's. 79a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com if (SkMask::kA8_Format == rec.fMaskFormat && !isAxisAligned(rec)) { 80a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com return true; 81a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com } 82a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com#endif 83a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com // false means allow GDI to generate the bits 84a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com return false; 85a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com} 86a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com 87ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.comusing namespace skia_advanced_typeface_metrics_utils; 88ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 89ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com/** 905aa937b300475c956bfad0c34a6daa71d166f6factguil@chromium.org * Since LOGFONT wants its textsize as an int, and we support fractional sizes, 91ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com * and since we have a cache of LOGFONTs for our tyepfaces, we always set the 92ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com * lfHeight to a canonical size, and then we use the 2x2 matrix to achieve the 93ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com * actual requested size. 9460af92cb6de814b14ee5d40b71bfbd79227597ecreed@google.com * 9560af92cb6de814b14ee5d40b71bfbd79227597ecreed@google.com * Not critical to match the font's upem, but we want it big enough to avoid 9660af92cb6de814b14ee5d40b71bfbd79227597ecreed@google.com * precision loss for GDI calls that return ints (e.g. GetOutlineFontMetrics). 97ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com */ 9860af92cb6de814b14ee5d40b71bfbd79227597ecreed@google.comstatic const int gCanonicalTextSize = 2048; 99ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 100a65a681d43a8e9f5d8726a389832e957b07ee16breed@google.comstatic void tchar_to_skstring(const TCHAR t[], SkString* s) { 101484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com#ifdef UNICODE 102484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com size_t sSize = WideCharToMultiByte(CP_UTF8, 0, t, -1, NULL, 0, NULL, NULL); 103484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com s->resize(sSize); 104484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com WideCharToMultiByte(CP_UTF8, 0, t, -1, s->writable_str(), sSize, NULL, NULL); 105484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com#else 106484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com s->set(t); 107484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com#endif 108484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com} 109484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com 110ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.comstatic void make_canonical(LOGFONT* lf) { 1115aa937b300475c956bfad0c34a6daa71d166f6factguil@chromium.org lf->lfHeight = -gCanonicalTextSize; 11259d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com lf->lfQuality = CLEARTYPE_QUALITY;//PROOF_QUALITY; 11359d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com lf->lfCharSet = DEFAULT_CHARSET; 11482a34d83f646d069ef2d1d7b649d0a0b1829d62freed@google.com// lf->lfClipPrecision = 64; 11559d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com} 11659d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com 11790d812b77ab025d5fd01dab904287f5c5bf56228bungeman@google.comstatic SkTypeface::Style get_style(const LOGFONT& lf) { 11859d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com unsigned style = 0; 11959d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com if (lf.lfWeight >= FW_BOLD) { 12059d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com style |= SkTypeface::kBold; 12159d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com } 12259d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com if (lf.lfItalic) { 12359d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com style |= SkTypeface::kItalic; 12459d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com } 12590d812b77ab025d5fd01dab904287f5c5bf56228bungeman@google.com return static_cast<SkTypeface::Style>(style); 12659d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com} 12759d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com 12859d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.comstatic void setStyle(LOGFONT* lf, SkTypeface::Style style) { 12959d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com lf->lfWeight = (style & SkTypeface::kBold) != 0 ? FW_BOLD : FW_NORMAL ; 13059d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com lf->lfItalic = ((style & SkTypeface::kItalic) != 0); 131ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com} 132ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 133ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.comstatic inline FIXED SkFixedToFIXED(SkFixed x) { 134ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com return *(FIXED*)(&x); 135ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com} 136a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.comstatic inline SkFixed SkFIXEDToFixed(FIXED x) { 137a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com return *(SkFixed*)(&x); 138a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com} 139ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 140ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.comstatic inline FIXED SkScalarToFIXED(SkScalar x) { 141ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com return SkFixedToFIXED(SkScalarToFixed(x)); 142ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com} 143ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 1447bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.comstatic unsigned calculateGlyphCount(HDC hdc, const LOGFONT& lf) { 1457bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com TEXTMETRIC textMetric; 1467bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com if (0 == GetTextMetrics(hdc, &textMetric)) { 1477bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com textMetric.tmPitchAndFamily = TMPF_VECTOR; 1487bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com call_ensure_accessible(lf); 1497bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com GetTextMetrics(hdc, &textMetric); 1507bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com } 1517bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com 1527bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com if (!(textMetric.tmPitchAndFamily & TMPF_VECTOR)) { 1537bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com return textMetric.tmLastChar; 1547bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com } 1557bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com 156ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com // The 'maxp' table stores the number of glyphs at offset 4, in 2 bytes. 157ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com uint16_t glyphs; 1587bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com if (GDI_ERROR != GetFontData(hdc, SkOTTableMaximumProfile::TAG, 4, &glyphs, sizeof(glyphs))) { 159ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com return SkEndian_SwapBE16(glyphs); 160ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } 1615aa937b300475c956bfad0c34a6daa71d166f6factguil@chromium.org 162ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com // Binary search for glyph count. 163ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com static const MAT2 mat2 = {{0, 1}, {0, 0}, {0, 0}, {0, 1}}; 164ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com int32_t max = SK_MaxU16 + 1; 165ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com int32_t min = 0; 166ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com GLYPHMETRICS gm; 167ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com while (min < max) { 168ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com int32_t mid = min + ((max - min) / 2); 169ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com if (GetGlyphOutlineW(hdc, mid, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, 170ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com NULL, &mat2) == GDI_ERROR) { 171ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com max = mid; 172ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } else { 173ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com min = mid + 1; 174ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } 175ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } 176ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com SkASSERT(min == max); 177ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com return min; 178ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com} 179ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 1807bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.comstatic unsigned calculateUPEM(HDC hdc, const LOGFONT& lf) { 1817bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com TEXTMETRIC textMetric; 1827bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com if (0 == GetTextMetrics(hdc, &textMetric)) { 1837bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com textMetric.tmPitchAndFamily = TMPF_VECTOR; 1847bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com call_ensure_accessible(lf); 1857bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com GetTextMetrics(hdc, &textMetric); 1867bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com } 1877bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com 1887bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com if (!(textMetric.tmPitchAndFamily & TMPF_VECTOR)) { 1897bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com return textMetric.tmMaxCharWidth; 1907bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com } 1917bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com 1927bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com OUTLINETEXTMETRIC otm; 1937bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com unsigned int otmRet = GetOutlineTextMetrics(hdc, sizeof(otm), &otm); 1947bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com if (0 == otmRet) { 1957bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com call_ensure_accessible(lf); 1967bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com otmRet = GetOutlineTextMetrics(hdc, sizeof(otm), &otm); 1977bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com } 1987bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com 1997bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com return (0 == otmRet) ? 0 : otm.otmEMSquare; 2007bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com} 2017bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com 202ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.comclass LogFontTypeface : public SkTypeface { 203ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.compublic: 204cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com LogFontTypeface(SkTypeface::Style style, SkFontID fontID, const LOGFONT& lf, bool serializeAsStream = false) : 205cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com SkTypeface(style, fontID, false), fLogFont(lf), fSerializeAsStream(serializeAsStream) { 206cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com 207cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com // If the font has cubic outlines, it will not be rendered with ClearType. 208cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com HFONT font = CreateFontIndirect(&lf); 209cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com 210cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com HDC deviceContext = ::CreateCompatibleDC(NULL); 211cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com HFONT savefont = (HFONT)SelectObject(deviceContext, font); 212cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com 213cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com TEXTMETRIC textMetric; 214cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com if (0 == GetTextMetrics(deviceContext, &textMetric)) { 215055180cb9c47c87e5ee8c9fa6d3f6a6079ad6f35reed@google.com call_ensure_accessible(lf); 216cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com if (0 == GetTextMetrics(deviceContext, &textMetric)) { 217cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com textMetric.tmPitchAndFamily = TMPF_TRUETYPE; 218cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com } 219cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com } 220cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com if (deviceContext) { 221cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com ::SelectObject(deviceContext, savefont); 222cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com ::DeleteDC(deviceContext); 223cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com } 224cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com if (font) { 225cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com ::DeleteObject(font); 226cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com } 227cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com 228fe74765f0d302669ae49e68074492bdfe0ce6e6fbungeman@google.com // The fixed pitch bit is set if the font is *not* fixed pitch. 229fe74765f0d302669ae49e68074492bdfe0ce6e6fbungeman@google.com this->setIsFixedPitch((textMetric.tmPitchAndFamily & TMPF_FIXED_PITCH) == 0); 230fe74765f0d302669ae49e68074492bdfe0ce6e6fbungeman@google.com 231cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com // Used a logfont on a memory context, should never get a device font. 232cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com // Therefore all TMPF_DEVICE will be PostScript (cubic) fonts. 233cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com fCanBeLCD = !((textMetric.tmPitchAndFamily & TMPF_VECTOR) && 234cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com (textMetric.tmPitchAndFamily & TMPF_DEVICE)); 235cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com } 236ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 237484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com void getFamilyName(SkString* name) const { 238484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com tchar_to_skstring(fLogFont.lfFaceName, name); 239484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com } 240484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com 24159d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com LOGFONT fLogFont; 242e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com bool fSerializeAsStream; 243cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com bool fCanBeLCD; 244ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 24559d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com static LogFontTypeface* Create(const LOGFONT& lf) { 24690d812b77ab025d5fd01dab904287f5c5bf56228bungeman@google.com SkTypeface::Style style = get_style(lf); 24759d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com SkFontID fontID = SkTypefaceCache::NewFontID(); 24859d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com return new LogFontTypeface(style, fontID, lf); 249ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } 2500da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com 251055180cb9c47c87e5ee8c9fa6d3f6a6079ad6f35reed@google.com static void EnsureAccessible(const SkTypeface* face) { 252055180cb9c47c87e5ee8c9fa6d3f6a6079ad6f35reed@google.com call_ensure_accessible(static_cast<const LogFontTypeface*>(face)->fLogFont); 253055180cb9c47c87e5ee8c9fa6d3f6a6079ad6f35reed@google.com } 254055180cb9c47c87e5ee8c9fa6d3f6a6079ad6f35reed@google.com 2550da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.comprotected: 2560042b9c2a2e6fe954cdfbcd5a5b7449cdf41a4c3reed@google.com virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE; 2570da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com virtual SkScalerContext* onCreateScalerContext(const SkDescriptor*) const SK_OVERRIDE; 2580da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com virtual void onFilterRec(SkScalerContextRec*) const SK_OVERRIDE; 2592689f615e364dc48ad73826564f5b13d2329179dreed@google.com virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics( 2602689f615e364dc48ad73826564f5b13d2329179dreed@google.com SkAdvancedTypefaceMetrics::PerGlyphInfo, 2612689f615e364dc48ad73826564f5b13d2329179dreed@google.com const uint32_t*, uint32_t) const SK_OVERRIDE; 2625526ede94a2fc58bcf6b578b12a29f6addad776dreed@google.com virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE; 2637bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com virtual int onCountGlyphs() const SK_OVERRIDE; 2647bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com virtual int onGetUPEM() const SK_OVERRIDE; 265ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com}; 266ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 267a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.comclass FontMemResourceTypeface : public LogFontTypeface { 268a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.compublic: 269a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com /** 270a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com * Takes ownership of fontMemResource. 271a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com */ 272a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com FontMemResourceTypeface(SkTypeface::Style style, SkFontID fontID, const LOGFONT& lf, HANDLE fontMemResource) : 273cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com LogFontTypeface(style, fontID, lf, true), fFontMemResource(fontMemResource) { 274e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com } 275a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com 276a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com HANDLE fFontMemResource; 277a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com 278a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com /** 279a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com * The created FontMemResourceTypeface takes ownership of fontMemResource. 280a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com */ 281a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com static FontMemResourceTypeface* Create(const LOGFONT& lf, HANDLE fontMemResource) { 282a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com SkTypeface::Style style = get_style(lf); 283a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com SkFontID fontID = SkTypefaceCache::NewFontID(); 284a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com return new FontMemResourceTypeface(style, fontID, lf, fontMemResource); 285a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com } 286a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com 287a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.comprotected: 288a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com virtual void weak_dispose() const SK_OVERRIDE { 289a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com RemoveFontMemResourceEx(fFontMemResource); 290a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com //SkTypefaceCache::Remove(this); 291a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com INHERITED::weak_dispose(); 292a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com } 293a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com 294a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.comprivate: 295a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com typedef LogFontTypeface INHERITED; 296a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com}; 297a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com 298ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.comstatic const LOGFONT& get_default_font() { 299ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com static LOGFONT gDefaultFont; 300ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com return gDefaultFont; 301ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com} 302ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 30359d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.comstatic bool FindByLogFont(SkTypeface* face, SkTypeface::Style requestedStyle, void* ctx) { 304a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com LogFontTypeface* lface = static_cast<LogFontTypeface*>(face); 30559d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com const LOGFONT* lf = reinterpret_cast<const LOGFONT*>(ctx); 306ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 307a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com return lface && 308a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com get_style(lface->fLogFont) == requestedStyle && 30959d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com !memcmp(&lface->fLogFont, lf, sizeof(LOGFONT)); 31059d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com} 31159d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com 31259d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com/** 31359d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com * This guy is public. It first searches the cache, and if a match is not found, 31459d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com * it creates a new face. 31559d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com */ 31659d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.comSkTypeface* SkCreateTypefaceFromLOGFONT(const LOGFONT& origLF) { 31759d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com LOGFONT lf = origLF; 31859d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com make_canonical(&lf); 319ee51d1a6e43615ae640410013c36d2d9873e6aa5bungeman@google.com SkTypeface* face = SkTypefaceCache::FindByProcAndRef(FindByLogFont, &lf); 320ee51d1a6e43615ae640410013c36d2d9873e6aa5bungeman@google.com if (NULL == face) { 32159d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com face = LogFontTypeface::Create(lf); 32290d812b77ab025d5fd01dab904287f5c5bf56228bungeman@google.com SkTypefaceCache::Add(face, get_style(lf)); 32359d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com } 32459d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com return face; 325ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com} 326ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 327db77a6a9a9bef7033aca9dffa99d52be1f51f8d9reed@google.com/** 328a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com * The created SkTypeface takes ownership of fontMemResource. 329a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com */ 330a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.comSkTypeface* SkCreateFontMemResourceTypefaceFromLOGFONT(const LOGFONT& origLF, HANDLE fontMemResource) { 331a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com LOGFONT lf = origLF; 332a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com make_canonical(&lf); 333a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com FontMemResourceTypeface* face = FontMemResourceTypeface::Create(lf, fontMemResource); 334a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com SkTypefaceCache::Add(face, get_style(lf), false); 335a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com return face; 336a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com} 337a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com 338a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com/** 339db77a6a9a9bef7033aca9dffa99d52be1f51f8d9reed@google.com * This guy is public 340db77a6a9a9bef7033aca9dffa99d52be1f51f8d9reed@google.com */ 341db77a6a9a9bef7033aca9dffa99d52be1f51f8d9reed@google.comvoid SkLOGFONTFromTypeface(const SkTypeface* face, LOGFONT* lf) { 342db77a6a9a9bef7033aca9dffa99d52be1f51f8d9reed@google.com if (NULL == face) { 343db77a6a9a9bef7033aca9dffa99d52be1f51f8d9reed@google.com *lf = get_default_font(); 344db77a6a9a9bef7033aca9dffa99d52be1f51f8d9reed@google.com } else { 345a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com *lf = static_cast<const LogFontTypeface*>(face)->fLogFont; 346db77a6a9a9bef7033aca9dffa99d52be1f51f8d9reed@google.com } 347db77a6a9a9bef7033aca9dffa99d52be1f51f8d9reed@google.com} 348db77a6a9a9bef7033aca9dffa99d52be1f51f8d9reed@google.com 34959d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.comstatic void GetLogFontByID(SkFontID fontID, LOGFONT* lf) { 350a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com LogFontTypeface* face = static_cast<LogFontTypeface*>(SkTypefaceCache::FindByID(fontID)); 35159d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com if (face) { 35259d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com *lf = face->fLogFont; 35359d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com } else { 35459d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com sk_bzero(lf, sizeof(LOGFONT)); 35559d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com } 35659d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com} 35759d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com 3586744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org// Construct Glyph to Unicode table. 3596744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org// Unicode code points that require conjugate pairs in utf16 are not 3606744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org// supported. 3616744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org// TODO(arthurhsu): Add support for conjugate pairs. It looks like that may 3626744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org// require parsing the TTF cmap table (platform 4, encoding 12) directly instead 3636744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org// of calling GetFontUnicodeRange(). 3646744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.orgstatic void populate_glyph_to_unicode(HDC fontHdc, const unsigned glyphCount, 3656744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org SkTDArray<SkUnichar>* glyphToUnicode) { 3666744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org DWORD glyphSetBufferSize = GetFontUnicodeRanges(fontHdc, NULL); 3676744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org if (!glyphSetBufferSize) { 3686744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org return; 3696744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org } 3706744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org 3716744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org SkAutoTDeleteArray<BYTE> glyphSetBuffer(new BYTE[glyphSetBufferSize]); 3726744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org GLYPHSET* glyphSet = 3736744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org reinterpret_cast<LPGLYPHSET>(glyphSetBuffer.get()); 3746744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org if (GetFontUnicodeRanges(fontHdc, glyphSet) != glyphSetBufferSize) { 3756744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org return; 3766744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org } 3776744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org 3786744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org glyphToUnicode->setCount(glyphCount); 3796744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org memset(glyphToUnicode->begin(), 0, glyphCount * sizeof(SkUnichar)); 3806744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org for (DWORD i = 0; i < glyphSet->cRanges; ++i) { 3816744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org // There is no guarantee that within a Unicode range, the corresponding 3826744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org // glyph id in a font file are continuous. So, even if we have ranges, 3836744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org // we can't just use the first and last entry of the range to compute 3846744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org // result. We need to enumerate them one by one. 3856744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org int count = glyphSet->ranges[i].cGlyphs; 3866744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org SkAutoTArray<WCHAR> chars(count + 1); 3876744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org chars[count] = 0; // termintate string 3886744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org SkAutoTArray<WORD> glyph(count); 3896744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org for (USHORT j = 0; j < count; ++j) { 3906744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org chars[j] = glyphSet->ranges[i].wcLow + j; 3916744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org } 3926744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org GetGlyphIndicesW(fontHdc, chars.get(), count, glyph.get(), 3936744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org GGI_MARK_NONEXISTING_GLYPHS); 3946744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org // If the glyph ID is valid, and the glyph is not mapped, then we will 3956744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org // fill in the char id into the vector. If the glyph is mapped already, 3966744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org // skip it. 3976744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org // TODO(arthurhsu): better improve this. e.g. Get all used char ids from 3986744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org // font cache, then generate this mapping table from there. It's 3996744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org // unlikely to have collisions since glyph reuse happens mostly for 4006744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org // different Unicode pages. 4016744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org for (USHORT j = 0; j < count; ++j) { 4026744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org if (glyph[j] != 0xffff && glyph[j] < glyphCount && 4036744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org (*glyphToUnicode)[glyph[j]] == 0) { 4046744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org (*glyphToUnicode)[glyph[j]] = chars[j]; 4056744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org } 4066744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org } 4076744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org } 4086744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org} 4096744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org 41099edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com////////////////////////////////////////////////////////////////////////////////////// 41199edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com 41299edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.comstatic int alignTo32(int n) { 41399edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com return (n + 31) & ~31; 41499edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com} 41599edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com 41699edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.comstruct MyBitmapInfo : public BITMAPINFO { 41799edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com RGBQUAD fMoreSpaceForColors[1]; 41899edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com}; 41999edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com 42099edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.comclass HDCOffscreen { 42199edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.compublic: 42299edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com HDCOffscreen() { 42399edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com fFont = 0; 42499edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com fDC = 0; 42599edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com fBM = 0; 42699edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com fBits = NULL; 42799edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com fWidth = fHeight = 0; 42899edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com fIsBW = false; 42999edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com } 43099edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com 43199edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com ~HDCOffscreen() { 43299edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com if (fDC) { 43399edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com DeleteDC(fDC); 43499edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com } 43599edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com if (fBM) { 43699edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com DeleteObject(fBM); 43799edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com } 43899edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com } 43999edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com 44099edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com void init(HFONT font, const XFORM& xform) { 44199edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com fFont = font; 44299edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com fXform = xform; 44399edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com } 44499edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com 44597efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com const void* draw(const SkGlyph&, bool isBW, size_t* srcRBPtr); 44699edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com 44799edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.comprivate: 44899edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com HDC fDC; 44999edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com HBITMAP fBM; 45099edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com HFONT fFont; 45199edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com XFORM fXform; 45299edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com void* fBits; // points into fBM 45399edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com int fWidth; 45499edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com int fHeight; 45599edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com bool fIsBW; 456754e4ebd10d7353ce55be7dfe0a417e502ef4047reed@google.com 457754e4ebd10d7353ce55be7dfe0a417e502ef4047reed@google.com enum { 458754e4ebd10d7353ce55be7dfe0a417e502ef4047reed@google.com // will always trigger us to reset the color, since we 4596f5df48c1d07295b75c1955a69142fb5e66b8647reed@google.com // should only store 0 or 0x00FFFFFF or gray (0x007F7F7F) 460754e4ebd10d7353ce55be7dfe0a417e502ef4047reed@google.com kInvalid_Color = 12345 461754e4ebd10d7353ce55be7dfe0a417e502ef4047reed@google.com }; 46299edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com}; 46399edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com 464754e4ebd10d7353ce55be7dfe0a417e502ef4047reed@google.comconst void* HDCOffscreen::draw(const SkGlyph& glyph, bool isBW, 46597efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com size_t* srcRBPtr) { 46684e22d847fc84727bc220947162363ee1fe068fcreed@google.com // Can we share the scalercontext's fDDC, so we don't need to create 46784e22d847fc84727bc220947162363ee1fe068fcreed@google.com // a separate fDC here? 46899edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com if (0 == fDC) { 46999edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com fDC = CreateCompatibleDC(0); 47099edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com if (0 == fDC) { 47199edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com return NULL; 47299edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com } 47399edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com SetGraphicsMode(fDC, GM_ADVANCED); 47499edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com SetBkMode(fDC, TRANSPARENT); 47599edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com SetTextAlign(fDC, TA_LEFT | TA_BASELINE); 47699edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com SelectObject(fDC, fFont); 47797efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com 47897efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com COLORREF color = 0x00FFFFFF; 479b58a639b2fbe919489654bb506efdb024a308a8ebsalomon@google.com SkDEBUGCODE(COLORREF prev =) SetTextColor(fDC, color); 48097efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com SkASSERT(prev != CLR_INVALID); 48199edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com } 48299edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com 48399edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com if (fBM && (fIsBW != isBW || fWidth < glyph.fWidth || fHeight < glyph.fHeight)) { 48499edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com DeleteObject(fBM); 48599edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com fBM = 0; 48699edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com } 487754e4ebd10d7353ce55be7dfe0a417e502ef4047reed@google.com fIsBW = isBW; 48899edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com 48999edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com fWidth = SkMax32(fWidth, glyph.fWidth); 49099edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com fHeight = SkMax32(fHeight, glyph.fHeight); 49199edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com 49299edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com int biWidth = isBW ? alignTo32(fWidth) : fWidth; 49399edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com 49499edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com if (0 == fBM) { 49599edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com MyBitmapInfo info; 49699edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com sk_bzero(&info, sizeof(info)); 49799edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com if (isBW) { 49899edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com RGBQUAD blackQuad = { 0, 0, 0, 0 }; 49999edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com RGBQUAD whiteQuad = { 0xFF, 0xFF, 0xFF, 0 }; 50099edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com info.bmiColors[0] = blackQuad; 50199edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com info.bmiColors[1] = whiteQuad; 50299edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com } 50399edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com info.bmiHeader.biSize = sizeof(info.bmiHeader); 50499edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com info.bmiHeader.biWidth = biWidth; 50599edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com info.bmiHeader.biHeight = fHeight; 50699edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com info.bmiHeader.biPlanes = 1; 50799edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com info.bmiHeader.biBitCount = isBW ? 1 : 32; 50899edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com info.bmiHeader.biCompression = BI_RGB; 50999edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com if (isBW) { 51099edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com info.bmiHeader.biClrUsed = 2; 51199edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com } 51299edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com fBM = CreateDIBSection(fDC, &info, DIB_RGB_COLORS, &fBits, 0, 0); 51399edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com if (0 == fBM) { 51499edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com return NULL; 51599edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com } 51699edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com SelectObject(fDC, fBM); 51799edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com } 51899edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com 51999edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com // erase 52099edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com size_t srcRB = isBW ? (biWidth >> 3) : (fWidth << 2); 52199edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com size_t size = fHeight * srcRB; 52297efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com memset(fBits, 0, size); 52399edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com 52499edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com XFORM xform = fXform; 52599edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com xform.eDx = (float)-glyph.fLeft; 52699edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com xform.eDy = (float)-glyph.fTop; 52799edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com SetWorldTransform(fDC, &xform); 52899edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com 52999edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com uint16_t glyphID = glyph.getGlyphID(); 53039698b1bd71fd54c7c44ae8d7224afdaf93c0ddabungeman@google.com BOOL ret = ExtTextOutW(fDC, 0, 0, ETO_GLYPH_INDEX, NULL, reinterpret_cast<LPCWSTR>(&glyphID), 1, NULL); 53199edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com GdiFlush(); 53239698b1bd71fd54c7c44ae8d7224afdaf93c0ddabungeman@google.com if (0 == ret) { 53339698b1bd71fd54c7c44ae8d7224afdaf93c0ddabungeman@google.com return NULL; 53439698b1bd71fd54c7c44ae8d7224afdaf93c0ddabungeman@google.com } 53599edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com *srcRBPtr = srcRB; 53699edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com // offset to the start of the image 53799edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com return (const char*)fBits + (fHeight - glyph.fHeight) * srcRB; 53899edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com} 53999edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com 540b8a5c618d2e18d71707ae4dcafbe5153d7ff427freed@google.com////////////////////////////////////////////////////////////////////////////// 54159d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com 542ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.comclass SkScalerContext_Windows : public SkScalerContext { 543ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.compublic: 5440da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com SkScalerContext_Windows(SkTypeface*, const SkDescriptor* desc); 545ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com virtual ~SkScalerContext_Windows(); 546ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 54784e22d847fc84727bc220947162363ee1fe068fcreed@google.com // Returns true if the constructor was able to complete all of its 54884e22d847fc84727bc220947162363ee1fe068fcreed@google.com // initializations (which may include calling GDI). 54984e22d847fc84727bc220947162363ee1fe068fcreed@google.com bool isValid() const; 55084e22d847fc84727bc220947162363ee1fe068fcreed@google.com 551ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.comprotected: 55297efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com virtual unsigned generateGlyphCount() SK_OVERRIDE; 55397efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com virtual uint16_t generateCharToGlyph(SkUnichar uni) SK_OVERRIDE; 55497efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com virtual void generateAdvance(SkGlyph* glyph) SK_OVERRIDE; 55597efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com virtual void generateMetrics(SkGlyph* glyph) SK_OVERRIDE; 556a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com virtual void generateImage(const SkGlyph& glyph) SK_OVERRIDE; 55797efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com virtual void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE; 558a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com virtual void generateFontMetrics(SkPaint::FontMetrics* mX, 559a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com SkPaint::FontMetrics* mY) SK_OVERRIDE; 56099edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com 561ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.comprivate: 56299edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com HDCOffscreen fOffscreen; 5635aa937b300475c956bfad0c34a6daa71d166f6factguil@chromium.org SkScalar fScale; // to get from canonical size to real size 564ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com MAT2 fMat22; 565ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com HDC fDDC; 566ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com HFONT fSavefont; 567ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com HFONT fFont; 56884e22d847fc84727bc220947162363ee1fe068fcreed@google.com HFONT fHiResFont; 569ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com SCRIPT_CACHE fSC; 570ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com int fGlyphCount; 5711dd17a133f4fa5c5a0c752e6b9a6f7af6f329fb8reed@google.com 5721dd17a133f4fa5c5a0c752e6b9a6f7af6f329fb8reed@google.com MAT2 fMat22Identity; 5731dd17a133f4fa5c5a0c752e6b9a6f7af6f329fb8reed@google.com SkMatrix fHiResMatrix; 574a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com enum Type { 575a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com kTrueType_Type, kBitmap_Type, 576a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com } fType; 577a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com TEXTMETRIC fTM; 578ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com}; 579ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 580ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.comstatic float mul2float(SkScalar a, SkScalar b) { 581ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com return SkScalarToFloat(SkScalarMul(a, b)); 582ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com} 583ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 584ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.comstatic FIXED float2FIXED(float x) { 585ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com return SkFixedToFIXED(SkFloatToFixed(x)); 586ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com} 587ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 5881dd17a133f4fa5c5a0c752e6b9a6f7af6f329fb8reed@google.com#define HIRES_TEXTSIZE 2048 5891dd17a133f4fa5c5a0c752e6b9a6f7af6f329fb8reed@google.com#define HIRES_SHIFT 11 5901dd17a133f4fa5c5a0c752e6b9a6f7af6f329fb8reed@google.comstatic inline SkFixed HiResToFixed(int value) { 5911dd17a133f4fa5c5a0c752e6b9a6f7af6f329fb8reed@google.com return value << (16 - HIRES_SHIFT); 5921dd17a133f4fa5c5a0c752e6b9a6f7af6f329fb8reed@google.com} 5931dd17a133f4fa5c5a0c752e6b9a6f7af6f329fb8reed@google.com 5941dd17a133f4fa5c5a0c752e6b9a6f7af6f329fb8reed@google.comstatic bool needHiResMetrics(const SkScalar mat[2][2]) { 5951dd17a133f4fa5c5a0c752e6b9a6f7af6f329fb8reed@google.com return mat[1][0] || mat[0][1]; 5961dd17a133f4fa5c5a0c752e6b9a6f7af6f329fb8reed@google.com} 5971dd17a133f4fa5c5a0c752e6b9a6f7af6f329fb8reed@google.com 59882a34d83f646d069ef2d1d7b649d0a0b1829d62freed@google.comstatic BYTE compute_quality(const SkScalerContext::Rec& rec) { 59982a34d83f646d069ef2d1d7b649d0a0b1829d62freed@google.com switch (rec.fMaskFormat) { 60082a34d83f646d069ef2d1d7b649d0a0b1829d62freed@google.com case SkMask::kBW_Format: 60182a34d83f646d069ef2d1d7b649d0a0b1829d62freed@google.com return NONANTIALIASED_QUALITY; 60282a34d83f646d069ef2d1d7b649d0a0b1829d62freed@google.com case SkMask::kLCD16_Format: 60382a34d83f646d069ef2d1d7b649d0a0b1829d62freed@google.com case SkMask::kLCD32_Format: 60482a34d83f646d069ef2d1d7b649d0a0b1829d62freed@google.com return CLEARTYPE_QUALITY; 60582a34d83f646d069ef2d1d7b649d0a0b1829d62freed@google.com default: 6068351aabbfe82a76a698fa2bde00d33c1174518cdreed@google.com if (rec.fFlags & SkScalerContext::kGenA8FromLCD_Flag) { 6078351aabbfe82a76a698fa2bde00d33c1174518cdreed@google.com return CLEARTYPE_QUALITY; 6088351aabbfe82a76a698fa2bde00d33c1174518cdreed@google.com } else { 6098351aabbfe82a76a698fa2bde00d33c1174518cdreed@google.com return ANTIALIASED_QUALITY; 6108351aabbfe82a76a698fa2bde00d33c1174518cdreed@google.com } 61182a34d83f646d069ef2d1d7b649d0a0b1829d62freed@google.com } 61282a34d83f646d069ef2d1d7b649d0a0b1829d62freed@google.com} 61382a34d83f646d069ef2d1d7b649d0a0b1829d62freed@google.com 614055180cb9c47c87e5ee8c9fa6d3f6a6079ad6f35reed@google.comSkScalerContext_Windows::SkScalerContext_Windows(SkTypeface* rawTypeface, 6150da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com const SkDescriptor* desc) 616055180cb9c47c87e5ee8c9fa6d3f6a6079ad6f35reed@google.com : SkScalerContext(rawTypeface, desc) 617055180cb9c47c87e5ee8c9fa6d3f6a6079ad6f35reed@google.com , fDDC(0) 618055180cb9c47c87e5ee8c9fa6d3f6a6079ad6f35reed@google.com , fSavefont(0) 61984e22d847fc84727bc220947162363ee1fe068fcreed@google.com , fFont(0) 62084e22d847fc84727bc220947162363ee1fe068fcreed@google.com , fHiResFont(0) 621055180cb9c47c87e5ee8c9fa6d3f6a6079ad6f35reed@google.com , fSC(0) 62205a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com , fGlyphCount(-1) 62305a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com{ 624055180cb9c47c87e5ee8c9fa6d3f6a6079ad6f35reed@google.com LogFontTypeface* typeface = reinterpret_cast<LogFontTypeface*>(rawTypeface); 625055180cb9c47c87e5ee8c9fa6d3f6a6079ad6f35reed@google.com 626ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com fDDC = ::CreateCompatibleDC(NULL); 62784e22d847fc84727bc220947162363ee1fe068fcreed@google.com if (!fDDC) { 62884e22d847fc84727bc220947162363ee1fe068fcreed@google.com return; 62984e22d847fc84727bc220947162363ee1fe068fcreed@google.com } 63084e22d847fc84727bc220947162363ee1fe068fcreed@google.com 6311dd17a133f4fa5c5a0c752e6b9a6f7af6f329fb8reed@google.com SetGraphicsMode(fDDC, GM_ADVANCED); 632ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com SetBkMode(fDDC, TRANSPARENT); 633ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 634ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com // Scaling by the DPI is inconsistent with how Skia draws elsewhere 635ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com //SkScalar height = -(fRec.fTextSize * GetDeviceCaps(ddc, LOGPIXELSY) / 72); 636055180cb9c47c87e5ee8c9fa6d3f6a6079ad6f35reed@google.com LOGFONT lf = typeface->fLogFont; 637ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com lf.lfHeight = -gCanonicalTextSize; 63882a34d83f646d069ef2d1d7b649d0a0b1829d62freed@google.com lf.lfQuality = compute_quality(fRec); 639ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com fFont = CreateFontIndirect(&lf); 64084e22d847fc84727bc220947162363ee1fe068fcreed@google.com if (!fFont) { 64184e22d847fc84727bc220947162363ee1fe068fcreed@google.com return; 64284e22d847fc84727bc220947162363ee1fe068fcreed@google.com } 6431dd17a133f4fa5c5a0c752e6b9a6f7af6f329fb8reed@google.com 6441dd17a133f4fa5c5a0c752e6b9a6f7af6f329fb8reed@google.com // if we're rotated, or want fractional widths, create a hires font 645c84547a8d3cb04f0547db282b34e26abfbe64ec3bungeman@google.com if (needHiResMetrics(fRec.fPost2x2)) { 6461dd17a133f4fa5c5a0c752e6b9a6f7af6f329fb8reed@google.com lf.lfHeight = -HIRES_TEXTSIZE; 6471dd17a133f4fa5c5a0c752e6b9a6f7af6f329fb8reed@google.com fHiResFont = CreateFontIndirect(&lf); 64884e22d847fc84727bc220947162363ee1fe068fcreed@google.com if (!fHiResFont) { 64984e22d847fc84727bc220947162363ee1fe068fcreed@google.com return; 65084e22d847fc84727bc220947162363ee1fe068fcreed@google.com } 6511dd17a133f4fa5c5a0c752e6b9a6f7af6f329fb8reed@google.com 6521dd17a133f4fa5c5a0c752e6b9a6f7af6f329fb8reed@google.com fMat22Identity.eM11 = fMat22Identity.eM22 = SkFixedToFIXED(SK_Fixed1); 6531dd17a133f4fa5c5a0c752e6b9a6f7af6f329fb8reed@google.com fMat22Identity.eM12 = fMat22Identity.eM21 = SkFixedToFIXED(0); 6541dd17a133f4fa5c5a0c752e6b9a6f7af6f329fb8reed@google.com 6551dd17a133f4fa5c5a0c752e6b9a6f7af6f329fb8reed@google.com // construct a matrix to go from HIRES logical units to our device units 6561dd17a133f4fa5c5a0c752e6b9a6f7af6f329fb8reed@google.com fRec.getSingleMatrix(&fHiResMatrix); 6571dd17a133f4fa5c5a0c752e6b9a6f7af6f329fb8reed@google.com SkScalar scale = SkScalarInvert(SkIntToScalar(HIRES_TEXTSIZE)); 6581dd17a133f4fa5c5a0c752e6b9a6f7af6f329fb8reed@google.com fHiResMatrix.preScale(scale, scale); 6591dd17a133f4fa5c5a0c752e6b9a6f7af6f329fb8reed@google.com } 660ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com fSavefont = (HFONT)SelectObject(fDDC, fFont); 661a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com 662a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com if (0 == GetTextMetrics(fDDC, &fTM)) { 663055180cb9c47c87e5ee8c9fa6d3f6a6079ad6f35reed@google.com call_ensure_accessible(lf); 664a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com if (0 == GetTextMetrics(fDDC, &fTM)) { 665a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com fTM.tmPitchAndFamily = TMPF_TRUETYPE; 666a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com } 667a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com } 668a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com // Used a logfont on a memory context, should never get a device font. 66990b7e386cab251db78152f18adfd54e019b8dc10bungeman@google.com // Therefore all TMPF_DEVICE will be PostScript fonts. 67090b7e386cab251db78152f18adfd54e019b8dc10bungeman@google.com 67190b7e386cab251db78152f18adfd54e019b8dc10bungeman@google.com // If TMPF_VECTOR is set, one of TMPF_TRUETYPE or TMPF_DEVICE must be set, 67290b7e386cab251db78152f18adfd54e019b8dc10bungeman@google.com // otherwise we have a vector FON, which we don't support. 67390b7e386cab251db78152f18adfd54e019b8dc10bungeman@google.com // This was determined by testing with Type1 PFM/PFB and OpenTypeCFF OTF, 67490b7e386cab251db78152f18adfd54e019b8dc10bungeman@google.com // as well as looking at Wine bugs and sources. 67590b7e386cab251db78152f18adfd54e019b8dc10bungeman@google.com SkASSERT(!(fTM.tmPitchAndFamily & TMPF_VECTOR) || 67690b7e386cab251db78152f18adfd54e019b8dc10bungeman@google.com (fTM.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_DEVICE))); 67790b7e386cab251db78152f18adfd54e019b8dc10bungeman@google.com 678d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com XFORM xform; 67990b7e386cab251db78152f18adfd54e019b8dc10bungeman@google.com if (fTM.tmPitchAndFamily & TMPF_VECTOR) { 680a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com // Truetype or PostScript. 681a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com // Stroked FON also gets here (TMPF_VECTOR), but we don't handle it. 682a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com fType = SkScalerContext_Windows::kTrueType_Type; 683a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com fScale = fRec.fTextSize / gCanonicalTextSize; 684a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com 685d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com // fPost2x2 is column-major, left handed (y down). 686d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com // XFORM 2x2 is row-major, left handed (y down). 687d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com xform.eM11 = mul2float(fScale, fRec.fPost2x2[0][0]); 688d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com xform.eM12 = mul2float(fScale, fRec.fPost2x2[1][0]); 689d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com xform.eM21 = mul2float(fScale, fRec.fPost2x2[0][1]); 690d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com xform.eM22 = mul2float(fScale, fRec.fPost2x2[1][1]); 691d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com xform.eDx = 0; 692d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com xform.eDy = 0; 693d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com 694d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com // MAT2 is row major, right handed (y up). 695d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com fMat22.eM11 = float2FIXED(xform.eM11); 696d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com fMat22.eM12 = float2FIXED(-xform.eM12); 697d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com fMat22.eM21 = float2FIXED(-xform.eM21); 698d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com fMat22.eM22 = float2FIXED(xform.eM22); 699a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com 700a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com if (needToRenderWithSkia(fRec)) { 701a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com this->forceGenerateImageFromPath(); 702a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com } 703a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com 704a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com } else { 705a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com // Assume bitmap 706a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com fType = SkScalerContext_Windows::kBitmap_Type; 707a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com fScale = SK_Scalar1; 708a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com 709d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com xform.eM11 = 1.0f; 710d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com xform.eM12 = 0.0f; 711d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com xform.eM21 = 0.0f; 712d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com xform.eM22 = 1.0f; 713d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com xform.eDx = 0.0f; 714d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com xform.eDy = 0.0f; 715a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com 716d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com // fPost2x2 is column-major, left handed (y down). 717d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com // MAT2 is row major, right handed (y up). 718a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com fMat22.eM11 = SkScalarToFIXED(fRec.fPost2x2[0][0]); 719d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com fMat22.eM12 = SkScalarToFIXED(-fRec.fPost2x2[1][0]); 720a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com fMat22.eM21 = SkScalarToFIXED(-fRec.fPost2x2[0][1]); 721d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com fMat22.eM22 = SkScalarToFIXED(fRec.fPost2x2[1][1]); 722a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com 723a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com lf.lfHeight = -SkScalarCeilToInt(fRec.fTextSize); 724a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com HFONT bitmapFont = CreateFontIndirect(&lf); 725a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com SelectObject(fDDC, bitmapFont); 726a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com ::DeleteObject(fFont); 727a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com fFont = bitmapFont; 728a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com 729a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com if (0 == GetTextMetrics(fDDC, &fTM)) { 730055180cb9c47c87e5ee8c9fa6d3f6a6079ad6f35reed@google.com call_ensure_accessible(lf); 731a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com //if the following fails, we'll just draw at gCanonicalTextSize. 732a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com GetTextMetrics(fDDC, &fTM); 733a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com } 734a767fa06ca28be9df1ff6e08a299e0bec839a2dcreed@google.com } 73599edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com 736d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com fOffscreen.init(fFont, xform); 737ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com} 738ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 739ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.comSkScalerContext_Windows::~SkScalerContext_Windows() { 740ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com if (fDDC) { 741ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com ::SelectObject(fDDC, fSavefont); 742ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com ::DeleteDC(fDDC); 743ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } 744ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com if (fFont) { 745ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com ::DeleteObject(fFont); 746ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } 7471dd17a133f4fa5c5a0c752e6b9a6f7af6f329fb8reed@google.com if (fHiResFont) { 7481dd17a133f4fa5c5a0c752e6b9a6f7af6f329fb8reed@google.com ::DeleteObject(fHiResFont); 7491dd17a133f4fa5c5a0c752e6b9a6f7af6f329fb8reed@google.com } 750ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com if (fSC) { 751ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com ::ScriptFreeCache(&fSC); 752ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } 753ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com} 754ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 75584e22d847fc84727bc220947162363ee1fe068fcreed@google.combool SkScalerContext_Windows::isValid() const { 75684e22d847fc84727bc220947162363ee1fe068fcreed@google.com return fDDC && fFont; 75784e22d847fc84727bc220947162363ee1fe068fcreed@google.com} 75884e22d847fc84727bc220947162363ee1fe068fcreed@google.com 759ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.comunsigned SkScalerContext_Windows::generateGlyphCount() { 760ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com if (fGlyphCount < 0) { 7617bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com fGlyphCount = calculateGlyphCount( 7627bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com fDDC, static_cast<const LogFontTypeface*>(this->getTypeface())->fLogFont); 763ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } 764ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com return fGlyphCount; 765ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com} 766ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 767ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.comuint16_t SkScalerContext_Windows::generateCharToGlyph(SkUnichar uni) { 768ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com uint16_t index = 0; 769ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com WCHAR c[2]; 770ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com // TODO(ctguil): Support characters that generate more than one glyph. 771ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com if (SkUTF16_FromUnichar(uni, (uint16_t*)c) == 1) { 772ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com // Type1 fonts fail with uniscribe API. Use GetGlyphIndices for plane 0. 773ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com SkAssertResult(GetGlyphIndicesW(fDDC, c, 1, &index, 0)); 774ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } else { 775ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com // Use uniscribe to detemine glyph index for non-BMP characters. 776ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com // Need to add extra item to SCRIPT_ITEM to work around a bug in older 777ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com // windows versions. https://bugzilla.mozilla.org/show_bug.cgi?id=366643 778ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com SCRIPT_ITEM si[2 + 1]; 779ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com int items; 780ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com SkAssertResult( 781ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com SUCCEEDED(ScriptItemize(c, 2, 2, NULL, NULL, si, &items))); 782ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 783ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com WORD log[2]; 784ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com SCRIPT_VISATTR vsa; 785ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com int glyphs; 786ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com SkAssertResult(SUCCEEDED(ScriptShape( 787ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com fDDC, &fSC, c, 2, 1, &si[0].a, &index, log, &vsa, &glyphs))); 788ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } 789ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com return index; 790ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com} 791ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 792ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.comvoid SkScalerContext_Windows::generateAdvance(SkGlyph* glyph) { 793ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com this->generateMetrics(glyph); 794ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com} 795ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 796ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.comvoid SkScalerContext_Windows::generateMetrics(SkGlyph* glyph) { 797ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com SkASSERT(fDDC); 798ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 799a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com if (fType == SkScalerContext_Windows::kBitmap_Type) { 800a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com SIZE size; 801a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com WORD glyphs = glyph->getGlyphID(0); 802a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com if (0 == GetTextExtentPointI(fDDC, &glyphs, 1, &size)) { 803a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com glyph->fWidth = SkToS16(fTM.tmMaxCharWidth); 804a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com } else { 805a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com glyph->fWidth = SkToS16(size.cx); 806a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com } 807a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com glyph->fHeight = SkToS16(size.cy); 808a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com 809a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com glyph->fTop = SkToS16(-fTM.tmAscent); 810a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com glyph->fLeft = SkToS16(0); 811a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com glyph->fAdvanceX = SkIntToFixed(glyph->fWidth); 812a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com glyph->fAdvanceY = 0; 813a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com 814d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com // Apply matrix to advance. 815a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com glyph->fAdvanceY = SkFixedMul(SkFIXEDToFixed(fMat22.eM21), glyph->fAdvanceX); 816a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com glyph->fAdvanceX = SkFixedMul(SkFIXEDToFixed(fMat22.eM11), glyph->fAdvanceX); 817a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com 818a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com return; 819a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com } 820a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com 821d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com UINT glyphId = glyph->getGlyphID(0); 822d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com 823ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com GLYPHMETRICS gm; 8241dd17a133f4fa5c5a0c752e6b9a6f7af6f329fb8reed@google.com sk_bzero(&gm, sizeof(gm)); 825ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 826d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com DWORD status = GetGlyphOutlineW(fDDC, glyphId, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, NULL, &fMat22); 827d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com if (GDI_ERROR == status) { 828055180cb9c47c87e5ee8c9fa6d3f6a6079ad6f35reed@google.com LogFontTypeface::EnsureAccessible(this->getTypeface()); 829d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com status = GetGlyphOutlineW(fDDC, glyphId, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, NULL, &fMat22); 830d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com if (GDI_ERROR == status) { 831d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com glyph->zeroMetrics(); 832d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com return; 833d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com } 83439698b1bd71fd54c7c44ae8d7224afdaf93c0ddabungeman@google.com } 835ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 836d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com bool empty = false; 837d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com // The black box is either the embedded bitmap size or the outline extent. 838d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com // It is 1x1 if nothing is to be drawn, but will also be 1x1 if something very small 839d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com // is to be drawn, like a '.'. We need to outset '.' but do not wish to outset ' '. 840d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com if (1 == gm.gmBlackBoxX && 1 == gm.gmBlackBoxY) { 841d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com // If GetGlyphOutline with GGO_NATIVE returns 0, we know there was no outline. 842d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com DWORD bufferSize = GetGlyphOutlineW(fDDC, glyphId, GGO_NATIVE | GGO_GLYPH_INDEX, &gm, 0, NULL, &fMat22); 843d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com empty = (0 == bufferSize); 844d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com } 8451dd17a133f4fa5c5a0c752e6b9a6f7af6f329fb8reed@google.com 846d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com glyph->fTop = SkToS16(-gm.gmptGlyphOrigin.y); 847d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com glyph->fLeft = SkToS16(gm.gmptGlyphOrigin.x); 848d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com if (empty) { 849d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com glyph->fWidth = 0; 850d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com glyph->fHeight = 0; 851ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } else { 852d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com // Outset, since the image may bleed out of the black box. 853d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com // For embedded bitmaps the black box should be exact. 854d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com // For outlines we need to outset by 1 in all directions for bleed. 855d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com // For ClearType we need to outset by 2 for bleed. 856d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com glyph->fWidth = gm.gmBlackBoxX + 4; 857d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com glyph->fHeight = gm.gmBlackBoxY + 4; 858d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com glyph->fTop -= 2; 859d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com glyph->fLeft -= 2; 860d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com } 861d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com glyph->fAdvanceX = SkIntToFixed(gm.gmCellIncX); 862d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com glyph->fAdvanceY = SkIntToFixed(gm.gmCellIncY); 863d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com glyph->fRsbDelta = 0; 864d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com glyph->fLsbDelta = 0; 865d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com 866d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com if (fHiResFont) { 867d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com SelectObject(fDDC, fHiResFont); 868d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com sk_bzero(&gm, sizeof(gm)); 869d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com status = GetGlyphOutlineW(fDDC, glyphId, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, NULL, &fMat22Identity); 870d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com if (GDI_ERROR != status) { 871d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com SkPoint advance; 872d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com fHiResMatrix.mapXY(SkIntToScalar(gm.gmCellIncX), SkIntToScalar(gm.gmCellIncY), &advance); 873d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com glyph->fAdvanceX = SkScalarToFixed(advance.fX); 874d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com glyph->fAdvanceY = SkScalarToFixed(advance.fY); 875d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com } 876d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com SelectObject(fDDC, fFont); 877ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } 878ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com} 879ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 880ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.comvoid SkScalerContext_Windows::generateFontMetrics(SkPaint::FontMetrics* mx, SkPaint::FontMetrics* my) { 88160af92cb6de814b14ee5d40b71bfbd79227597ecreed@google.com if (!(mx || my)) { 882ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com return; 88360af92cb6de814b14ee5d40b71bfbd79227597ecreed@google.com } 88460af92cb6de814b14ee5d40b71bfbd79227597ecreed@google.com 88560af92cb6de814b14ee5d40b71bfbd79227597ecreed@google.com if (mx) { 88660af92cb6de814b14ee5d40b71bfbd79227597ecreed@google.com sk_bzero(mx, sizeof(*mx)); 88760af92cb6de814b14ee5d40b71bfbd79227597ecreed@google.com } 88860af92cb6de814b14ee5d40b71bfbd79227597ecreed@google.com if (my) { 88960af92cb6de814b14ee5d40b71bfbd79227597ecreed@google.com sk_bzero(my, sizeof(*my)); 89060af92cb6de814b14ee5d40b71bfbd79227597ecreed@google.com } 891ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 892ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com SkASSERT(fDDC); 893ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 894e9d831957602e3fa46fc4b609ae6d2da46654915bungeman@google.com#ifndef SK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS 895a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com if (fType == SkScalerContext_Windows::kBitmap_Type) { 896e9d831957602e3fa46fc4b609ae6d2da46654915bungeman@google.com#endif 897a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com if (mx) { 898a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com mx->fTop = SkIntToScalar(-fTM.tmAscent); 899a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com mx->fAscent = SkIntToScalar(-fTM.tmAscent); 900a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com mx->fDescent = -SkIntToScalar(fTM.tmDescent); 901a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com mx->fBottom = SkIntToScalar(fTM.tmDescent); 90260af92cb6de814b14ee5d40b71bfbd79227597ecreed@google.com mx->fLeading = SkIntToScalar(fTM.tmExternalLeading); 903a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com } 904a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com 905a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com if (my) { 906a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com my->fTop = SkIntToScalar(-fTM.tmAscent); 907a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com my->fAscent = SkIntToScalar(-fTM.tmAscent); 908a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com my->fDescent = SkIntToScalar(-fTM.tmDescent); 909a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com my->fBottom = SkIntToScalar(fTM.tmDescent); 91060af92cb6de814b14ee5d40b71bfbd79227597ecreed@google.com my->fLeading = SkIntToScalar(fTM.tmExternalLeading); 91160af92cb6de814b14ee5d40b71bfbd79227597ecreed@google.com my->fAvgCharWidth = SkIntToScalar(fTM.tmAveCharWidth); 912e9d831957602e3fa46fc4b609ae6d2da46654915bungeman@google.com my->fMaxCharWidth = SkIntToScalar(fTM.tmMaxCharWidth); 913e9d831957602e3fa46fc4b609ae6d2da46654915bungeman@google.com my->fXMin = 0; 914e9d831957602e3fa46fc4b609ae6d2da46654915bungeman@google.com my->fXMax = my->fMaxCharWidth; 915e9d831957602e3fa46fc4b609ae6d2da46654915bungeman@google.com //my->fXHeight = 0; 916a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com } 917e9d831957602e3fa46fc4b609ae6d2da46654915bungeman@google.com#ifndef SK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS 918a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com return; 919a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com } 920e9d831957602e3fa46fc4b609ae6d2da46654915bungeman@google.com#endif 921a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com 922ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com OUTLINETEXTMETRIC otm; 923ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 924ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com uint32_t ret = GetOutlineTextMetrics(fDDC, sizeof(otm), &otm); 92539698b1bd71fd54c7c44ae8d7224afdaf93c0ddabungeman@google.com if (GDI_ERROR == ret) { 926055180cb9c47c87e5ee8c9fa6d3f6a6079ad6f35reed@google.com LogFontTypeface::EnsureAccessible(this->getTypeface()); 92739698b1bd71fd54c7c44ae8d7224afdaf93c0ddabungeman@google.com ret = GetOutlineTextMetrics(fDDC, sizeof(otm), &otm); 92839698b1bd71fd54c7c44ae8d7224afdaf93c0ddabungeman@google.com } 929ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com if (sizeof(otm) != ret) { 930a0319f6d071bb8298e56ace043ea6c623fb358f7bungeman@google.com return; 931ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } 932ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 933ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com if (mx) { 93460af92cb6de814b14ee5d40b71bfbd79227597ecreed@google.com mx->fTop = -fScale * otm.otmrcFontBox.left; 9355aa937b300475c956bfad0c34a6daa71d166f6factguil@chromium.org mx->fAscent = -fScale * otm.otmAscent; 9365aa937b300475c956bfad0c34a6daa71d166f6factguil@chromium.org mx->fDescent = -fScale * otm.otmDescent; 93760af92cb6de814b14ee5d40b71bfbd79227597ecreed@google.com mx->fBottom = fScale * otm.otmrcFontBox.right; 93860af92cb6de814b14ee5d40b71bfbd79227597ecreed@google.com mx->fLeading = fScale * otm.otmLineGap; 939ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } 940ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 941ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com if (my) { 942e9d831957602e3fa46fc4b609ae6d2da46654915bungeman@google.com#ifndef SK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS 94360af92cb6de814b14ee5d40b71bfbd79227597ecreed@google.com my->fTop = -fScale * otm.otmrcFontBox.top; 9445aa937b300475c956bfad0c34a6daa71d166f6factguil@chromium.org my->fAscent = -fScale * otm.otmAscent; 9455aa937b300475c956bfad0c34a6daa71d166f6factguil@chromium.org my->fDescent = -fScale * otm.otmDescent; 94694b366a3e8ed7f03b4417f45999572399e6e591creed@google.com my->fBottom = -fScale * otm.otmrcFontBox.bottom; 94760af92cb6de814b14ee5d40b71bfbd79227597ecreed@google.com my->fLeading = fScale * otm.otmLineGap; 94860af92cb6de814b14ee5d40b71bfbd79227597ecreed@google.com my->fAvgCharWidth = fScale * otm.otmTextMetrics.tmAveCharWidth; 949e9d831957602e3fa46fc4b609ae6d2da46654915bungeman@google.com my->fMaxCharWidth = fScale * otm.otmTextMetrics.tmMaxCharWidth; 950e9d831957602e3fa46fc4b609ae6d2da46654915bungeman@google.com my->fXMin = fScale * otm.otmrcFontBox.left; 951e9d831957602e3fa46fc4b609ae6d2da46654915bungeman@google.com my->fXMax = fScale * otm.otmrcFontBox.right; 952e9d831957602e3fa46fc4b609ae6d2da46654915bungeman@google.com#endif 95360af92cb6de814b14ee5d40b71bfbd79227597ecreed@google.com my->fXHeight = fScale * otm.otmsXHeight; 954ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } 955ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com} 956ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 9577430a3376c0f4e0c2809fedecd12765034f9e3a8reed@google.com//////////////////////////////////////////////////////////////////////////////////////// 9587430a3376c0f4e0c2809fedecd12765034f9e3a8reed@google.com 9597430a3376c0f4e0c2809fedecd12765034f9e3a8reed@google.comstatic void build_power_table(uint8_t table[], float ee) { 9607430a3376c0f4e0c2809fedecd12765034f9e3a8reed@google.com for (int i = 0; i < 256; i++) { 9617430a3376c0f4e0c2809fedecd12765034f9e3a8reed@google.com float x = i / 255.f; 96297efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com x = sk_float_pow(x, ee); 9637430a3376c0f4e0c2809fedecd12765034f9e3a8reed@google.com int xx = SkScalarRound(SkFloatToScalar(x * 255)); 9647430a3376c0f4e0c2809fedecd12765034f9e3a8reed@google.com table[i] = SkToU8(xx); 9657430a3376c0f4e0c2809fedecd12765034f9e3a8reed@google.com } 9667430a3376c0f4e0c2809fedecd12765034f9e3a8reed@google.com} 9677430a3376c0f4e0c2809fedecd12765034f9e3a8reed@google.com 96897efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com/** 96997efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com * This will invert the gamma applied by GDI (gray-scale antialiased), so we 97097efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com * can get linear values. 97197efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com * 97297efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com * GDI grayscale appears to use a hard-coded gamma of 2.3. 97397efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com * 97497efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com * GDI grayscale appears to draw using the black and white rasterizer at four 97597efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com * times the size and then downsamples to compute the coverage mask. As a 97697efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com * result there are only seventeen total grays. This lack of fidelity means 97797efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com * that shifting into other color spaces is imprecise. 97897efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com */ 97997efada074e4806479f1350ab1508939c2fdcb53bungeman@google.comstatic const uint8_t* getInverseGammaTableGDI() { 98005a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com // Since build_power_table is idempotent, many threads can build gTableGdi 98105a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com // simultaneously. 98205a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com 98305a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com // Microsoft Specific: 98405a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com // Making gInited volatile provides read-aquire and write-release in vc++. 98505a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com // In VS2012, see compiler option /volatile:(ms|iso). 98605a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com // Replace with C++11 atomics when possible. 98705a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com static volatile bool gInited; 98897efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com static uint8_t gTableGdi[256]; 98905a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com if (gInited) { 99005a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com // Need a L/L (read) barrier (full acquire not needed). If gInited is observed 99105a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com // true then gTableGdi is observable, but it must be requested. 99205a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com } else { 99397efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com build_power_table(gTableGdi, 2.3f); 99405a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com // Need a S/S (write) barrier (full release not needed) here so that this 99505a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com // write to gInited becomes observable after gTableGdi. 99697efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com gInited = true; 99797efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com } 99897efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com return gTableGdi; 99997efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com} 100097efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com 100197efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com/** 100297efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com * This will invert the gamma applied by GDI ClearType, so we can get linear 100397efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com * values. 100497efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com * 100597efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com * GDI ClearType uses SPI_GETFONTSMOOTHINGCONTRAST / 1000 as the gamma value. 100697efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com * If this value is not specified, the default is a gamma of 1.4. 100797efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com */ 100897efada074e4806479f1350ab1508939c2fdcb53bungeman@google.comstatic const uint8_t* getInverseGammaTableClearType() { 100905a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com // We don't expect SPI_GETFONTSMOOTHINGCONTRAST to ever change, so building 101005a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com // gTableClearType with build_power_table is effectively idempotent. 101105a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com 101205a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com // Microsoft Specific: 101305a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com // Making gInited volatile provides read-aquire and write-release in vc++. 101405a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com // In VS2012, see compiler option /volatile:(ms|iso). 101505a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com // Replace with C++11 atomics when possible. 101605a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com static volatile bool gInited; 101797efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com static uint8_t gTableClearType[256]; 101805a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com if (gInited) { 101905a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com // Need a L/L (read) barrier (acquire not needed). If gInited is observed 102005a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com // true then gTableClearType is observable, but it must be requested. 102105a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com } else { 10227430a3376c0f4e0c2809fedecd12765034f9e3a8reed@google.com UINT level = 0; 10237430a3376c0f4e0c2809fedecd12765034f9e3a8reed@google.com if (!SystemParametersInfo(SPI_GETFONTSMOOTHINGCONTRAST, 0, &level, 0) || !level) { 10247430a3376c0f4e0c2809fedecd12765034f9e3a8reed@google.com // can't get the data, so use a default 10257430a3376c0f4e0c2809fedecd12765034f9e3a8reed@google.com level = 1400; 10267430a3376c0f4e0c2809fedecd12765034f9e3a8reed@google.com } 102797efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com build_power_table(gTableClearType, level / 1000.0f); 102805a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com // Need a S/S (write) barrier (release not needed) here so that this 102905a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com // write to gInited becomes observable after gTableClearType. 10307430a3376c0f4e0c2809fedecd12765034f9e3a8reed@google.com gInited = true; 10317430a3376c0f4e0c2809fedecd12765034f9e3a8reed@google.com } 103297efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com return gTableClearType; 10337430a3376c0f4e0c2809fedecd12765034f9e3a8reed@google.com} 10347430a3376c0f4e0c2809fedecd12765034f9e3a8reed@google.com 1035ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com#include "SkColorPriv.h" 1036ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 10376385314686875ecb484d95b33fcbf08890b5144dbungeman@google.com//Cannot assume that the input rgb is gray due to possible setting of kGenA8FromLCD_Flag. 103897efada074e4806479f1350ab1508939c2fdcb53bungeman@google.comtemplate<bool APPLY_PREBLEND> 103997efada074e4806479f1350ab1508939c2fdcb53bungeman@google.comstatic inline uint8_t rgb_to_a8(SkGdiRGB rgb, const uint8_t* table8) { 10406385314686875ecb484d95b33fcbf08890b5144dbungeman@google.com U8CPU r = (rgb >> 16) & 0xFF; 10416385314686875ecb484d95b33fcbf08890b5144dbungeman@google.com U8CPU g = (rgb >> 8) & 0xFF; 10426385314686875ecb484d95b33fcbf08890b5144dbungeman@google.com U8CPU b = (rgb >> 0) & 0xFF; 10431bfe01d06b896eca94c80d9af9a6bb30216b5e42bungeman@google.com return sk_apply_lut_if<APPLY_PREBLEND>(SkComputeLuminance(r, g, b), table8); 104482a34d83f646d069ef2d1d7b649d0a0b1829d62freed@google.com} 104582a34d83f646d069ef2d1d7b649d0a0b1829d62freed@google.com 104697efada074e4806479f1350ab1508939c2fdcb53bungeman@google.comtemplate<bool APPLY_PREBLEND> 104797efada074e4806479f1350ab1508939c2fdcb53bungeman@google.comstatic inline uint16_t rgb_to_lcd16(SkGdiRGB rgb, const uint8_t* tableR, 104897efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com const uint8_t* tableG, 104997efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com const uint8_t* tableB) { 105097efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 16) & 0xFF, tableR); 105197efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 8) & 0xFF, tableG); 105297efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 0) & 0xFF, tableB); 105397efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com return SkPack888ToRGB16(r, g, b); 1054ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com} 1055ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 105697efada074e4806479f1350ab1508939c2fdcb53bungeman@google.comtemplate<bool APPLY_PREBLEND> 105797efada074e4806479f1350ab1508939c2fdcb53bungeman@google.comstatic inline SkPMColor rgb_to_lcd32(SkGdiRGB rgb, const uint8_t* tableR, 105897efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com const uint8_t* tableG, 105997efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com const uint8_t* tableB) { 106097efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 16) & 0xFF, tableR); 106197efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 8) & 0xFF, tableG); 106297efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 0) & 0xFF, tableB); 106397efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com return SkPackARGB32(0xFF, r, g, b); 1064754e4ebd10d7353ce55be7dfe0a417e502ef4047reed@google.com} 1065754e4ebd10d7353ce55be7dfe0a417e502ef4047reed@google.com 106682cff020b7e055f2d01686f060a884df842306edreed@google.com// Is this GDI color neither black nor white? If so, we have to keep this 106782cff020b7e055f2d01686f060a884df842306edreed@google.com// image as is, rather than smashing it down to a BW mask. 106882cff020b7e055f2d01686f060a884df842306edreed@google.com// 106982cff020b7e055f2d01686f060a884df842306edreed@google.com// returns int instead of bool, since we don't want/have to pay to convert 107082cff020b7e055f2d01686f060a884df842306edreed@google.com// the zero/non-zero value into a bool 107182cff020b7e055f2d01686f060a884df842306edreed@google.comstatic int is_not_black_or_white(SkGdiRGB c) { 107282cff020b7e055f2d01686f060a884df842306edreed@google.com // same as (but faster than) 107382cff020b7e055f2d01686f060a884df842306edreed@google.com // c &= 0x00FFFFFF; 107482cff020b7e055f2d01686f060a884df842306edreed@google.com // return 0 == c || 0x00FFFFFF == c; 107582cff020b7e055f2d01686f060a884df842306edreed@google.com return (c + (c & 1)) & 0x00FFFFFF; 10765e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com} 10775e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com 10785e2df64215f12660ab26b96816f40ad8e32bf16freed@google.comstatic bool is_rgb_really_bw(const SkGdiRGB* src, int width, int height, int srcRB) { 10795e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com for (int y = 0; y < height; ++y) { 10805e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com for (int x = 0; x < width; ++x) { 108182cff020b7e055f2d01686f060a884df842306edreed@google.com if (is_not_black_or_white(src[x])) { 10825e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com return false; 10835e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com } 10845e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com } 108505a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com src = SkTAddOffset<const SkGdiRGB>(src, srcRB); 10865e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com } 10875e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com return true; 10885e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com} 10895e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com 109097efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com// gdi's bitmap is upside-down, so we reverse dst walking in Y 109197efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com// whenever we copy it into skia's buffer 10925e2df64215f12660ab26b96816f40ad8e32bf16freed@google.comstatic void rgb_to_bw(const SkGdiRGB* SK_RESTRICT src, size_t srcRB, 109397efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com const SkGlyph& glyph) { 10945e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com const int width = glyph.fWidth; 10955e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com const size_t dstRB = (width + 7) >> 3; 10965e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com uint8_t* SK_RESTRICT dst = (uint8_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB); 10975e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com 10985e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com int byteCount = width >> 3; 10995e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com int bitCount = width & 7; 11005e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com 11015e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com // adjust srcRB to skip the values in our byteCount loop, 11025e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com // since we increment src locally there 11035e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com srcRB -= byteCount * 8 * sizeof(SkGdiRGB); 11045e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com 11055e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com for (int y = 0; y < glyph.fHeight; ++y) { 11065e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com if (byteCount > 0) { 11075e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com for (int i = 0; i < byteCount; ++i) { 11087a230142e01c5a8cf955be12a5f287589b551634reed@google.com unsigned byte = 0; 110997efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com byte |= src[0] & (1 << 7); 111097efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com byte |= src[1] & (1 << 6); 111197efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com byte |= src[2] & (1 << 5); 111297efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com byte |= src[3] & (1 << 4); 111397efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com byte |= src[4] & (1 << 3); 111497efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com byte |= src[5] & (1 << 2); 111597efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com byte |= src[6] & (1 << 1); 111697efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com byte |= src[7] & (1 << 0); 11176a8f14d9633b330fb8051581828a0aaf4403d1a9reed@google.com dst[i] = byte; 11185e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com src += 8; 11195e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com } 11205e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com } 11215e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com if (bitCount > 0) { 11225e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com unsigned byte = 0; 11235e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com unsigned mask = 0x80; 11245e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com for (int i = 0; i < bitCount; i++) { 112597efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com byte |= src[i] & mask; 11265e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com mask >>= 1; 11275e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com } 11285e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com dst[byteCount] = byte; 11295e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com } 113005a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com src = SkTAddOffset<const SkGdiRGB>(src, srcRB); 11315e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com dst -= dstRB; 11325e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com } 11335e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com} 11345e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com 113597efada074e4806479f1350ab1508939c2fdcb53bungeman@google.comtemplate<bool APPLY_PREBLEND> 11365e2df64215f12660ab26b96816f40ad8e32bf16freed@google.comstatic void rgb_to_a8(const SkGdiRGB* SK_RESTRICT src, size_t srcRB, 113797efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com const SkGlyph& glyph, const uint8_t* table8) { 11385e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com const size_t dstRB = glyph.rowBytes(); 11395e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com const int width = glyph.fWidth; 11405e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com uint8_t* SK_RESTRICT dst = (uint8_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB); 11415e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com 11425e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com for (int y = 0; y < glyph.fHeight; y++) { 11435e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com for (int i = 0; i < width; i++) { 114497efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com dst[i] = rgb_to_a8<APPLY_PREBLEND>(src[i], table8); 11455e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com } 114605a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com src = SkTAddOffset<const SkGdiRGB>(src, srcRB); 11475e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com dst -= dstRB; 11485e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com } 11495e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com} 11505e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com 115197efada074e4806479f1350ab1508939c2fdcb53bungeman@google.comtemplate<bool APPLY_PREBLEND> 115297efada074e4806479f1350ab1508939c2fdcb53bungeman@google.comstatic void rgb_to_lcd16(const SkGdiRGB* SK_RESTRICT src, size_t srcRB, const SkGlyph& glyph, 115397efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) { 11545e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com const size_t dstRB = glyph.rowBytes(); 11555e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com const int width = glyph.fWidth; 11565e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com uint16_t* SK_RESTRICT dst = (uint16_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB); 11575e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com 11585e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com for (int y = 0; y < glyph.fHeight; y++) { 11595e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com for (int i = 0; i < width; i++) { 116097efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com dst[i] = rgb_to_lcd16<APPLY_PREBLEND>(src[i], tableR, tableG, tableB); 11615e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com } 116205a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com src = SkTAddOffset<const SkGdiRGB>(src, srcRB); 11635e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com dst = (uint16_t*)((char*)dst - dstRB); 11645e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com } 11655e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com} 11665e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com 116797efada074e4806479f1350ab1508939c2fdcb53bungeman@google.comtemplate<bool APPLY_PREBLEND> 116897efada074e4806479f1350ab1508939c2fdcb53bungeman@google.comstatic void rgb_to_lcd32(const SkGdiRGB* SK_RESTRICT src, size_t srcRB, const SkGlyph& glyph, 116997efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) { 1170754e4ebd10d7353ce55be7dfe0a417e502ef4047reed@google.com const size_t dstRB = glyph.rowBytes(); 1171754e4ebd10d7353ce55be7dfe0a417e502ef4047reed@google.com const int width = glyph.fWidth; 117297efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com uint32_t* SK_RESTRICT dst = (uint32_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB); 1173754e4ebd10d7353ce55be7dfe0a417e502ef4047reed@google.com 1174754e4ebd10d7353ce55be7dfe0a417e502ef4047reed@google.com for (int y = 0; y < glyph.fHeight; y++) { 1175754e4ebd10d7353ce55be7dfe0a417e502ef4047reed@google.com for (int i = 0; i < width; i++) { 117697efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com dst[i] = rgb_to_lcd32<APPLY_PREBLEND>(src[i], tableR, tableG, tableB); 1177754e4ebd10d7353ce55be7dfe0a417e502ef4047reed@google.com } 117805a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com src = SkTAddOffset<const SkGdiRGB>(src, srcRB); 117997efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com dst = (uint32_t*)((char*)dst - dstRB); 1180754e4ebd10d7353ce55be7dfe0a417e502ef4047reed@google.com } 1181754e4ebd10d7353ce55be7dfe0a417e502ef4047reed@google.com} 1182754e4ebd10d7353ce55be7dfe0a417e502ef4047reed@google.com 11836f5df48c1d07295b75c1955a69142fb5e66b8647reed@google.comstatic inline unsigned clamp255(unsigned x) { 11846f5df48c1d07295b75c1955a69142fb5e66b8647reed@google.com SkASSERT(x <= 256); 11856f5df48c1d07295b75c1955a69142fb5e66b8647reed@google.com return x - (x >> 8); 11866f5df48c1d07295b75c1955a69142fb5e66b8647reed@google.com} 11876f5df48c1d07295b75c1955a69142fb5e66b8647reed@google.com 1188a76de72a6036da0a6b051b14411b80941971f881bungeman@google.comvoid SkScalerContext_Windows::generateImage(const SkGlyph& glyph) { 1189ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com SkASSERT(fDDC); 1190ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 11916271117d826098c1399cf7442f8eea2d665cb78areed@google.com const bool isBW = SkMask::kBW_Format == fRec.fMaskFormat; 119282a34d83f646d069ef2d1d7b649d0a0b1829d62freed@google.com const bool isAA = !isLCD(fRec); 119382a34d83f646d069ef2d1d7b649d0a0b1829d62freed@google.com 119499edd43813b7f1a8f02146cbd8c783d3c82be4abreed@google.com size_t srcRB; 119597efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com const void* bits = fOffscreen.draw(glyph, isBW, &srcRB); 119639698b1bd71fd54c7c44ae8d7224afdaf93c0ddabungeman@google.com if (NULL == bits) { 1197055180cb9c47c87e5ee8c9fa6d3f6a6079ad6f35reed@google.com LogFontTypeface::EnsureAccessible(this->getTypeface()); 119897efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com bits = fOffscreen.draw(glyph, isBW, &srcRB); 119939698b1bd71fd54c7c44ae8d7224afdaf93c0ddabungeman@google.com if (NULL == bits) { 120039698b1bd71fd54c7c44ae8d7224afdaf93c0ddabungeman@google.com sk_bzero(glyph.fImage, glyph.computeImageSize()); 120139698b1bd71fd54c7c44ae8d7224afdaf93c0ddabungeman@google.com return; 120239698b1bd71fd54c7c44ae8d7224afdaf93c0ddabungeman@google.com } 120382a34d83f646d069ef2d1d7b649d0a0b1829d62freed@google.com } 120482a34d83f646d069ef2d1d7b649d0a0b1829d62freed@google.com 120597efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com if (!isBW) { 12061bd2d67702a5c14011f02e23b3724965f82c4780bungeman@google.com const uint8_t* table; 12071bd2d67702a5c14011f02e23b3724965f82c4780bungeman@google.com //The offscreen contains a GDI blit if isAA and kGenA8FromLCD_Flag is not set. 12081bd2d67702a5c14011f02e23b3724965f82c4780bungeman@google.com //Otherwise the offscreen contains a ClearType blit. 12091bd2d67702a5c14011f02e23b3724965f82c4780bungeman@google.com if (isAA && !(fRec.fFlags & SkScalerContext::kGenA8FromLCD_Flag)) { 12101bd2d67702a5c14011f02e23b3724965f82c4780bungeman@google.com table = getInverseGammaTableGDI(); 12111bd2d67702a5c14011f02e23b3724965f82c4780bungeman@google.com } else { 12121bd2d67702a5c14011f02e23b3724965f82c4780bungeman@google.com table = getInverseGammaTableClearType(); 121397efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com } 121497efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com //Note that the following cannot really be integrated into the 121597efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com //pre-blend, since we may not be applying the pre-blend; when we aren't 121697efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com //applying the pre-blend it means that a filter wants linear anyway. 121797efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com //Other code may also be applying the pre-blend, so we'd need another 121897efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com //one with this and one without. 12196f5df48c1d07295b75c1955a69142fb5e66b8647reed@google.com SkGdiRGB* addr = (SkGdiRGB*)bits; 12206f5df48c1d07295b75c1955a69142fb5e66b8647reed@google.com for (int y = 0; y < glyph.fHeight; ++y) { 12216f5df48c1d07295b75c1955a69142fb5e66b8647reed@google.com for (int x = 0; x < glyph.fWidth; ++x) { 12226f5df48c1d07295b75c1955a69142fb5e66b8647reed@google.com int r = (addr[x] >> 16) & 0xFF; 12236f5df48c1d07295b75c1955a69142fb5e66b8647reed@google.com int g = (addr[x] >> 8) & 0xFF; 12246f5df48c1d07295b75c1955a69142fb5e66b8647reed@google.com int b = (addr[x] >> 0) & 0xFF; 12257430a3376c0f4e0c2809fedecd12765034f9e3a8reed@google.com addr[x] = (table[r] << 16) | (table[g] << 8) | table[b]; 12266f5df48c1d07295b75c1955a69142fb5e66b8647reed@google.com } 122705a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com addr = SkTAddOffset<SkGdiRGB>(addr, srcRB); 12286f5df48c1d07295b75c1955a69142fb5e66b8647reed@google.com } 12296f5df48c1d07295b75c1955a69142fb5e66b8647reed@google.com } 12306f5df48c1d07295b75c1955a69142fb5e66b8647reed@google.com 123182a34d83f646d069ef2d1d7b649d0a0b1829d62freed@google.com int width = glyph.fWidth; 123282a34d83f646d069ef2d1d7b649d0a0b1829d62freed@google.com size_t dstRB = glyph.rowBytes(); 123382a34d83f646d069ef2d1d7b649d0a0b1829d62freed@google.com if (isBW) { 123482a34d83f646d069ef2d1d7b649d0a0b1829d62freed@google.com const uint8_t* src = (const uint8_t*)bits; 123582a34d83f646d069ef2d1d7b649d0a0b1829d62freed@google.com uint8_t* dst = (uint8_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB); 123682a34d83f646d069ef2d1d7b649d0a0b1829d62freed@google.com for (int y = 0; y < glyph.fHeight; y++) { 123782a34d83f646d069ef2d1d7b649d0a0b1829d62freed@google.com memcpy(dst, src, dstRB); 123882a34d83f646d069ef2d1d7b649d0a0b1829d62freed@google.com src += srcRB; 123982a34d83f646d069ef2d1d7b649d0a0b1829d62freed@google.com dst -= dstRB; 1240ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } 124182a34d83f646d069ef2d1d7b649d0a0b1829d62freed@google.com } else if (isAA) { 12426f5df48c1d07295b75c1955a69142fb5e66b8647reed@google.com // since the caller may require A8 for maskfilters, we can't check for BW 12436f5df48c1d07295b75c1955a69142fb5e66b8647reed@google.com // ... until we have the caller tell us that explicitly 12445e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com const SkGdiRGB* src = (const SkGdiRGB*)bits; 1245a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com if (fPreBlend.isApplicable()) { 1246a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com rgb_to_a8<true>(src, srcRB, glyph, fPreBlend.fG); 124797efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com } else { 1248a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com rgb_to_a8<false>(src, srcRB, glyph, fPreBlend.fG); 124997efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com } 125082a34d83f646d069ef2d1d7b649d0a0b1829d62freed@google.com } else { // LCD16 12515e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com const SkGdiRGB* src = (const SkGdiRGB*)bits; 12525e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com if (is_rgb_really_bw(src, width, glyph.fHeight, srcRB)) { 125397efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com rgb_to_bw(src, srcRB, glyph); 12545e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com ((SkGlyph*)&glyph)->fMaskFormat = SkMask::kBW_Format; 12555e2df64215f12660ab26b96816f40ad8e32bf16freed@google.com } else { 1256754e4ebd10d7353ce55be7dfe0a417e502ef4047reed@google.com if (SkMask::kLCD16_Format == glyph.fMaskFormat) { 1257a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com if (fPreBlend.isApplicable()) { 1258a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com rgb_to_lcd16<true>(src, srcRB, glyph, 1259a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); 126097efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com } else { 1261a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com rgb_to_lcd16<false>(src, srcRB, glyph, 1262a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); 126397efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com } 1264754e4ebd10d7353ce55be7dfe0a417e502ef4047reed@google.com } else { 1265754e4ebd10d7353ce55be7dfe0a417e502ef4047reed@google.com SkASSERT(SkMask::kLCD32_Format == glyph.fMaskFormat); 1266a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com if (fPreBlend.isApplicable()) { 1267a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com rgb_to_lcd32<true>(src, srcRB, glyph, 1268a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); 126997efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com } else { 1270a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com rgb_to_lcd32<false>(src, srcRB, glyph, 1271a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); 127297efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com } 1273754e4ebd10d7353ce55be7dfe0a417e502ef4047reed@google.com } 1274ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } 1275ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } 1276ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com} 1277ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 1278ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.comvoid SkScalerContext_Windows::generatePath(const SkGlyph& glyph, SkPath* path) { 1279ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com SkASSERT(&glyph && path); 1280ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com SkASSERT(fDDC); 1281ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 1282ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com path->reset(); 1283ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 1284ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com GLYPHMETRICS gm; 128505a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com 128605a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com // Out of all the fonts on a typical Windows box, 128705a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com // 25% of glyphs require more than 2KB. 128805a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com // 1% of glyphs require more than 4KB. 128905a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com // 0.01% of glyphs require more than 8KB. 129005a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com // 8KB is less than 1% of the normal 1MB stack on Windows. 129105a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com // Note that some web fonts glyphs require more than 20KB. 12924fe06995fc4d29d2f7b514a55376787dd3319c59bungeman@google.com static const DWORD BUFFERSIZE = (1 << 13); 129305a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com SkAutoSTMalloc<BUFFERSIZE, uint8_t> glyphbuf(BUFFERSIZE); 129405a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com 129505a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com const UINT flags = GGO_NATIVE | GGO_GLYPH_INDEX; 129605a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com DWORD total_size = GetGlyphOutlineW(fDDC, glyph.fID, flags, &gm, BUFFERSIZE, glyphbuf, &fMat22); 12974fe06995fc4d29d2f7b514a55376787dd3319c59bungeman@google.com // Sometimes GetGlyphOutlineW returns a number larger than BUFFERSIZE even if BUFFERSIZE > 0. 12984fe06995fc4d29d2f7b514a55376787dd3319c59bungeman@google.com // It has been verified that this does not involve a buffer overrun. 12994fe06995fc4d29d2f7b514a55376787dd3319c59bungeman@google.com if (GDI_ERROR == total_size || total_size > BUFFERSIZE) { 130005a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com // GDI_ERROR because the BUFFERSIZE was too small, or because the data was not accessible. 130105a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com // When the data is not accessable GetGlyphOutlineW fails rather quickly, 130205a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com // so just try to get the size. If that fails then ensure the data is accessible. 130305a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com total_size = GetGlyphOutlineW(fDDC, glyph.fID, flags, &gm, 0, NULL, &fMat22); 1304d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com if (GDI_ERROR == total_size) { 130505a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com LogFontTypeface::EnsureAccessible(this->getTypeface()); 130605a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com total_size = GetGlyphOutlineW(fDDC, glyph.fID, flags, &gm, 0, NULL, &fMat22); 130705a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com if (GDI_ERROR == total_size) { 130805a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com SkASSERT(false); 130905a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com return; 131005a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com } 131105a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com } 131205a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com 131305a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com glyphbuf.reset(total_size); 131405a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com 131505a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com DWORD ret = GetGlyphOutlineW(fDDC, glyph.fID, flags, &gm, total_size, glyphbuf, &fMat22); 131605a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com if (GDI_ERROR == ret) { 131705a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com LogFontTypeface::EnsureAccessible(this->getTypeface()); 131805a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com ret = GetGlyphOutlineW(fDDC, glyph.fID, flags, &gm, total_size, glyphbuf, &fMat22); 131905a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com if (GDI_ERROR == ret) { 132005a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com SkASSERT(false); 132105a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com return; 132205a729ff90f75ac013873742ee0e4ae7e5e6e415bungeman@google.com } 1323d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com } 132439698b1bd71fd54c7c44ae8d7224afdaf93c0ddabungeman@google.com } 1325ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 1326d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com const uint8_t* cur_glyph = glyphbuf; 1327d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com const uint8_t* end_glyph = glyphbuf + total_size; 1328ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 1329d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com while (cur_glyph < end_glyph) { 1330d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com const TTPOLYGONHEADER* th = (TTPOLYGONHEADER*)cur_glyph; 1331ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 1332d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com const uint8_t* end_poly = cur_glyph + th->cb; 1333d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com const uint8_t* cur_poly = cur_glyph + sizeof(TTPOLYGONHEADER); 1334ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 1335d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com path->moveTo(SkFixedToScalar( SkFIXEDToFixed(th->pfxStart.x)), 1336d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com SkFixedToScalar(-SkFIXEDToFixed(th->pfxStart.y))); 1337ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 1338d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com while (cur_poly < end_poly) { 1339d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com const TTPOLYCURVE* pc = (const TTPOLYCURVE*)cur_poly; 1340ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 1341d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com if (pc->wType == TT_PRIM_LINE) { 1342d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com for (uint16_t i = 0; i < pc->cpfx; i++) { 1343d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com path->lineTo(SkFixedToScalar( SkFIXEDToFixed(pc->apfx[i].x)), 1344d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com SkFixedToScalar(-SkFIXEDToFixed(pc->apfx[i].y))); 1345ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } 1346d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com } 1347ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 1348d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com if (pc->wType == TT_PRIM_QSPLINE) { 1349d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com for (uint16_t u = 0; u < pc->cpfx - 1; u++) { // Walk through points in spline 1350d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com POINTFX pnt_b = pc->apfx[u]; // B is always the current point 1351d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com POINTFX pnt_c = pc->apfx[u+1]; 1352ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 1353d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com if (u < pc->cpfx - 2) { // If not on last spline, compute C 1354d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com pnt_c.x = SkFixedToFIXED(SkFixedAve(SkFIXEDToFixed(pnt_b.x), 1355d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com SkFIXEDToFixed(pnt_c.x))); 1356d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com pnt_c.y = SkFixedToFIXED(SkFixedAve(SkFIXEDToFixed(pnt_b.y), 1357d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com SkFIXEDToFixed(pnt_c.y))); 1358ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } 1359d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com 1360d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com path->quadTo(SkFixedToScalar( SkFIXEDToFixed(pnt_b.x)), 1361d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com SkFixedToScalar(-SkFIXEDToFixed(pnt_b.y)), 1362d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com SkFixedToScalar( SkFIXEDToFixed(pnt_c.x)), 1363d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com SkFixedToScalar(-SkFIXEDToFixed(pnt_c.y))); 1364ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } 1365ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } 1366d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com // Advance past this TTPOLYCURVE. 1367d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com cur_poly += sizeof(WORD) * 2 + sizeof(POINTFX) * pc->cpfx; 1368ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } 1369d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com cur_glyph += th->cb; 1370d1c7f71ee371738a8c7896a4f06d28b32e3c713ebungeman@google.com path->close(); 1371ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } 1372ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com} 1373ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 1374484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.comstatic void logfont_for_name(const char* familyName, LOGFONT* lf) { 1375484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com sk_bzero(lf, sizeof(LOGFONT)); 1376e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com#ifdef UNICODE 1377484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com // Get the buffer size needed first. 1378484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com size_t str_len = ::MultiByteToWideChar(CP_UTF8, 0, familyName, 1379484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com -1, NULL, 0); 1380484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com // Allocate a buffer (str_len already has terminating null 1381484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com // accounted for). 1382484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com wchar_t *wideFamilyName = new wchar_t[str_len]; 1383484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com // Now actually convert the string. 1384484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com ::MultiByteToWideChar(CP_UTF8, 0, familyName, -1, 1385484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com wideFamilyName, str_len); 1386484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com ::wcsncpy(lf->lfFaceName, wideFamilyName, LF_FACESIZE - 1); 1387484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com delete [] wideFamilyName; 1388484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com lf->lfFaceName[LF_FACESIZE-1] = L'\0'; 1389e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com#else 1390484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com ::strncpy(lf->lfFaceName, familyName, LF_FACESIZE - 1); 1391484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com lf->lfFaceName[LF_FACESIZE - 1] = '\0'; 1392e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com#endif 1393e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com} 1394e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com 13955526ede94a2fc58bcf6b578b12a29f6addad776dreed@google.comvoid LogFontTypeface::onGetFontDescriptor(SkFontDescriptor* desc, 13965526ede94a2fc58bcf6b578b12a29f6addad776dreed@google.com bool* isLocalStream) const { 13977103f182ce61280eacb35f1832df350b642a5381bungeman@google.com // Get the actual name of the typeface. The logfont may not know this. 13985526ede94a2fc58bcf6b578b12a29f6addad776dreed@google.com HFONT font = CreateFontIndirect(&fLogFont); 13997103f182ce61280eacb35f1832df350b642a5381bungeman@google.com 14007103f182ce61280eacb35f1832df350b642a5381bungeman@google.com HDC deviceContext = ::CreateCompatibleDC(NULL); 14017103f182ce61280eacb35f1832df350b642a5381bungeman@google.com HFONT savefont = (HFONT)SelectObject(deviceContext, font); 14027103f182ce61280eacb35f1832df350b642a5381bungeman@google.com 14037103f182ce61280eacb35f1832df350b642a5381bungeman@google.com int fontNameLen; //length of fontName in TCHARS. 14047103f182ce61280eacb35f1832df350b642a5381bungeman@google.com if (0 == (fontNameLen = GetTextFace(deviceContext, 0, NULL))) { 14055526ede94a2fc58bcf6b578b12a29f6addad776dreed@google.com call_ensure_accessible(fLogFont); 14067103f182ce61280eacb35f1832df350b642a5381bungeman@google.com if (0 == (fontNameLen = GetTextFace(deviceContext, 0, NULL))) { 14077103f182ce61280eacb35f1832df350b642a5381bungeman@google.com fontNameLen = 0; 14087103f182ce61280eacb35f1832df350b642a5381bungeman@google.com } 14097103f182ce61280eacb35f1832df350b642a5381bungeman@google.com } 14107103f182ce61280eacb35f1832df350b642a5381bungeman@google.com 14117103f182ce61280eacb35f1832df350b642a5381bungeman@google.com SkAutoSTArray<LF_FULLFACESIZE, TCHAR> fontName(fontNameLen+1); 14127103f182ce61280eacb35f1832df350b642a5381bungeman@google.com if (0 == GetTextFace(deviceContext, fontNameLen, fontName.get())) { 14135526ede94a2fc58bcf6b578b12a29f6addad776dreed@google.com call_ensure_accessible(fLogFont); 14147103f182ce61280eacb35f1832df350b642a5381bungeman@google.com if (0 == GetTextFace(deviceContext, fontNameLen, fontName.get())) { 14157103f182ce61280eacb35f1832df350b642a5381bungeman@google.com fontName[0] = 0; 14167103f182ce61280eacb35f1832df350b642a5381bungeman@google.com } 14177103f182ce61280eacb35f1832df350b642a5381bungeman@google.com } 14187103f182ce61280eacb35f1832df350b642a5381bungeman@google.com 14197103f182ce61280eacb35f1832df350b642a5381bungeman@google.com if (deviceContext) { 14207103f182ce61280eacb35f1832df350b642a5381bungeman@google.com ::SelectObject(deviceContext, savefont); 14217103f182ce61280eacb35f1832df350b642a5381bungeman@google.com ::DeleteDC(deviceContext); 14227103f182ce61280eacb35f1832df350b642a5381bungeman@google.com } 14237103f182ce61280eacb35f1832df350b642a5381bungeman@google.com if (font) { 14247103f182ce61280eacb35f1832df350b642a5381bungeman@google.com ::DeleteObject(font); 14257103f182ce61280eacb35f1832df350b642a5381bungeman@google.com } 14267103f182ce61280eacb35f1832df350b642a5381bungeman@google.com 1427e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com SkString familyName; 14287103f182ce61280eacb35f1832df350b642a5381bungeman@google.com tchar_to_skstring(fontName.get(), &familyName); 1429e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com 14305526ede94a2fc58bcf6b578b12a29f6addad776dreed@google.com desc->setFamilyName(familyName.c_str()); 14315526ede94a2fc58bcf6b578b12a29f6addad776dreed@google.com *isLocalStream = this->fSerializeAsStream; 1432ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com} 1433ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 1434ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.comstatic bool getWidthAdvance(HDC hdc, int gId, int16_t* advance) { 1435ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com // Initialize the MAT2 structure to the identify transformation matrix. 1436ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com static const MAT2 mat2 = {SkScalarToFIXED(1), SkScalarToFIXED(0), 1437ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com SkScalarToFIXED(0), SkScalarToFIXED(1)}; 1438ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com int flags = GGO_METRICS | GGO_GLYPH_INDEX; 1439ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com GLYPHMETRICS gm; 1440ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com if (GDI_ERROR == GetGlyphOutline(hdc, gId, flags, &gm, 0, NULL, &mat2)) { 1441ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com return false; 1442ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } 1443ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com SkASSERT(advance); 1444ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com *advance = gm.gmCellIncX; 1445ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com return true; 1446ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com} 1447ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 14482689f615e364dc48ad73826564f5b13d2329179dreed@google.comSkAdvancedTypefaceMetrics* LogFontTypeface::onGetAdvancedTypefaceMetrics( 144937ad8fb72ff1b3faac93b01ead2c79e1a06fc172vandebo@chromium.org SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo, 145037ad8fb72ff1b3faac93b01ead2c79e1a06fc172vandebo@chromium.org const uint32_t* glyphIDs, 14512689f615e364dc48ad73826564f5b13d2329179dreed@google.com uint32_t glyphIDsCount) const { 14522689f615e364dc48ad73826564f5b13d2329179dreed@google.com LOGFONT lf = fLogFont; 1453ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com SkAdvancedTypefaceMetrics* info = NULL; 1454ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 1455ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com HDC hdc = CreateCompatibleDC(NULL); 1456ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com HFONT font = CreateFontIndirect(&lf); 1457ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com HFONT savefont = (HFONT)SelectObject(hdc, font); 1458ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com HFONT designFont = NULL; 1459ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 146005b6f3a5a94de475d3a9dcfdd1833e24d933f207reed@google.com const char stem_chars[] = {'i', 'I', '!', '1'}; 146105b6f3a5a94de475d3a9dcfdd1833e24d933f207reed@google.com int16_t min_width; 146205b6f3a5a94de475d3a9dcfdd1833e24d933f207reed@google.com unsigned glyphCount; 146305b6f3a5a94de475d3a9dcfdd1833e24d933f207reed@google.com 1464ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com // To request design units, create a logical font whose height is specified 1465ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com // as unitsPerEm. 1466ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com OUTLINETEXTMETRIC otm; 146739698b1bd71fd54c7c44ae8d7224afdaf93c0ddabungeman@google.com unsigned int otmRet = GetOutlineTextMetrics(hdc, sizeof(otm), &otm); 146839698b1bd71fd54c7c44ae8d7224afdaf93c0ddabungeman@google.com if (0 == otmRet) { 1469055180cb9c47c87e5ee8c9fa6d3f6a6079ad6f35reed@google.com call_ensure_accessible(lf); 147039698b1bd71fd54c7c44ae8d7224afdaf93c0ddabungeman@google.com otmRet = GetOutlineTextMetrics(hdc, sizeof(otm), &otm); 147139698b1bd71fd54c7c44ae8d7224afdaf93c0ddabungeman@google.com } 147239698b1bd71fd54c7c44ae8d7224afdaf93c0ddabungeman@google.com if (!otmRet || !GetTextFace(hdc, LF_FACESIZE, lf.lfFaceName)) { 1473ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com goto Error; 1474ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } 1475ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com lf.lfHeight = -SkToS32(otm.otmEMSquare); 1476ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com designFont = CreateFontIndirect(&lf); 1477ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com SelectObject(hdc, designFont); 1478ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com if (!GetOutlineTextMetrics(hdc, sizeof(otm), &otm)) { 1479ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com goto Error; 1480ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } 14817bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com glyphCount = calculateGlyphCount(hdc, fLogFont); 1482ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 1483ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com info = new SkAdvancedTypefaceMetrics; 1484ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com info->fEmSize = otm.otmEMSquare; 1485ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com info->fMultiMaster = false; 1486ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com info->fLastGlyphID = SkToU16(glyphCount - 1); 1487ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com info->fStyle = 0; 14887103f182ce61280eacb35f1832df350b642a5381bungeman@google.com tchar_to_skstring(lf.lfFaceName, &info->fFontName); 1489ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 14906744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo) { 14916744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org populate_glyph_to_unicode(hdc, glyphCount, &(info->fGlyphToUnicode)); 14926744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org } 14936744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org 1494d41e70de196e78e21e1001d23a7259785cbd0835vandebo@chromium.org if (glyphCount > 0 && 1495d41e70de196e78e21e1001d23a7259785cbd0835vandebo@chromium.org (otm.otmTextMetrics.tmPitchAndFamily & TMPF_TRUETYPE)) { 1496ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font; 1497ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } else { 1498ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com info->fType = SkAdvancedTypefaceMetrics::kOther_Font; 1499ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com info->fItalicAngle = 0; 1500ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com info->fAscent = 0; 1501ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com info->fDescent = 0; 1502ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com info->fStemV = 0; 1503ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com info->fCapHeight = 0; 1504ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com info->fBBox = SkIRect::MakeEmpty(); 1505390c6d7a9018e233a6519397ac6c739fb21a99efedisonn@google.com goto ReturnInfo; 1506ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } 15075aa937b300475c956bfad0c34a6daa71d166f6factguil@chromium.org 1508ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com // If this bit is clear the font is a fixed pitch font. 1509ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com if (!(otm.otmTextMetrics.tmPitchAndFamily & TMPF_FIXED_PITCH)) { 1510ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style; 1511ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } 1512ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com if (otm.otmTextMetrics.tmItalic) { 1513ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style; 1514ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } 1515ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com if (otm.otmTextMetrics.tmPitchAndFamily & FF_ROMAN) { 1516ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style; 1517ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } else if (otm.otmTextMetrics.tmPitchAndFamily & FF_SCRIPT) { 1518ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style; 1519ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } 1520ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 1521ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com // The main italic angle of the font, in tenths of a degree counterclockwise 1522ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com // from vertical. 1523ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com info->fItalicAngle = otm.otmItalicAngle / 10; 1524ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com info->fAscent = SkToS16(otm.otmTextMetrics.tmAscent); 1525ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com info->fDescent = SkToS16(-otm.otmTextMetrics.tmDescent); 1526ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com // TODO(ctguil): Use alternate cap height calculation. 1527ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com // MSDN says otmsCapEmHeight is not support but it is returning a value on 1528ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com // my Win7 box. 1529ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com info->fCapHeight = otm.otmsCapEmHeight; 1530ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com info->fBBox = 1531ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com SkIRect::MakeLTRB(otm.otmrcFontBox.left, otm.otmrcFontBox.top, 1532ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com otm.otmrcFontBox.right, otm.otmrcFontBox.bottom); 1533ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 1534ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com // Figure out a good guess for StemV - Min width of i, I, !, 1. 1535ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com // This probably isn't very good with an italic font. 153605b6f3a5a94de475d3a9dcfdd1833e24d933f207reed@google.com min_width = SHRT_MAX; 1537ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com info->fStemV = 0; 1538ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) { 1539ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com ABC abcWidths; 1540ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com if (GetCharABCWidths(hdc, stem_chars[i], stem_chars[i], &abcWidths)) { 1541ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com int16_t width = abcWidths.abcB; 1542ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com if (width > 0 && width < min_width) { 1543ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com min_width = width; 1544ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com info->fStemV = min_width; 1545ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } 1546ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } 1547ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } 1548ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 1549ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com // If bit 1 is set, the font may not be embedded in a document. 1550ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com // If bit 1 is clear, the font can be embedded. 1551ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com // If bit 2 is set, the embedding is read-only. 1552ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com if (otm.otmfsType & 0x1) { 1553ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font; 15540e6dc0a320985ffd31f77eed8a41e62132b9ba95ctguil@chromium.org } else if (perGlyphInfo & 15550e6dc0a320985ffd31f77eed8a41e62132b9ba95ctguil@chromium.org SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo) { 15565aa937b300475c956bfad0c34a6daa71d166f6factguil@chromium.org if (info->fStyle & SkAdvancedTypefaceMetrics::kFixedPitch_Style) { 15575aa937b300475c956bfad0c34a6daa71d166f6factguil@chromium.org appendRange(&info->fGlyphWidths, 0); 15585aa937b300475c956bfad0c34a6daa71d166f6factguil@chromium.org info->fGlyphWidths->fAdvance.append(1, &min_width); 15595aa937b300475c956bfad0c34a6daa71d166f6factguil@chromium.org finishRange(info->fGlyphWidths.get(), 0, 15605aa937b300475c956bfad0c34a6daa71d166f6factguil@chromium.org SkAdvancedTypefaceMetrics::WidthRange::kDefault); 15615aa937b300475c956bfad0c34a6daa71d166f6factguil@chromium.org } else { 15625aa937b300475c956bfad0c34a6daa71d166f6factguil@chromium.org info->fGlyphWidths.reset( 156337ad8fb72ff1b3faac93b01ead2c79e1a06fc172vandebo@chromium.org getAdvanceData(hdc, 156437ad8fb72ff1b3faac93b01ead2c79e1a06fc172vandebo@chromium.org glyphCount, 156537ad8fb72ff1b3faac93b01ead2c79e1a06fc172vandebo@chromium.org glyphIDs, 156637ad8fb72ff1b3faac93b01ead2c79e1a06fc172vandebo@chromium.org glyphIDsCount, 156737ad8fb72ff1b3faac93b01ead2c79e1a06fc172vandebo@chromium.org &getWidthAdvance)); 15685aa937b300475c956bfad0c34a6daa71d166f6factguil@chromium.org } 1569ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } 1570ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 1571ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.comError: 1572390c6d7a9018e233a6519397ac6c739fb21a99efedisonn@google.comReturnInfo: 1573ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com SelectObject(hdc, savefont); 1574ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com DeleteObject(designFont); 1575ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com DeleteObject(font); 1576ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com DeleteDC(hdc); 1577ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 1578ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com return info; 1579ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com} 1580ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 1581a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com//Dummy representation of a Base64 encoded GUID from create_unique_font_name. 1582a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com#define BASE64_GUID_ID "XXXXXXXXXXXXXXXXXXXXXXXX" 1583a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com//Length of GUID representation from create_id, including NULL terminator. 1584a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com#define BASE64_GUID_ID_LEN SK_ARRAY_COUNT(BASE64_GUID_ID) 1585a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com 1586a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.comSK_COMPILE_ASSERT(BASE64_GUID_ID_LEN < LF_FACESIZE, GUID_longer_than_facesize); 1587a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com 1588a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com/** 1589a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com NameID 6 Postscript names cannot have the character '/'. 1590a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com It would be easier to hex encode the GUID, but that is 32 bytes, 1591a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com and many systems have issues with names longer than 28 bytes. 1592a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com The following need not be any standard base64 encoding. 1593a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com The encoded value is never decoded. 1594a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com*/ 1595d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.comstatic const char postscript_safe_base64_encode[] = 1596a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 1597a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com "abcdefghijklmnopqrstuvwxyz" 1598a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com "0123456789-_="; 1599a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com 1600a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com/** 1601a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com Formats a GUID into Base64 and places it into buffer. 1602a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com buffer should have space for at least BASE64_GUID_ID_LEN characters. 1603a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com The string will always be null terminated. 1604a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com XXXXXXXXXXXXXXXXXXXXXXXX0 1605a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com */ 1606a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.comstatic void format_guid_b64(const GUID& guid, char* buffer, size_t bufferSize) { 1607a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com SkASSERT(bufferSize >= BASE64_GUID_ID_LEN); 1608a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com size_t written = SkBase64::Encode(&guid, sizeof(guid), buffer, postscript_safe_base64_encode); 1609a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com SkASSERT(written < LF_FACESIZE); 1610a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com buffer[written] = '\0'; 1611a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com} 1612a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com 1613a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com/** 1614a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com Creates a Base64 encoded GUID and places it into buffer. 1615a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com buffer should have space for at least BASE64_GUID_ID_LEN characters. 1616a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com The string will always be null terminated. 1617a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com XXXXXXXXXXXXXXXXXXXXXXXX0 1618a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com */ 1619a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.comstatic HRESULT create_unique_font_name(char* buffer, size_t bufferSize) { 1620a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com GUID guid = {}; 1621a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com if (FAILED(CoCreateGuid(&guid))) { 1622a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com return E_UNEXPECTED; 1623a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com } 1624a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com format_guid_b64(guid, buffer, bufferSize); 1625a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com 1626a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com return S_OK; 1627a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com} 1628a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com 1629a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com/** 1630a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com Introduces a font to GDI. On failure will return NULL. The returned handle 1631a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com should eventually be passed to RemoveFontMemResourceEx. 1632a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com*/ 1633a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.comstatic HANDLE activate_font(SkData* fontData) { 1634a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com DWORD numFonts = 0; 1635a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com //AddFontMemResourceEx just copies the data, but does not specify const. 1636a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com HANDLE fontHandle = AddFontMemResourceEx(const_cast<void*>(fontData->data()), 1637a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com fontData->size(), 1638a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com 0, 1639a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com &numFonts); 1640a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com 1641a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com if (fontHandle != NULL && numFonts < 1) { 1642a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com RemoveFontMemResourceEx(fontHandle); 1643a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com return NULL; 1644a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com } 1645a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com 1646a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com return fontHandle; 1647a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com} 1648a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com 1649437eea160b2f605d9074106891288e85baaecfefreed@google.comstatic SkTypeface* create_from_stream(SkStream* stream) { 1650a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com // Create a unique and unpredictable font name. 1651a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com // Avoids collisions and access from CSS. 1652a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com char familyName[BASE64_GUID_ID_LEN]; 1653a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com const int familyNameSize = SK_ARRAY_COUNT(familyName); 1654a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com if (FAILED(create_unique_font_name(familyName, familyNameSize))) { 1655a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com return NULL; 1656a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com } 1657d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 1658a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com // Change the name of the font. 1659e9bbee397ce96aa6642a42823feb1d7c4a8ffd8bbungeman@google.com SkAutoTUnref<SkData> rewrittenFontData(SkOTUtils::RenameFont(stream, familyName, familyNameSize-1)); 1660e9bbee397ce96aa6642a42823feb1d7c4a8ffd8bbungeman@google.com if (NULL == rewrittenFontData.get()) { 1661a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com return NULL; 1662a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com } 1663ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 1664a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com // Register the font with GDI. 1665e9bbee397ce96aa6642a42823feb1d7c4a8ffd8bbungeman@google.com HANDLE fontReference = activate_font(rewrittenFontData.get()); 1666a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com if (NULL == fontReference) { 1667a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com return NULL; 1668a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com } 1669a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com 1670a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com // Create the typeface. 1671a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com LOGFONT lf; 1672484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com logfont_for_name(familyName, &lf); 1673a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com 1674a550199c6f37e1b05a386ea57eee4c40cc91d84dbungeman@google.com return SkCreateFontMemResourceTypefaceFromLOGFONT(lf, fontReference); 1675ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com} 1676ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 1677437eea160b2f605d9074106891288e85baaecfefreed@google.comSkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) { 1678437eea160b2f605d9074106891288e85baaecfefreed@google.com return create_from_stream(stream); 1679437eea160b2f605d9074106891288e85baaecfefreed@google.com} 1680437eea160b2f605d9074106891288e85baaecfefreed@google.com 16810042b9c2a2e6fe954cdfbcd5a5b7449cdf41a4c3reed@google.comSkStream* LogFontTypeface::onOpenStream(int* ttcIndex) const { 16820042b9c2a2e6fe954cdfbcd5a5b7449cdf41a4c3reed@google.com *ttcIndex = 0; 16830042b9c2a2e6fe954cdfbcd5a5b7449cdf41a4c3reed@google.com 1684f4c2622a1a3489988f2d85a81fdc132b17a92bddctguil@chromium.org const DWORD kTTCTag = 1685f4c2622a1a3489988f2d85a81fdc132b17a92bddctguil@chromium.org SkEndian_SwapBE32(SkSetFourByteTag('t', 't', 'c', 'f')); 16860042b9c2a2e6fe954cdfbcd5a5b7449cdf41a4c3reed@google.com LOGFONT lf = fLogFont; 1687ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 1688ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com HDC hdc = ::CreateCompatibleDC(NULL); 168959d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com HFONT font = CreateFontIndirect(&lf); 1690ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com HFONT savefont = (HFONT)SelectObject(hdc, font); 1691ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 1692d604481f7a2587f5b400d2a0a68a6491a0d584c7vandebo@chromium.org SkMemoryStream* stream = NULL; 1693d604481f7a2587f5b400d2a0a68a6491a0d584c7vandebo@chromium.org DWORD tables[2] = {kTTCTag, 0}; 1694d604481f7a2587f5b400d2a0a68a6491a0d584c7vandebo@chromium.org for (int i = 0; i < SK_ARRAY_COUNT(tables); i++) { 1695d604481f7a2587f5b400d2a0a68a6491a0d584c7vandebo@chromium.org size_t bufferSize = GetFontData(hdc, tables[i], 0, NULL, 0); 169639698b1bd71fd54c7c44ae8d7224afdaf93c0ddabungeman@google.com if (bufferSize == GDI_ERROR) { 1697055180cb9c47c87e5ee8c9fa6d3f6a6079ad6f35reed@google.com call_ensure_accessible(lf); 169839698b1bd71fd54c7c44ae8d7224afdaf93c0ddabungeman@google.com bufferSize = GetFontData(hdc, tables[i], 0, NULL, 0); 169939698b1bd71fd54c7c44ae8d7224afdaf93c0ddabungeman@google.com } 1700d604481f7a2587f5b400d2a0a68a6491a0d584c7vandebo@chromium.org if (bufferSize != GDI_ERROR) { 1701d604481f7a2587f5b400d2a0a68a6491a0d584c7vandebo@chromium.org stream = new SkMemoryStream(bufferSize); 1702d604481f7a2587f5b400d2a0a68a6491a0d584c7vandebo@chromium.org if (GetFontData(hdc, tables[i], 0, (void*)stream->getMemoryBase(), 1703d604481f7a2587f5b400d2a0a68a6491a0d584c7vandebo@chromium.org bufferSize)) { 1704d604481f7a2587f5b400d2a0a68a6491a0d584c7vandebo@chromium.org break; 1705d604481f7a2587f5b400d2a0a68a6491a0d584c7vandebo@chromium.org } else { 1706d604481f7a2587f5b400d2a0a68a6491a0d584c7vandebo@chromium.org delete stream; 1707d604481f7a2587f5b400d2a0a68a6491a0d584c7vandebo@chromium.org stream = NULL; 1708d604481f7a2587f5b400d2a0a68a6491a0d584c7vandebo@chromium.org } 1709d604481f7a2587f5b400d2a0a68a6491a0d584c7vandebo@chromium.org } 1710ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } 1711ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 1712ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com SelectObject(hdc, savefont); 1713ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com DeleteObject(font); 1714ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com DeleteDC(hdc); 1715ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 1716ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com return stream; 1717ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com} 1718ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 17197bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.comint LogFontTypeface::onCountGlyphs() const { 17207bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com HDC hdc = ::CreateCompatibleDC(NULL); 17217bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com HFONT font = CreateFontIndirect(&fLogFont); 17227bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com HFONT savefont = (HFONT)SelectObject(hdc, font); 17237bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com 17247bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com unsigned int glyphCount = calculateGlyphCount(hdc, fLogFont); 17257bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com 17267bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com SelectObject(hdc, savefont); 17277bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com DeleteObject(font); 17287bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com DeleteDC(hdc); 17297bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com 17307bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com return glyphCount; 17317bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com} 17327bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com 17337bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.comint LogFontTypeface::onGetUPEM() const { 17347bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com HDC hdc = ::CreateCompatibleDC(NULL); 17357bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com HFONT font = CreateFontIndirect(&fLogFont); 17367bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com HFONT savefont = (HFONT)SelectObject(hdc, font); 17377bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com 17387bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com unsigned int upem = calculateUPEM(hdc, fLogFont); 17397bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com 17407bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com SelectObject(hdc, savefont); 17417bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com DeleteObject(font); 17427bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com DeleteDC(hdc); 17437bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com 17447bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com return upem; 17457bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com} 17467bdd614a1940935d3badeb54f7aae75d76ea830dbungeman@google.com 17470da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.comSkScalerContext* LogFontTypeface::onCreateScalerContext(const SkDescriptor* desc) const { 174884e22d847fc84727bc220947162363ee1fe068fcreed@google.com SkScalerContext_Windows* ctx = SkNEW_ARGS(SkScalerContext_Windows, 174984e22d847fc84727bc220947162363ee1fe068fcreed@google.com (const_cast<LogFontTypeface*>(this), desc)); 175084e22d847fc84727bc220947162363ee1fe068fcreed@google.com if (!ctx->isValid()) { 175184e22d847fc84727bc220947162363ee1fe068fcreed@google.com SkDELETE(ctx); 175284e22d847fc84727bc220947162363ee1fe068fcreed@google.com ctx = NULL; 175384e22d847fc84727bc220947162363ee1fe068fcreed@google.com } 175484e22d847fc84727bc220947162363ee1fe068fcreed@google.com return ctx; 1755ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com} 1756ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 1757ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com/** Return the closest matching typeface given either an existing family 1758ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com (specified by a typeface in that family) or by a familyName, and a 1759ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com requested style. 176090d812b77ab025d5fd01dab904287f5c5bf56228bungeman@google.com 1) If familyFace is null, use familyName. 176190d812b77ab025d5fd01dab904287f5c5bf56228bungeman@google.com 2) If familyName is null, use familyFace. 1762ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 3) If both are null, return the default font that best matches style 1763ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com This MUST not return NULL. 1764ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com */ 1765ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 1766ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.comSkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace, 1767ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com const char familyName[], 1768ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com SkTypeface::Style style) { 176959d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com LOGFONT lf; 1770ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com if (NULL == familyFace && NULL == familyName) { 177159d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com lf = get_default_font(); 177259d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com } else if (familyFace) { 177359d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com LogFontTypeface* face = (LogFontTypeface*)familyFace; 177459d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com lf = face->fLogFont; 1775ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } else { 1776484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com logfont_for_name(familyName, &lf); 1777ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com } 177859d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com setStyle(&lf, style); 177959d2f63583512b47df579e80f1ae39c74fad5f3ereed@google.com return SkCreateTypefaceFromLOGFONT(lf); 1780ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com} 1781ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 1782ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.comSkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) { 1783f381162e5616daacdbcc06d693aca5111aeeebe8mike@reedtribe.org SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path)); 1784f381162e5616daacdbcc06d693aca5111aeeebe8mike@reedtribe.org return stream.get() ? CreateTypefaceFromStream(stream) : NULL; 1785ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com} 1786ac6b97972d3c5a8e10b79c1409818756310e0f12reed@google.com 17870da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.comvoid LogFontTypeface::onFilterRec(SkScalerContextRec* rec) const { 1788c5fd46171841711973b9433c726ff8608335940ccommit-bot@chromium.org if (rec->fFlags & SkScalerContext::kLCD_BGROrder_Flag || 1789c5fd46171841711973b9433c726ff8608335940ccommit-bot@chromium.org rec->fFlags & SkScalerContext::kLCD_Vertical_Flag) 1790c5fd46171841711973b9433c726ff8608335940ccommit-bot@chromium.org { 1791c5fd46171841711973b9433c726ff8608335940ccommit-bot@chromium.org rec->fMaskFormat = SkMask::kA8_Format; 1792c5fd46171841711973b9433c726ff8608335940ccommit-bot@chromium.org rec->fFlags |= SkScalerContext::kGenA8FromLCD_Flag; 1793c5fd46171841711973b9433c726ff8608335940ccommit-bot@chromium.org } 1794c5fd46171841711973b9433c726ff8608335940ccommit-bot@chromium.org 1795e8fab0111d11316a027bc6ae60c62cc6575cdc05reed@google.com unsigned flagsWeDontSupport = SkScalerContext::kDevKernText_Flag | 1796e8fab0111d11316a027bc6ae60c62cc6575cdc05reed@google.com SkScalerContext::kAutohinting_Flag | 1797e8fab0111d11316a027bc6ae60c62cc6575cdc05reed@google.com SkScalerContext::kEmbeddedBitmapText_Flag | 1798e8fab0111d11316a027bc6ae60c62cc6575cdc05reed@google.com SkScalerContext::kEmbolden_Flag | 1799c84547a8d3cb04f0547db282b34e26abfbe64ec3bungeman@google.com SkScalerContext::kSubpixelPositioning_Flag | 1800e8fab0111d11316a027bc6ae60c62cc6575cdc05reed@google.com SkScalerContext::kLCD_BGROrder_Flag | 1801e8fab0111d11316a027bc6ae60c62cc6575cdc05reed@google.com SkScalerContext::kLCD_Vertical_Flag; 1802e8fab0111d11316a027bc6ae60c62cc6575cdc05reed@google.com rec->fFlags &= ~flagsWeDontSupport; 1803e8fab0111d11316a027bc6ae60c62cc6575cdc05reed@google.com 1804e8fab0111d11316a027bc6ae60c62cc6575cdc05reed@google.com SkPaint::Hinting h = rec->getHinting(); 1805da44067ec97fddd3bab52da34e2fc5ddc5241c34reed@google.com 1806da44067ec97fddd3bab52da34e2fc5ddc5241c34reed@google.com // I think we can support no-hinting, if we get hires outlines and just 1807da44067ec97fddd3bab52da34e2fc5ddc5241c34reed@google.com // use skia to rasterize into a gray-scale mask... 1808da44067ec97fddd3bab52da34e2fc5ddc5241c34reed@google.com#if 0 1809e8fab0111d11316a027bc6ae60c62cc6575cdc05reed@google.com switch (h) { 1810e8fab0111d11316a027bc6ae60c62cc6575cdc05reed@google.com case SkPaint::kNo_Hinting: 1811e8fab0111d11316a027bc6ae60c62cc6575cdc05reed@google.com case SkPaint::kSlight_Hinting: 1812e8fab0111d11316a027bc6ae60c62cc6575cdc05reed@google.com h = SkPaint::kNo_Hinting; 1813e8fab0111d11316a027bc6ae60c62cc6575cdc05reed@google.com break; 1814e8fab0111d11316a027bc6ae60c62cc6575cdc05reed@google.com case SkPaint::kNormal_Hinting: 1815e8fab0111d11316a027bc6ae60c62cc6575cdc05reed@google.com case SkPaint::kFull_Hinting: 1816e8fab0111d11316a027bc6ae60c62cc6575cdc05reed@google.com h = SkPaint::kNormal_Hinting; 1817e8fab0111d11316a027bc6ae60c62cc6575cdc05reed@google.com break; 1818e8fab0111d11316a027bc6ae60c62cc6575cdc05reed@google.com default: 18190c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("unknown hinting"); 1820e8fab0111d11316a027bc6ae60c62cc6575cdc05reed@google.com } 1821da44067ec97fddd3bab52da34e2fc5ddc5241c34reed@google.com#else 1822da44067ec97fddd3bab52da34e2fc5ddc5241c34reed@google.com h = SkPaint::kNormal_Hinting; 1823da44067ec97fddd3bab52da34e2fc5ddc5241c34reed@google.com#endif 1824e8fab0111d11316a027bc6ae60c62cc6575cdc05reed@google.com rec->setHinting(h); 1825da44067ec97fddd3bab52da34e2fc5ddc5241c34reed@google.com 18269181aa84aa288d2bc3ab079b6b40a79ac87d8807reed@google.com// turn this off since GDI might turn A8 into BW! Need a bigger fix. 18279181aa84aa288d2bc3ab079b6b40a79ac87d8807reed@google.com#if 0 1828da44067ec97fddd3bab52da34e2fc5ddc5241c34reed@google.com // Disable LCD when rotated, since GDI's output is ugly 1829da44067ec97fddd3bab52da34e2fc5ddc5241c34reed@google.com if (isLCD(*rec) && !isAxisAligned(*rec)) { 1830da44067ec97fddd3bab52da34e2fc5ddc5241c34reed@google.com rec->fMaskFormat = SkMask::kA8_Format; 1831da44067ec97fddd3bab52da34e2fc5ddc5241c34reed@google.com } 18329181aa84aa288d2bc3ab079b6b40a79ac87d8807reed@google.com#endif 1833754e4ebd10d7353ce55be7dfe0a417e502ef4047reed@google.com 18340da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com if (!fCanBeLCD && isLCD(*rec)) { 1835cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com rec->fMaskFormat = SkMask::kA8_Format; 1836cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com rec->fFlags &= ~SkScalerContext::kGenA8FromLCD_Flag; 1837754e4ebd10d7353ce55be7dfe0a417e502ef4047reed@google.com } 1838754e4ebd10d7353ce55be7dfe0a417e502ef4047reed@google.com} 1839070da5edcb1c6e9b9507f06a5e2c270e1c1fd796reed@google.com 1840070da5edcb1c6e9b9507f06a5e2c270e1c1fd796reed@google.com/////////////////////////////////////////////////////////////////////////////// 1841070da5edcb1c6e9b9507f06a5e2c270e1c1fd796reed@google.com 1842070da5edcb1c6e9b9507f06a5e2c270e1c1fd796reed@google.com#include "SkFontMgr.h" 1843484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com#include "SkDataTable.h" 1844484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com 1845484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.comstatic bool valid_logfont_for_enum(const LOGFONT& lf, DWORD fontType) { 1846484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com return TRUETYPE_FONTTYPE == fontType 1847484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com && lf.lfFaceName[0] 1848484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com && lf.lfFaceName[0] != '@' 1849484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com && OUT_STROKE_PRECIS == lf.lfOutPrecision 1850484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com // without the chraset check, we got LOTS of dups of the same font 1851484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com // is there a better check (other than searching the array for 1852484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com // the same name? 1853484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com && 0 == lf.lfCharSet 1854484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com ; 1855484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com} 1856484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com 1857484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.comstatic int CALLBACK enum_fonts_proc(const LOGFONT* lf, const TEXTMETRIC*, 1858484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com DWORD fontType, LPARAM builderParam) { 1859484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com if (valid_logfont_for_enum(*lf, fontType)) { 1860a65a681d43a8e9f5d8726a389832e957b07ee16breed@google.com SkTDArray<ENUMLOGFONTEX>* array = (SkTDArray<ENUMLOGFONTEX>*)builderParam; 1861a65a681d43a8e9f5d8726a389832e957b07ee16breed@google.com *array->append() = *(ENUMLOGFONTEX*)lf; 1862484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com } 1863484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com return 1; // non-zero means continue 1864484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com} 1865484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com 1866484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.comstatic SkFontStyle compute_fontstyle(const LOGFONT& lf) { 1867484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com return SkFontStyle(lf.lfWeight, SkFontStyle::kNormal_Width, 1868484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com lf.lfItalic ? SkFontStyle::kItalic_Slant 1869484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com : SkFontStyle::kUpright_Slant); 1870484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com} 1871484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com 1872484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.comclass SkFontStyleSetGDI : public SkFontStyleSet { 1873484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.compublic: 1874a65a681d43a8e9f5d8726a389832e957b07ee16breed@google.com SkFontStyleSetGDI(const TCHAR familyName[]) { 1875484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com HDC hdc = ::CreateCompatibleDC(NULL); 1876a65a681d43a8e9f5d8726a389832e957b07ee16breed@google.com ::EnumFonts(hdc, familyName, enum_fonts_proc, (LPARAM)&fArray); 1877484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com ::DeleteDC(hdc); 1878484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com } 1879484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com 1880484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com virtual int count() SK_OVERRIDE { 1881484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com return fArray.count(); 1882484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com } 1883484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com 1884484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com virtual void getStyle(int index, SkFontStyle* fs, SkString* styleName) SK_OVERRIDE { 1885484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com if (fs) { 1886a65a681d43a8e9f5d8726a389832e957b07ee16breed@google.com *fs = compute_fontstyle(fArray[index].elfLogFont); 1887a65a681d43a8e9f5d8726a389832e957b07ee16breed@google.com } 1888a65a681d43a8e9f5d8726a389832e957b07ee16breed@google.com if (styleName) { 1889a65a681d43a8e9f5d8726a389832e957b07ee16breed@google.com const ENUMLOGFONTEX& ref = fArray[index]; 1890a65a681d43a8e9f5d8726a389832e957b07ee16breed@google.com // For some reason, ENUMLOGFONTEX and LOGFONT disagree on their type in the 1891a65a681d43a8e9f5d8726a389832e957b07ee16breed@google.com // non-unicode version. 1892a65a681d43a8e9f5d8726a389832e957b07ee16breed@google.com // ENUMLOGFONTEX uses BYTE 1893a65a681d43a8e9f5d8726a389832e957b07ee16breed@google.com // LOGFONT uses CHAR 1894a65a681d43a8e9f5d8726a389832e957b07ee16breed@google.com // Here we assert they that the style name is logically the same (size) as 1895a65a681d43a8e9f5d8726a389832e957b07ee16breed@google.com // a TCHAR, so we can use the same converter function. 1896a65a681d43a8e9f5d8726a389832e957b07ee16breed@google.com SkASSERT(sizeof(TCHAR) == sizeof(ref.elfStyle[0])); 1897a65a681d43a8e9f5d8726a389832e957b07ee16breed@google.com tchar_to_skstring((const TCHAR*)ref.elfStyle, styleName); 1898484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com } 1899484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com } 1900484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com 1901484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com virtual SkTypeface* createTypeface(int index) SK_OVERRIDE { 1902a65a681d43a8e9f5d8726a389832e957b07ee16breed@google.com return SkCreateTypefaceFromLOGFONT(fArray[index].elfLogFont); 1903484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com } 1904484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com 1905484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE { 1906484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com // todo: 1907a65a681d43a8e9f5d8726a389832e957b07ee16breed@google.com return SkCreateTypefaceFromLOGFONT(fArray[0].elfLogFont); 1908484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com } 1909484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com 1910484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.comprivate: 1911a65a681d43a8e9f5d8726a389832e957b07ee16breed@google.com SkTDArray<ENUMLOGFONTEX> fArray; 1912484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com}; 1913484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com 1914484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.comstatic int CALLBACK enum_family_proc(const LOGFONT* lf, const TEXTMETRIC* tm, 1915484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com DWORD fontType, LPARAM builderParam) { 1916484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com if (valid_logfont_for_enum(*lf, fontType)) { 1917a65a681d43a8e9f5d8726a389832e957b07ee16breed@google.com SkTDArray<ENUMLOGFONTEX>* array = (SkTDArray<ENUMLOGFONTEX>*)builderParam; 1918a65a681d43a8e9f5d8726a389832e957b07ee16breed@google.com *array->append() = *(ENUMLOGFONTEX*)lf; 1919484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com#if 0 1920484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com SkString str; 1921484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com tchar_to_skstring(lf->lfFaceName, &str); 1922484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com SkDebugf("fam:%s height:%d width:%d esc:%d orien:%d weight:%d ital:%d char:%d clip:%d qual:%d pitch:%d\n", 1923484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com str.c_str(), lf->lfHeight, lf->lfWidth, lf->lfEscapement, lf->lfOrientation, 1924484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com lf->lfWeight, lf->lfItalic, lf->lfCharSet, lf->lfClipPrecision, lf->lfQuality, 1925484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com lf->lfPitchAndFamily); 1926484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com#endif 1927484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com } 1928484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com return 1; // non-zero means continue 1929484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com} 1930484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com 1931484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.comclass SkFontMgrGDI : public SkFontMgr { 1932484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com void init() { 1933484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com if (!fLogFontArray.isEmpty()) { 1934484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com return; 1935484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com } 1936484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com 1937484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com LOGFONT lf; 1938484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com sk_bzero(&lf, sizeof(lf)); 1939484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com lf.lfCharSet = DEFAULT_CHARSET; 1940484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com 1941484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com HDC hdc = ::CreateCompatibleDC(NULL); 1942484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com ::EnumFontFamiliesEx(hdc, &lf, enum_family_proc, (LPARAM)&fLogFontArray, 0); 1943484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com ::DeleteDC(hdc); 1944484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com } 1945484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com 1946484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.compublic: 1947484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com SkFontMgrGDI() {} 1948484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com 1949484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.comprotected: 1950484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com virtual int onCountFamilies() SK_OVERRIDE { 1951484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com this->init(); 1952484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com return fLogFontArray.count(); 1953484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com } 1954484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com 1955484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com virtual void onGetFamilyName(int index, SkString* familyName) SK_OVERRIDE { 1956484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com this->init(); 1957484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com SkASSERT((unsigned)index < (unsigned)fLogFontArray.count()); 1958a65a681d43a8e9f5d8726a389832e957b07ee16breed@google.com tchar_to_skstring(fLogFontArray[index].elfLogFont.lfFaceName, familyName); 1959484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com } 1960484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com 1961484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com virtual SkFontStyleSet* onCreateStyleSet(int index) SK_OVERRIDE { 1962484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com this->init(); 1963484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com SkASSERT((unsigned)index < (unsigned)fLogFontArray.count()); 1964a65a681d43a8e9f5d8726a389832e957b07ee16breed@google.com return SkNEW_ARGS(SkFontStyleSetGDI, (fLogFontArray[index].elfLogFont.lfFaceName)); 1965484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com } 1966484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com 1967484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com virtual SkFontStyleSet* onMatchFamily(const char familyName[]) SK_OVERRIDE { 1968484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com if (NULL == familyName) { 1969484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com familyName = ""; // do we need this check??? 1970484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com } 1971484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com LOGFONT lf; 1972484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com logfont_for_name(familyName, &lf); 1973a65a681d43a8e9f5d8726a389832e957b07ee16breed@google.com return SkNEW_ARGS(SkFontStyleSetGDI, (lf.lfFaceName)); 1974484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com } 1975484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com 1976484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com virtual SkTypeface* onMatchFamilyStyle(const char familyName[], 1977484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com const SkFontStyle& fontstyle) SK_OVERRIDE { 1978437eea160b2f605d9074106891288e85baaecfefreed@google.com // could be in base impl 1979484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName)); 1980484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com return sset->matchStyle(fontstyle); 1981484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com } 1982484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com 1983484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember, 1984484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com const SkFontStyle& fontstyle) SK_OVERRIDE { 1985437eea160b2f605d9074106891288e85baaecfefreed@google.com // could be in base impl 1986484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com SkString familyName; 1987484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com ((LogFontTypeface*)familyMember)->getFamilyName(&familyName); 1988484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com return this->matchFamilyStyle(familyName.c_str(), fontstyle); 1989484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com } 1990484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com 1991437eea160b2f605d9074106891288e85baaecfefreed@google.com virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) SK_OVERRIDE { 1992437eea160b2f605d9074106891288e85baaecfefreed@google.com return create_from_stream(stream); 1993484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com } 1994437eea160b2f605d9074106891288e85baaecfefreed@google.com 1995437eea160b2f605d9074106891288e85baaecfefreed@google.com virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) SK_OVERRIDE { 1996437eea160b2f605d9074106891288e85baaecfefreed@google.com // could be in base impl 1997437eea160b2f605d9074106891288e85baaecfefreed@google.com SkAutoTUnref<SkStream> stream(SkNEW_ARGS(SkMemoryStream, (data))); 1998437eea160b2f605d9074106891288e85baaecfefreed@google.com return this->createFromStream(stream); 1999484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com } 2000437eea160b2f605d9074106891288e85baaecfefreed@google.com 2001484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) SK_OVERRIDE { 2002437eea160b2f605d9074106891288e85baaecfefreed@google.com // could be in base impl 2003437eea160b2f605d9074106891288e85baaecfefreed@google.com SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path)); 2004437eea160b2f605d9074106891288e85baaecfefreed@google.com return this->createFromStream(stream); 2005484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com } 2006484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com 2007484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.comprivate: 2008a65a681d43a8e9f5d8726a389832e957b07ee16breed@google.com SkTDArray<ENUMLOGFONTEX> fLogFontArray; 2009484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com}; 2010070da5edcb1c6e9b9507f06a5e2c270e1c1fd796reed@google.com 2011070da5edcb1c6e9b9507f06a5e2c270e1c1fd796reed@google.comSkFontMgr* SkFontMgr::Factory() { 2012484f5bcf07c965e84cf021a6272aff73e2d7c1ecreed@google.com return SkNEW(SkFontMgrGDI); 2013070da5edcb1c6e9b9507f06a5e2c270e1c1fd796reed@google.com} 2014