1 /* 2 * Copyright 2014 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkTypes.h" 9 #if defined(SK_BUILD_FOR_WIN32) 10 11 // SkTypes will include Windows.h, which will pull in all of the GDI defines. 12 // GDI #defines GetGlyphIndices to GetGlyphIndicesA or GetGlyphIndicesW, but 13 // IDWriteFontFace has a method called GetGlyphIndices. Since this file does 14 // not use GDI, undefing GetGlyphIndices makes things less confusing. 15 #undef GetGlyphIndices 16 17 #include "SkDWrite.h" 18 #include "SkDWriteFontFileStream.h" 19 #include "SkFontDescriptor.h" 20 #include "SkFontStream.h" 21 #include "SkOTTable_head.h" 22 #include "SkOTTable_hhea.h" 23 #include "SkOTTable_OS_2.h" 24 #include "SkOTTable_post.h" 25 #include "SkOTUtils.h" 26 #include "SkScalerContext.h" 27 #include "SkScalerContext_win_dw.h" 28 #include "SkTypeface_win_dw.h" 29 #include "SkUtils.h" 30 31 void DWriteFontTypeface::onGetFamilyName(SkString* familyName) const { 32 SkTScopedComPtr<IDWriteLocalizedStrings> familyNames; 33 HRV(fDWriteFontFamily->GetFamilyNames(&familyNames)); 34 35 sk_get_locale_string(familyNames.get(), nullptr/*fMgr->fLocaleName.get()*/, familyName); 36 } 37 38 void DWriteFontTypeface::onGetFontDescriptor(SkFontDescriptor* desc, 39 bool* isLocalStream) const { 40 // Get the family name. 41 SkTScopedComPtr<IDWriteLocalizedStrings> familyNames; 42 HRV(fDWriteFontFamily->GetFamilyNames(&familyNames)); 43 44 SkString utf8FamilyName; 45 sk_get_locale_string(familyNames.get(), nullptr/*fMgr->fLocaleName.get()*/, &utf8FamilyName); 46 47 desc->setFamilyName(utf8FamilyName.c_str()); 48 *isLocalStream = SkToBool(fDWriteFontFileLoader.get()); 49 } 50 51 static SkUnichar next_utf8(const void** chars) { 52 return SkUTF8_NextUnichar((const char**)chars); 53 } 54 55 static SkUnichar next_utf16(const void** chars) { 56 return SkUTF16_NextUnichar((const uint16_t**)chars); 57 } 58 59 static SkUnichar next_utf32(const void** chars) { 60 const SkUnichar** uniChars = (const SkUnichar**)chars; 61 SkUnichar uni = **uniChars; 62 *uniChars += 1; 63 return uni; 64 } 65 66 typedef SkUnichar (*EncodingProc)(const void**); 67 68 static EncodingProc find_encoding_proc(SkTypeface::Encoding enc) { 69 static const EncodingProc gProcs[] = { 70 next_utf8, next_utf16, next_utf32 71 }; 72 SkASSERT((size_t)enc < SK_ARRAY_COUNT(gProcs)); 73 return gProcs[enc]; 74 } 75 76 int DWriteFontTypeface::onCharsToGlyphs(const void* chars, Encoding encoding, 77 uint16_t glyphs[], int glyphCount) const 78 { 79 if (nullptr == glyphs) { 80 EncodingProc next_ucs4_proc = find_encoding_proc(encoding); 81 for (int i = 0; i < glyphCount; ++i) { 82 const SkUnichar c = next_ucs4_proc(&chars); 83 BOOL exists; 84 fDWriteFont->HasCharacter(c, &exists); 85 if (!exists) { 86 return i; 87 } 88 } 89 return glyphCount; 90 } 91 92 switch (encoding) { 93 case SkTypeface::kUTF8_Encoding: 94 case SkTypeface::kUTF16_Encoding: { 95 static const int scratchCount = 256; 96 UINT32 scratch[scratchCount]; 97 EncodingProc next_ucs4_proc = find_encoding_proc(encoding); 98 for (int baseGlyph = 0; baseGlyph < glyphCount; baseGlyph += scratchCount) { 99 int glyphsLeft = glyphCount - baseGlyph; 100 int limit = SkTMin(glyphsLeft, scratchCount); 101 for (int i = 0; i < limit; ++i) { 102 scratch[i] = next_ucs4_proc(&chars); 103 } 104 fDWriteFontFace->GetGlyphIndices(scratch, limit, &glyphs[baseGlyph]); 105 } 106 break; 107 } 108 case SkTypeface::kUTF32_Encoding: { 109 const UINT32* utf32 = reinterpret_cast<const UINT32*>(chars); 110 fDWriteFontFace->GetGlyphIndices(utf32, glyphCount, glyphs); 111 break; 112 } 113 default: 114 SK_ABORT("Invalid Text Encoding"); 115 } 116 117 for (int i = 0; i < glyphCount; ++i) { 118 if (0 == glyphs[i]) { 119 return i; 120 } 121 } 122 return glyphCount; 123 } 124 125 int DWriteFontTypeface::onCountGlyphs() const { 126 return fDWriteFontFace->GetGlyphCount(); 127 } 128 129 int DWriteFontTypeface::onGetUPEM() const { 130 DWRITE_FONT_METRICS metrics; 131 fDWriteFontFace->GetMetrics(&metrics); 132 return metrics.designUnitsPerEm; 133 } 134 135 class LocalizedStrings_IDWriteLocalizedStrings : public SkTypeface::LocalizedStrings { 136 public: 137 /** Takes ownership of the IDWriteLocalizedStrings. */ 138 explicit LocalizedStrings_IDWriteLocalizedStrings(IDWriteLocalizedStrings* strings) 139 : fIndex(0), fStrings(strings) 140 { } 141 142 bool next(SkTypeface::LocalizedString* localizedString) override { 143 if (fIndex >= fStrings->GetCount()) { 144 return false; 145 } 146 147 // String 148 UINT32 stringLen; 149 HRBM(fStrings->GetStringLength(fIndex, &stringLen), "Could not get string length."); 150 151 SkSMallocWCHAR wString(stringLen+1); 152 HRBM(fStrings->GetString(fIndex, wString.get(), stringLen+1), "Could not get string."); 153 154 HRB(sk_wchar_to_skstring(wString.get(), stringLen, &localizedString->fString)); 155 156 // Locale 157 UINT32 localeLen; 158 HRBM(fStrings->GetLocaleNameLength(fIndex, &localeLen), "Could not get locale length."); 159 160 SkSMallocWCHAR wLocale(localeLen+1); 161 HRBM(fStrings->GetLocaleName(fIndex, wLocale.get(), localeLen+1), "Could not get locale."); 162 163 HRB(sk_wchar_to_skstring(wLocale.get(), localeLen, &localizedString->fLanguage)); 164 165 ++fIndex; 166 return true; 167 } 168 169 private: 170 UINT32 fIndex; 171 SkTScopedComPtr<IDWriteLocalizedStrings> fStrings; 172 }; 173 174 SkTypeface::LocalizedStrings* DWriteFontTypeface::onCreateFamilyNameIterator() const { 175 SkTypeface::LocalizedStrings* nameIter = 176 SkOTUtils::LocalizedStrings_NameTable::CreateForFamilyNames(*this); 177 if (nullptr == nameIter) { 178 SkTScopedComPtr<IDWriteLocalizedStrings> familyNames; 179 HRNM(fDWriteFontFamily->GetFamilyNames(&familyNames), "Could not obtain family names."); 180 nameIter = new LocalizedStrings_IDWriteLocalizedStrings(familyNames.release()); 181 } 182 return nameIter; 183 } 184 185 int DWriteFontTypeface::onGetTableTags(SkFontTableTag tags[]) const { 186 DWRITE_FONT_FACE_TYPE type = fDWriteFontFace->GetType(); 187 if (type != DWRITE_FONT_FACE_TYPE_CFF && 188 type != DWRITE_FONT_FACE_TYPE_TRUETYPE && 189 type != DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION) 190 { 191 return 0; 192 } 193 194 int ttcIndex; 195 SkAutoTDelete<SkStream> stream(this->openStream(&ttcIndex)); 196 return stream.get() ? SkFontStream::GetTableTags(stream, ttcIndex, tags) : 0; 197 } 198 199 size_t DWriteFontTypeface::onGetTableData(SkFontTableTag tag, size_t offset, 200 size_t length, void* data) const 201 { 202 AutoDWriteTable table(fDWriteFontFace.get(), SkEndian_SwapBE32(tag)); 203 if (!table.fExists) { 204 return 0; 205 } 206 207 if (offset > table.fSize) { 208 return 0; 209 } 210 size_t size = SkTMin(length, table.fSize - offset); 211 if (data) { 212 memcpy(data, table.fData + offset, size); 213 } 214 215 return size; 216 } 217 218 SkStreamAsset* DWriteFontTypeface::onOpenStream(int* ttcIndex) const { 219 *ttcIndex = fDWriteFontFace->GetIndex(); 220 221 UINT32 numFiles; 222 HRNM(fDWriteFontFace->GetFiles(&numFiles, nullptr), 223 "Could not get number of font files."); 224 if (numFiles != 1) { 225 return nullptr; 226 } 227 228 SkTScopedComPtr<IDWriteFontFile> fontFile; 229 HRNM(fDWriteFontFace->GetFiles(&numFiles, &fontFile), "Could not get font files."); 230 231 const void* fontFileKey; 232 UINT32 fontFileKeySize; 233 HRNM(fontFile->GetReferenceKey(&fontFileKey, &fontFileKeySize), 234 "Could not get font file reference key."); 235 236 SkTScopedComPtr<IDWriteFontFileLoader> fontFileLoader; 237 HRNM(fontFile->GetLoader(&fontFileLoader), "Could not get font file loader."); 238 239 SkTScopedComPtr<IDWriteFontFileStream> fontFileStream; 240 HRNM(fontFileLoader->CreateStreamFromKey(fontFileKey, fontFileKeySize, 241 &fontFileStream), 242 "Could not create font file stream."); 243 244 return new SkDWriteFontFileStream(fontFileStream.get()); 245 } 246 247 SkScalerContext* DWriteFontTypeface::onCreateScalerContext(const SkDescriptor* desc) const { 248 return new SkScalerContext_DW(const_cast<DWriteFontTypeface*>(this), desc); 249 } 250 251 void DWriteFontTypeface::onFilterRec(SkScalerContext::Rec* rec) const { 252 if (rec->fFlags & SkScalerContext::kLCD_Vertical_Flag) { 253 rec->fMaskFormat = SkMask::kA8_Format; 254 } 255 256 unsigned flagsWeDontSupport = SkScalerContext::kVertical_Flag | 257 SkScalerContext::kDevKernText_Flag | 258 SkScalerContext::kForceAutohinting_Flag | 259 SkScalerContext::kEmbolden_Flag | 260 SkScalerContext::kLCD_Vertical_Flag; 261 rec->fFlags &= ~flagsWeDontSupport; 262 263 SkPaint::Hinting h = rec->getHinting(); 264 // DirectWrite does not provide for hinting hints. 265 h = SkPaint::kSlight_Hinting; 266 rec->setHinting(h); 267 268 #if SK_FONT_HOST_USE_SYSTEM_SETTINGS 269 IDWriteFactory* factory = get_dwrite_factory(); 270 if (factory != nullptr) { 271 SkTScopedComPtr<IDWriteRenderingParams> defaultRenderingParams; 272 if (SUCCEEDED(factory->CreateRenderingParams(&defaultRenderingParams))) { 273 float gamma = defaultRenderingParams->GetGamma(); 274 rec->setDeviceGamma(gamma); 275 rec->setPaintGamma(gamma); 276 277 rec->setContrast(defaultRenderingParams->GetEnhancedContrast()); 278 } 279 } 280 #endif 281 } 282 283 /////////////////////////////////////////////////////////////////////////////// 284 //PDF Support 285 286 using namespace skia_advanced_typeface_metrics_utils; 287 288 // Construct Glyph to Unicode table. 289 // Unicode code points that require conjugate pairs in utf16 are not 290 // supported. 291 // TODO(bungeman): This never does what anyone wants. 292 // What is really wanted is the text to glyphs mapping 293 static void populate_glyph_to_unicode(IDWriteFontFace* fontFace, 294 const unsigned glyphCount, 295 SkTDArray<SkUnichar>* glyphToUnicode) { 296 //Do this like free type instead 297 SkAutoTMalloc<SkUnichar> glyphToUni(glyphCount); 298 int maxGlyph = -1; 299 for (UINT32 c = 0; c < 0x10FFFF; ++c) { 300 UINT16 glyph = 0; 301 HRVM(fontFace->GetGlyphIndices(&c, 1, &glyph), 302 "Failed to get glyph index."); 303 // Intermittent DW bug on Windows 10. See crbug.com/470146. 304 if (glyph >= glyphCount) { 305 return; 306 } 307 if (0 < glyph) { 308 maxGlyph = SkTMax(static_cast<int>(glyph), maxGlyph); 309 glyphToUni[glyph] = c; 310 } 311 } 312 313 SkTDArray<SkUnichar>(glyphToUni, maxGlyph + 1).swap(*glyphToUnicode); 314 } 315 316 static bool getWidthAdvance(IDWriteFontFace* fontFace, int gId, int16_t* advance) { 317 SkASSERT(advance); 318 319 UINT16 glyphId = gId; 320 DWRITE_GLYPH_METRICS gm; 321 HRESULT hr = fontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm); 322 323 if (FAILED(hr)) { 324 *advance = 0; 325 return false; 326 } 327 328 *advance = gm.advanceWidth; 329 return true; 330 } 331 332 SkAdvancedTypefaceMetrics* DWriteFontTypeface::onGetAdvancedTypefaceMetrics( 333 PerGlyphInfo perGlyphInfo, 334 const uint32_t* glyphIDs, 335 uint32_t glyphIDsCount) const { 336 337 SkAdvancedTypefaceMetrics* info = nullptr; 338 339 HRESULT hr = S_OK; 340 341 const unsigned glyphCount = fDWriteFontFace->GetGlyphCount(); 342 343 DWRITE_FONT_METRICS dwfm; 344 fDWriteFontFace->GetMetrics(&dwfm); 345 346 info = new SkAdvancedTypefaceMetrics; 347 info->fEmSize = dwfm.designUnitsPerEm; 348 info->fLastGlyphID = SkToU16(glyphCount - 1); 349 350 // SkAdvancedTypefaceMetrics::fFontName is in theory supposed to be 351 // the PostScript name of the font. However, due to the way it is currently 352 // used, it must actually be a family name. 353 SkTScopedComPtr<IDWriteLocalizedStrings> familyNames; 354 hr = fDWriteFontFamily->GetFamilyNames(&familyNames); 355 356 UINT32 familyNameLen; 357 hr = familyNames->GetStringLength(0, &familyNameLen); 358 359 SkSMallocWCHAR familyName(familyNameLen+1); 360 hr = familyNames->GetString(0, familyName.get(), familyNameLen+1); 361 362 hr = sk_wchar_to_skstring(familyName.get(), familyNameLen, &info->fFontName); 363 364 if (perGlyphInfo & kToUnicode_PerGlyphInfo) { 365 populate_glyph_to_unicode(fDWriteFontFace.get(), glyphCount, &(info->fGlyphToUnicode)); 366 } 367 368 DWRITE_FONT_FACE_TYPE fontType = fDWriteFontFace->GetType(); 369 if (fontType == DWRITE_FONT_FACE_TYPE_TRUETYPE || 370 fontType == DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION) { 371 info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font; 372 } else { 373 info->fAscent = dwfm.ascent; 374 info->fDescent = dwfm.descent; 375 info->fCapHeight = dwfm.capHeight; 376 return info; 377 } 378 379 AutoTDWriteTable<SkOTTableHead> headTable(fDWriteFontFace.get()); 380 AutoTDWriteTable<SkOTTablePostScript> postTable(fDWriteFontFace.get()); 381 AutoTDWriteTable<SkOTTableHorizontalHeader> hheaTable(fDWriteFontFace.get()); 382 AutoTDWriteTable<SkOTTableOS2> os2Table(fDWriteFontFace.get()); 383 if (!headTable.fExists || !postTable.fExists || !hheaTable.fExists || !os2Table.fExists) { 384 info->fAscent = dwfm.ascent; 385 info->fDescent = dwfm.descent; 386 info->fCapHeight = dwfm.capHeight; 387 return info; 388 } 389 390 //There exist CJK fonts which set the IsFixedPitch and Monospace bits, 391 //but have full width, latin half-width, and half-width kana. 392 bool fixedWidth = (postTable->isFixedPitch && 393 (1 == SkEndian_SwapBE16(hheaTable->numberOfHMetrics))); 394 //Monospace 395 if (fixedWidth) { 396 info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style; 397 } 398 //Italic 399 if (os2Table->version.v0.fsSelection.field.Italic) { 400 info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style; 401 } 402 //Script 403 if (SkPanose::FamilyType::Script == os2Table->version.v0.panose.bFamilyType.value) { 404 info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style; 405 //Serif 406 } else if (SkPanose::FamilyType::TextAndDisplay == os2Table->version.v0.panose.bFamilyType.value && 407 SkPanose::Data::TextAndDisplay::SerifStyle::Triangle <= os2Table->version.v0.panose.data.textAndDisplay.bSerifStyle.value && 408 SkPanose::Data::TextAndDisplay::SerifStyle::NoFit != os2Table->version.v0.panose.data.textAndDisplay.bSerifStyle.value) { 409 info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style; 410 } 411 412 info->fItalicAngle = SkEndian_SwapBE32(postTable->italicAngle) >> 16; 413 414 info->fAscent = SkToS16(dwfm.ascent); 415 info->fDescent = SkToS16(dwfm.descent); 416 info->fCapHeight = SkToS16(dwfm.capHeight); 417 418 info->fBBox = SkIRect::MakeLTRB((int32_t)SkEndian_SwapBE16((uint16_t)headTable->xMin), 419 (int32_t)SkEndian_SwapBE16((uint16_t)headTable->yMax), 420 (int32_t)SkEndian_SwapBE16((uint16_t)headTable->xMax), 421 (int32_t)SkEndian_SwapBE16((uint16_t)headTable->yMin)); 422 423 //TODO: is this even desired? It seems PDF only wants this value for Type1 424 //fonts, and we only get here for TrueType fonts. 425 info->fStemV = 0; 426 /* 427 // Figure out a good guess for StemV - Min width of i, I, !, 1. 428 // This probably isn't very good with an italic font. 429 int16_t min_width = SHRT_MAX; 430 info->fStemV = 0; 431 char stem_chars[] = {'i', 'I', '!', '1'}; 432 for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) { 433 ABC abcWidths; 434 if (GetCharABCWidths(hdc, stem_chars[i], stem_chars[i], &abcWidths)) { 435 int16_t width = abcWidths.abcB; 436 if (width > 0 && width < min_width) { 437 min_width = width; 438 info->fStemV = min_width; 439 } 440 } 441 } 442 */ 443 444 if (perGlyphInfo & kHAdvance_PerGlyphInfo) { 445 if (fixedWidth) { 446 appendRange(&info->fGlyphWidths, 0); 447 int16_t advance; 448 getWidthAdvance(fDWriteFontFace.get(), 1, &advance); 449 info->fGlyphWidths->fAdvance.append(1, &advance); 450 finishRange(info->fGlyphWidths.get(), 0, 451 SkAdvancedTypefaceMetrics::WidthRange::kDefault); 452 } else { 453 info->fGlyphWidths.reset( 454 getAdvanceData(fDWriteFontFace.get(), 455 glyphCount, 456 glyphIDs, 457 glyphIDsCount, 458 getWidthAdvance)); 459 } 460 } 461 462 return info; 463 } 464 #endif//defined(SK_BUILD_FOR_WIN32) 465