1e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com/* 2e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com * Copyright 2011 Google Inc. 3e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com * 4e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com * Use of this source code is governed by a BSD-style license that can be 5e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com * found in the LICENSE file. 6e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com */ 7e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 8e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com#include "SkTypes.h" 98f11d4dcafef4447fa68ea0ab28a72589241e9fdMike Klein#if defined(SK_BUILD_FOR_WIN) 101ee76510f5dbf632d30975fc3509ef4f609156d2mtklein 11e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com#undef GetGlyphIndices 12e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 13c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin#include "SkDraw.h" 1472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkDWrite.h" 15e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com#include "SkDWriteGeometrySink.h" 16e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com#include "SkEndian.h" 17e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com#include "SkGlyph.h" 18e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com#include "SkHRESULT.h" 19e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com#include "SkMaskGamma.h" 20058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com#include "SkMatrix22.h" 21c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb#include "SkMutex.h" 22058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com#include "SkOTTable_EBLC.h" 23058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com#include "SkOTTable_EBSC.h" 24740c3f17f7f37fca5268b60a83448953f075d8d1bungeman#include "SkOTTable_gasp.h" 25761b2509d59787a8920b2e98911cff9f88e0eb4ebungeman#include "SkOTTable_maxp.h" 26e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com#include "SkPath.h" 27c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin#include "SkRasterClip.h" 2851daa25a2b16bca578e78b7ea1e5815b9abb8b0bbungeman#include "SkScalerContext.h" 2951daa25a2b16bca578e78b7ea1e5815b9abb8b0bbungeman#include "SkScalerContext_win_dw.h" 306440f0b09ede274f93131eebb3ef49e73dfb2b9cherb#include "SkSharedMutex.h" 31e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com#include "SkTScopedComPtr.h" 3251daa25a2b16bca578e78b7ea1e5815b9abb8b0bbungeman#include "SkTypeface_win_dw.h" 33e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 34e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com#include <dwrite.h> 35e0c9e00cd5ed17a45a988b8b57fa9c09f3574921Ben Wagner#include <dwrite_1.h> 36e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 37c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb/* Note: 38c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb * In versions 8 and 8.1 of Windows, some calls in DWrite are not thread safe. 39c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb * The DWriteFactoryMutex protects the calls that are problematic. 40c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb */ 416440f0b09ede274f93131eebb3ef49e73dfb2b9cherbstatic SkSharedMutex DWriteFactoryMutex; 42c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb 436440f0b09ede274f93131eebb3ef49e73dfb2b9cherbtypedef SkAutoSharedMutexShared Shared; 44c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb 453e45a2f48ed8dbf3a55e980c43d97d29afeb93a0Ben Wagnerstatic bool isLCD(const SkScalerContextRec& rec) { 46d54d3fc82456f8789b3e4dff40faeb7b670bcf4breed return SkMask::kLCD16_Format == rec.fMaskFormat; 47e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com} 48e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 499f591347e902aa0c59a5da2915d829ae162831f4Ben Wagnerstatic bool is_hinted(DWriteFontTypeface* typeface) { 50f10637f2795b147751ef413237389d230b869360mtklein SkAutoExclusive l(DWriteFactoryMutex); 51761b2509d59787a8920b2e98911cff9f88e0eb4ebungeman AutoTDWriteTable<SkOTTableMaximumProfile> maxp(typeface->fDWriteFontFace.get()); 52761b2509d59787a8920b2e98911cff9f88e0eb4ebungeman if (!maxp.fExists) { 53761b2509d59787a8920b2e98911cff9f88e0eb4ebungeman return false; 54761b2509d59787a8920b2e98911cff9f88e0eb4ebungeman } 55761b2509d59787a8920b2e98911cff9f88e0eb4ebungeman if (maxp.fSize < sizeof(SkOTTableMaximumProfile::Version::TT)) { 56761b2509d59787a8920b2e98911cff9f88e0eb4ebungeman return false; 57761b2509d59787a8920b2e98911cff9f88e0eb4ebungeman } 58761b2509d59787a8920b2e98911cff9f88e0eb4ebungeman if (maxp->version.version != SkOTTableMaximumProfile::Version::TT::VERSION) { 59761b2509d59787a8920b2e98911cff9f88e0eb4ebungeman return false; 60761b2509d59787a8920b2e98911cff9f88e0eb4ebungeman } 619f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner return (0 != maxp->version.tt.maxSizeOfInstructions); 62761b2509d59787a8920b2e98911cff9f88e0eb4ebungeman} 63761b2509d59787a8920b2e98911cff9f88e0eb4ebungeman 6422253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner/** A GaspRange is inclusive, [min, max]. */ 6522253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagnerstruct GaspRange { 6622253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner using Behavior = SkOTTableGridAndScanProcedure::GaspRange::behavior; 6742a2a20b9114c904ce73d66d0105b81f19d93914Ben Wagner GaspRange(int min, int max, int version, Behavior flags) 6842a2a20b9114c904ce73d66d0105b81f19d93914Ben Wagner : fMin(min), fMax(max), fVersion(version), fFlags(flags) { } 6922253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner int fMin; 7022253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner int fMax; 7142a2a20b9114c904ce73d66d0105b81f19d93914Ben Wagner int fVersion; 7222253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner Behavior fFlags; 73740c3f17f7f37fca5268b60a83448953f075d8d1bungeman}; 74740c3f17f7f37fca5268b60a83448953f075d8d1bungeman 7522253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagnerbool get_gasp_range(DWriteFontTypeface* typeface, int size, GaspRange* range) { 76740c3f17f7f37fca5268b60a83448953f075d8d1bungeman AutoTDWriteTable<SkOTTableGridAndScanProcedure> gasp(typeface->fDWriteFontFace.get()); 77740c3f17f7f37fca5268b60a83448953f075d8d1bungeman if (!gasp.fExists) { 7822253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner return false; 79740c3f17f7f37fca5268b60a83448953f075d8d1bungeman } 80740c3f17f7f37fca5268b60a83448953f075d8d1bungeman if (gasp.fSize < sizeof(SkOTTableGridAndScanProcedure)) { 8122253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner return false; 82740c3f17f7f37fca5268b60a83448953f075d8d1bungeman } 83740c3f17f7f37fca5268b60a83448953f075d8d1bungeman if (gasp->version != SkOTTableGridAndScanProcedure::version0 && 84740c3f17f7f37fca5268b60a83448953f075d8d1bungeman gasp->version != SkOTTableGridAndScanProcedure::version1) 85740c3f17f7f37fca5268b60a83448953f075d8d1bungeman { 8622253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner return false; 87740c3f17f7f37fca5268b60a83448953f075d8d1bungeman } 88740c3f17f7f37fca5268b60a83448953f075d8d1bungeman 89740c3f17f7f37fca5268b60a83448953f075d8d1bungeman uint16_t numRanges = SkEndianSwap16(gasp->numRanges); 90740c3f17f7f37fca5268b60a83448953f075d8d1bungeman if (numRanges > 1024 || 91740c3f17f7f37fca5268b60a83448953f075d8d1bungeman gasp.fSize < sizeof(SkOTTableGridAndScanProcedure) + 9222253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner sizeof(SkOTTableGridAndScanProcedure::GaspRange) * numRanges) 93740c3f17f7f37fca5268b60a83448953f075d8d1bungeman { 9422253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner return false; 95740c3f17f7f37fca5268b60a83448953f075d8d1bungeman } 96740c3f17f7f37fca5268b60a83448953f075d8d1bungeman 97740c3f17f7f37fca5268b60a83448953f075d8d1bungeman const SkOTTableGridAndScanProcedure::GaspRange* rangeTable = 98740c3f17f7f37fca5268b60a83448953f075d8d1bungeman SkTAfter<const SkOTTableGridAndScanProcedure::GaspRange>(gasp.get()); 99740c3f17f7f37fca5268b60a83448953f075d8d1bungeman int minPPEM = -1; 100740c3f17f7f37fca5268b60a83448953f075d8d1bungeman for (uint16_t i = 0; i < numRanges; ++i, ++rangeTable) { 101740c3f17f7f37fca5268b60a83448953f075d8d1bungeman int maxPPEM = SkEndianSwap16(rangeTable->maxPPEM); 10222253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner if (minPPEM < size && size <= maxPPEM) { 10322253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner range->fMin = minPPEM + 1; 10422253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner range->fMax = maxPPEM; 10542a2a20b9114c904ce73d66d0105b81f19d93914Ben Wagner range->fVersion = SkEndian_SwapBE16(gasp->version); 10622253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner range->fFlags = rangeTable->flags; 10722253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner return true; 108740c3f17f7f37fca5268b60a83448953f075d8d1bungeman } 109740c3f17f7f37fca5268b60a83448953f075d8d1bungeman minPPEM = maxPPEM; 110740c3f17f7f37fca5268b60a83448953f075d8d1bungeman } 11122253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner return false; 11222253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner} 11322253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner/** If the rendering mode for the specified 'size' is gridfit, then place 11422253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner * the gridfit range into 'range'. Otherwise, leave 'range' alone. 11522253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner */ 11622253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagnerstatic bool is_gridfit_only(GaspRange::Behavior flags) { 11722253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner return flags.raw.value == GaspRange::Behavior::Raw::GridfitMask; 118740c3f17f7f37fca5268b60a83448953f075d8d1bungeman} 119740c3f17f7f37fca5268b60a83448953f075d8d1bungeman 12022253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagnerstatic bool has_bitmap_strike(DWriteFontTypeface* typeface, GaspRange range) { 121f10637f2795b147751ef413237389d230b869360mtklein SkAutoExclusive l(DWriteFactoryMutex); 122058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com { 123058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com AutoTDWriteTable<SkOTTableEmbeddedBitmapLocation> eblc(typeface->fDWriteFontFace.get()); 124058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com if (!eblc.fExists) { 125058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com return false; 126058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com } 127058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com if (eblc.fSize < sizeof(SkOTTableEmbeddedBitmapLocation)) { 128058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com return false; 129058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com } 130058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com if (eblc->version != SkOTTableEmbeddedBitmapLocation::version_initial) { 131058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com return false; 132058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com } 133058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 134058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com uint32_t numSizes = SkEndianSwap32(eblc->numSizes); 135740c3f17f7f37fca5268b60a83448953f075d8d1bungeman if (numSizes > 1024 || 136740c3f17f7f37fca5268b60a83448953f075d8d1bungeman eblc.fSize < sizeof(SkOTTableEmbeddedBitmapLocation) + 137058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com sizeof(SkOTTableEmbeddedBitmapLocation::BitmapSizeTable) * numSizes) 138058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com { 139058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com return false; 140058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com } 141058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 142058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com const SkOTTableEmbeddedBitmapLocation::BitmapSizeTable* sizeTable = 143058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com SkTAfter<const SkOTTableEmbeddedBitmapLocation::BitmapSizeTable>(eblc.get()); 144058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com for (uint32_t i = 0; i < numSizes; ++i, ++sizeTable) { 145740c3f17f7f37fca5268b60a83448953f075d8d1bungeman if (sizeTable->ppemX == sizeTable->ppemY && 14622253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner range.fMin <= sizeTable->ppemX && sizeTable->ppemX <= range.fMax) 147740c3f17f7f37fca5268b60a83448953f075d8d1bungeman { 148058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // TODO: determine if we should dig through IndexSubTableArray/IndexSubTable 149058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // to determine the actual number of glyphs with bitmaps. 150058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 151058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // TODO: Ensure that the bitmaps actually cover a significant portion of the strike. 152058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 153740c3f17f7f37fca5268b60a83448953f075d8d1bungeman // TODO: Ensure that the bitmaps are bi-level? 154058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com if (sizeTable->endGlyphIndex >= sizeTable->startGlyphIndex + 3) { 155058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com return true; 156058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com } 157058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com } 158058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com } 159058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com } 160058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 161058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com { 162058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com AutoTDWriteTable<SkOTTableEmbeddedBitmapScaling> ebsc(typeface->fDWriteFontFace.get()); 163058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com if (!ebsc.fExists) { 164058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com return false; 165058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com } 166058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com if (ebsc.fSize < sizeof(SkOTTableEmbeddedBitmapScaling)) { 167058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com return false; 168058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com } 169058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com if (ebsc->version != SkOTTableEmbeddedBitmapScaling::version_initial) { 170058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com return false; 171058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com } 172058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 173058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com uint32_t numSizes = SkEndianSwap32(ebsc->numSizes); 174740c3f17f7f37fca5268b60a83448953f075d8d1bungeman if (numSizes > 1024 || 175740c3f17f7f37fca5268b60a83448953f075d8d1bungeman ebsc.fSize < sizeof(SkOTTableEmbeddedBitmapScaling) + 176058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com sizeof(SkOTTableEmbeddedBitmapScaling::BitmapScaleTable) * numSizes) 177058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com { 178058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com return false; 179058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com } 180058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 181058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com const SkOTTableEmbeddedBitmapScaling::BitmapScaleTable* scaleTable = 182058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com SkTAfter<const SkOTTableEmbeddedBitmapScaling::BitmapScaleTable>(ebsc.get()); 183058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com for (uint32_t i = 0; i < numSizes; ++i, ++scaleTable) { 184740c3f17f7f37fca5268b60a83448953f075d8d1bungeman if (scaleTable->ppemX == scaleTable->ppemY && 18522253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner range.fMin <= scaleTable->ppemX && scaleTable->ppemX <= range.fMax) { 186058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // EBSC tables are normally only found in bitmap only fonts. 187058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com return true; 188058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com } 189058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com } 190058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com } 191058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 192058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com return false; 193058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com} 194058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 195740c3f17f7f37fca5268b60a83448953f075d8d1bungemanstatic bool both_zero(SkScalar a, SkScalar b) { 196058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com return 0 == a && 0 == b; 197058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com} 198058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 199058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com// returns false if there is any non-90-rotation or skew 2003e45a2f48ed8dbf3a55e980c43d97d29afeb93a0Ben Wagnerstatic bool is_axis_aligned(const SkScalerContextRec& rec) { 201058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com return 0 == rec.fPreSkewX && 202740c3f17f7f37fca5268b60a83448953f075d8d1bungeman (both_zero(rec.fPost2x2[0][1], rec.fPost2x2[1][0]) || 203740c3f17f7f37fca5268b60a83448953f075d8d1bungeman both_zero(rec.fPost2x2[0][0], rec.fPost2x2[1][1])); 204058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com} 205058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 2067cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungemanSkScalerContext_DW::SkScalerContext_DW(sk_sp<DWriteFontTypeface> typefaceRef, 207a9322c2d86aaef1085c267dfc43cf0747f170a86reed const SkScalerContextEffects& effects, 2086eddc77f6a0078570471277954c07d73b3a921d8bungeman@google.com const SkDescriptor* desc) 2097cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman : SkScalerContext(std::move(typefaceRef), effects, desc) 210e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com , fGlyphCount(-1) { 211e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 2127cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman DWriteFontTypeface* typeface = this->getDWriteTypeface(); 21322253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner fIsColorFont = typeface->fFactory2 && 21422253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner typeface->fDWriteFontFace2 && 21522253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner typeface->fDWriteFontFace2->IsColorFont(); 216c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin 21722253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner // In general, all glyphs should use NATURAL_SYMMETRIC 218058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // except when bi-level rendering is requested or there are embedded 219058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // bi-level bitmaps (and the embedded bitmap flag is set and no rotation). 220058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // 221058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // DirectWrite's IDWriteFontFace::GetRecommendedRenderingMode does not do 222058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // this. As a result, determine the actual size of the text and then see if 223058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // there are any embedded bi-level bitmaps of that size. If there are, then 224058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // force bitmaps by requesting bi-level rendering. 225058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // 226058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // FreeType allows for separate ppemX and ppemY, but DirectWrite assumes 227058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // square pixels and only uses ppemY. Therefore the transform must track any 228058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // non-uniform x-scale. 229058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // 230058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // Also, rotated glyphs should have the same absolute advance widths as 231058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // horizontal glyphs and the subpixel flag should not affect glyph shapes. 232058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 2335f14c5e038a16c80d50c2f87ae7c8775f977456cbungeman SkVector scale; 2341f5f6b823d32b1f85589e0cf81f8e7b91e89c1f2Ben Wagner fRec.computeMatrices(SkScalerContextRec::kVertical_PreMatrixScale, &scale, &fSkXform); 235058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 2365f14c5e038a16c80d50c2f87ae7c8775f977456cbungeman fXform.m11 = SkScalarToFloat(fSkXform.getScaleX()); 2375f14c5e038a16c80d50c2f87ae7c8775f977456cbungeman fXform.m12 = SkScalarToFloat(fSkXform.getSkewY()); 2385f14c5e038a16c80d50c2f87ae7c8775f977456cbungeman fXform.m21 = SkScalarToFloat(fSkXform.getSkewX()); 2395f14c5e038a16c80d50c2f87ae7c8775f977456cbungeman fXform.m22 = SkScalarToFloat(fSkXform.getScaleY()); 2405f14c5e038a16c80d50c2f87ae7c8775f977456cbungeman fXform.dx = 0; 2415f14c5e038a16c80d50c2f87ae7c8775f977456cbungeman fXform.dy = 0; 242058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 243058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // realTextSize is the actual device size we want (as opposed to the size the user requested). 244058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // gdiTextSize is the size we request when GDI compatible. 245058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // If the scale is negative, this means the matrix will do the flip anyway. 2465f14c5e038a16c80d50c2f87ae7c8775f977456cbungeman const SkScalar realTextSize = scale.fY; 247058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // Due to floating point math, the lower bits are suspect. Round carefully. 2487c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com SkScalar gdiTextSize = SkScalarRoundToScalar(realTextSize * 64.0f) / 64.0f; 249058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com if (gdiTextSize == 0) { 250058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com gdiTextSize = SK_Scalar1; 251058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com } 252058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 2537c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com bool bitmapRequested = SkToBool(fRec.fFlags & SkScalerContext::kEmbeddedBitmapText_Flag); 254740c3f17f7f37fca5268b60a83448953f075d8d1bungeman bool treatLikeBitmap = false; 2557c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com bool axisAlignedBitmap = false; 2567c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com if (bitmapRequested) { 257740c3f17f7f37fca5268b60a83448953f075d8d1bungeman // When embedded bitmaps are requested, treat the entire range like 258740c3f17f7f37fca5268b60a83448953f075d8d1bungeman // a bitmap strike if the range is gridfit only and contains a bitmap. 259740c3f17f7f37fca5268b60a83448953f075d8d1bungeman int bitmapPPEM = SkScalarTruncToInt(gdiTextSize); 26042a2a20b9114c904ce73d66d0105b81f19d93914Ben Wagner GaspRange range(bitmapPPEM, bitmapPPEM, 0, GaspRange::Behavior()); 26122253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner if (get_gasp_range(typeface, bitmapPPEM, &range)) { 26222253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner if (!is_gridfit_only(range.fFlags)) { 26342a2a20b9114c904ce73d66d0105b81f19d93914Ben Wagner range = GaspRange(bitmapPPEM, bitmapPPEM, 0, GaspRange::Behavior()); 26422253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner } 26522253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner } 266740c3f17f7f37fca5268b60a83448953f075d8d1bungeman treatLikeBitmap = has_bitmap_strike(typeface, range); 267740c3f17f7f37fca5268b60a83448953f075d8d1bungeman 268740c3f17f7f37fca5268b60a83448953f075d8d1bungeman axisAlignedBitmap = is_axis_aligned(fRec); 2697c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com } 270058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 27142a2a20b9114c904ce73d66d0105b81f19d93914Ben Wagner GaspRange range(0, 0xFFFF, 0, GaspRange::Behavior()); 2729f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner 2737c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com // If the user requested aliased, do so with aliased compatible metrics. 2747c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com if (SkMask::kBW_Format == fRec.fMaskFormat) { 275058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com fTextSizeRender = gdiTextSize; 276d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com fRenderingMode = DWRITE_RENDERING_MODE_ALIASED; 277d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com fTextureType = DWRITE_TEXTURE_ALIASED_1x1; 278058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com fTextSizeMeasure = gdiTextSize; 279058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com fMeasuringMode = DWRITE_MEASURING_MODE_GDI_CLASSIC; 280df1640d413c16abf4527960642aca41581808699bungeman 2817c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com // If we can use a bitmap, use gdi classic rendering and measurement. 2827c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com // This will not always provide a bitmap, but matches expected behavior. 283740c3f17f7f37fca5268b60a83448953f075d8d1bungeman } else if (treatLikeBitmap && axisAlignedBitmap) { 2847c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com fTextSizeRender = gdiTextSize; 28522253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner fRenderingMode = DWRITE_RENDERING_MODE_GDI_CLASSIC; 2867c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1; 2877c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com fTextSizeMeasure = gdiTextSize; 2887c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com fMeasuringMode = DWRITE_MEASURING_MODE_GDI_CLASSIC; 289df1640d413c16abf4527960642aca41581808699bungeman 2907c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com // If rotated but the horizontal text could have used a bitmap, 2917c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com // render high quality rotated glyphs but measure using bitmap metrics. 292740c3f17f7f37fca5268b60a83448953f075d8d1bungeman } else if (treatLikeBitmap) { 293058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com fTextSizeRender = gdiTextSize; 29422253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner fRenderingMode = DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC; 295058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1; 296058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com fTextSizeMeasure = gdiTextSize; 297d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com fMeasuringMode = DWRITE_MEASURING_MODE_GDI_CLASSIC; 2987c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com 29942a2a20b9114c904ce73d66d0105b81f19d93914Ben Wagner // If the font has a gasp table version 1, use it to determine symmetric rendering. 30042a2a20b9114c904ce73d66d0105b81f19d93914Ben Wagner } else if (get_gasp_range(typeface, SkScalarRoundToInt(gdiTextSize), &range) && 30142a2a20b9114c904ce73d66d0105b81f19d93914Ben Wagner range.fVersion >= 1) 30242a2a20b9114c904ce73d66d0105b81f19d93914Ben Wagner { 3039f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner fTextSizeRender = realTextSize; 3049f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner fRenderingMode = range.fFlags.field.SymmetricSmoothing 3059f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner ? DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC 3069f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner : DWRITE_RENDERING_MODE_NATURAL; 307761b2509d59787a8920b2e98911cff9f88e0eb4ebungeman fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1; 308761b2509d59787a8920b2e98911cff9f88e0eb4ebungeman fTextSizeMeasure = realTextSize; 309761b2509d59787a8920b2e98911cff9f88e0eb4ebungeman fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL; 310761b2509d59787a8920b2e98911cff9f88e0eb4ebungeman 3119f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner // If the requested size is above 20px or there are no bytecode hints, use symmetric rendering. 3129f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner } else if (realTextSize > SkIntToScalar(20) || !is_hinted(typeface)) { 313058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com fTextSizeRender = realTextSize; 3149f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner fRenderingMode = DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC; 3159f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1; 3169f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner fTextSizeMeasure = realTextSize; 3179f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL; 3189f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner 31942a2a20b9114c904ce73d66d0105b81f19d93914Ben Wagner // Fonts with hints, no gasp or gasp version 0, and below 20px get non-symmetric rendering. 32042a2a20b9114c904ce73d66d0105b81f19d93914Ben Wagner // Often such fonts have hints which were only tested with GDI ClearType classic. 32142a2a20b9114c904ce73d66d0105b81f19d93914Ben Wagner // Some of these fonts rely on drop out control in the y direction in order to be legible. 3229f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner // Tenor Sans 3239f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner // https://fonts.google.com/specimen/Tenor+Sans 3249f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner // Gill Sans W04 3259f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner // https://cdn.leagueoflegends.com/lolkit/1.1.9/resources/fonts/gill-sans-w04-book.woff 3269f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner // https://na.leagueoflegends.com/en/news/game-updates/patch/patch-410-notes 3279f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner // See https://crbug.com/385897 3289f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner } else { 3299f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner fTextSizeRender = gdiTextSize; 3309f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner fRenderingMode = DWRITE_RENDERING_MODE_NATURAL; 331d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1; 332058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com fTextSizeMeasure = realTextSize; 333d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL; 334d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com } 335d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com 33622253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner // DirectWrite2 allows for grayscale hinting. 33722253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner fAntiAliasMode = DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE; 33822253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner if (typeface->fFactory2 && typeface->fDWriteFontFace2 && 339e0a34e7dcddf68f0972805894f26c54869c3fabaBen Wagner SkMask::kA8_Format == fRec.fMaskFormat && 340e0a34e7dcddf68f0972805894f26c54869c3fabaBen Wagner !(fRec.fFlags & SkScalerContext::kGenA8FromLCD_Flag)) 34122253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner { 34222253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner // DWRITE_TEXTURE_ALIASED_1x1 is now misnamed, it must also be used with grayscale. 34322253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner fTextureType = DWRITE_TEXTURE_ALIASED_1x1; 34422253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner fAntiAliasMode = DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE; 34522253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner } 34622253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner 34722253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner // DirectWrite2 allows hinting to be disabled. 34822253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner fGridFitMode = DWRITE_GRID_FIT_MODE_ENABLED; 34922253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner if (fRec.getHinting() == SkPaint::kNo_Hinting) { 35022253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner fGridFitMode = DWRITE_GRID_FIT_MODE_DISABLED; 35122253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner if (fRenderingMode != DWRITE_RENDERING_MODE_ALIASED) { 35222253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner fRenderingMode = DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC; 35322253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner } 35422253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner } 35522253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner 356d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com if (this->isSubpixel()) { 357058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com fTextSizeMeasure = realTextSize; 358d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL; 359d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com } 360e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com} 361e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 36230ddd615c447fed73286151b463af20d309c85f1reed@google.comSkScalerContext_DW::~SkScalerContext_DW() { 363e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com} 364e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 36530ddd615c447fed73286151b463af20d309c85f1reed@google.comunsigned SkScalerContext_DW::generateGlyphCount() { 366e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com if (fGlyphCount < 0) { 3677cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman fGlyphCount = this->getDWriteTypeface()->fDWriteFontFace->GetGlyphCount(); 368e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 369e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com return fGlyphCount; 370e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com} 371e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 37230ddd615c447fed73286151b463af20d309c85f1reed@google.comuint16_t SkScalerContext_DW::generateCharToGlyph(SkUnichar uni) { 373e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com uint16_t index = 0; 3747cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman UINT32* uniPtr = reinterpret_cast<UINT32*>(&uni); 3757cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman this->getDWriteTypeface()->fDWriteFontFace->GetGlyphIndices(uniPtr, 1, &index); 376e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com return index; 377e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com} 378e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 37930ddd615c447fed73286151b463af20d309c85f1reed@google.comvoid SkScalerContext_DW::generateAdvance(SkGlyph* glyph) { 380e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com //Delta is the difference between the right/left side bearing metric 381e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com //and where the right/left side bearing ends up after hinting. 382e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com //DirectWrite does not provide this information. 383e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com glyph->fRsbDelta = 0; 384e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com glyph->fLsbDelta = 0; 385d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 386e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com glyph->fAdvanceX = 0; 387e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com glyph->fAdvanceY = 0; 388e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 389e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com uint16_t glyphId = glyph->getGlyphID(); 390e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com DWRITE_GLYPH_METRICS gm; 391d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com 392d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode || 393d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode) 394d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com { 395f10637f2795b147751ef413237389d230b869360mtklein SkAutoExclusive l(DWriteFactoryMutex); 3967cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman HRVM(this->getDWriteTypeface()->fDWriteFontFace->GetGdiCompatibleGlyphMetrics( 397058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com fTextSizeMeasure, 398d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com 1.0f, // pixelsPerDip 3991f5f6b823d32b1f85589e0cf81f8e7b91e89c1f2Ben Wagner // This parameter does not act like the lpmat2 parameter to GetGlyphOutlineW. 4001f5f6b823d32b1f85589e0cf81f8e7b91e89c1f2Ben Wagner // If it did then GsA here and G_inv below to mapVectors. 4011f5f6b823d32b1f85589e0cf81f8e7b91e89c1f2Ben Wagner nullptr, 402d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode, 403d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com &glyphId, 1, 404d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com &gm), 405d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com "Could not get gdi compatible glyph metrics."); 406d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com } else { 407f10637f2795b147751ef413237389d230b869360mtklein SkAutoExclusive l(DWriteFactoryMutex); 4087cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman HRVM(this->getDWriteTypeface()->fDWriteFontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm), 409d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com "Could not get design metrics."); 410d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com } 411e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 412e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com DWRITE_FONT_METRICS dwfm; 413c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb { 4146440f0b09ede274f93131eebb3ef49e73dfb2b9cherb Shared l(DWriteFactoryMutex); 4157cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman this->getDWriteTypeface()->fDWriteFontFace->GetMetrics(&dwfm); 416c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb } 4178be952ad8c9deefe19cff36f9ad217563400f817Mike Reed SkScalar advanceX = fTextSizeMeasure * gm.advanceWidth / dwfm.designUnitsPerEm; 418d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 4191f5f6b823d32b1f85589e0cf81f8e7b91e89c1f2Ben Wagner SkVector advance = { advanceX, 0 }; 420058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode || 421058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode) 422058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com { 423761b2509d59787a8920b2e98911cff9f88e0eb4ebungeman // DirectWrite produced 'compatible' metrics, but while close, 424761b2509d59787a8920b2e98911cff9f88e0eb4ebungeman // the end result is not always an integer as it would be with GDI. 4251f5f6b823d32b1f85589e0cf81f8e7b91e89c1f2Ben Wagner advance.fX = SkScalarRoundToScalar(advance.fX); 426058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com } 4271f5f6b823d32b1f85589e0cf81f8e7b91e89c1f2Ben Wagner fSkXform.mapVectors(&advance, 1); 428e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 4291f5f6b823d32b1f85589e0cf81f8e7b91e89c1f2Ben Wagner glyph->fAdvanceX = SkScalarToFloat(advance.fX); 4301f5f6b823d32b1f85589e0cf81f8e7b91e89c1f2Ben Wagner glyph->fAdvanceY = SkScalarToFloat(advance.fY); 431e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com} 432e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 433683a37692bc67ef1144922b73a1e871e7e1e842ebungemanHRESULT SkScalerContext_DW::getBoundingBox(SkGlyph* glyph, 434683a37692bc67ef1144922b73a1e871e7e1e842ebungeman DWRITE_RENDERING_MODE renderingMode, 435683a37692bc67ef1144922b73a1e871e7e1e842ebungeman DWRITE_TEXTURE_TYPE textureType, 436683a37692bc67ef1144922b73a1e871e7e1e842ebungeman RECT* bbox) 437b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner{ 438e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com //Measure raster size. 439e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com fXform.dx = SkFixedToFloat(glyph->getSubXFixed()); 440e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com fXform.dy = SkFixedToFloat(glyph->getSubYFixed()); 441e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 442e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com FLOAT advance = 0; 443e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 444e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com UINT16 glyphId = glyph->getGlyphID(); 445e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 446e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com DWRITE_GLYPH_OFFSET offset; 447e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com offset.advanceOffset = 0.0f; 448e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com offset.ascenderOffset = 0.0f; 449e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 450e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com DWRITE_GLYPH_RUN run; 451e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com run.glyphCount = 1; 452e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com run.glyphAdvances = &advance; 4537cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman run.fontFace = this->getDWriteTypeface()->fDWriteFontFace.get(); 454058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com run.fontEmSize = SkScalarToFloat(fTextSizeRender); 455e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com run.bidiLevel = 0; 456e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com run.glyphIndices = &glyphId; 457e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com run.isSideways = FALSE; 458e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com run.glyphOffsets = &offset; 4596440f0b09ede274f93131eebb3ef49e73dfb2b9cherb 4606440f0b09ede274f93131eebb3ef49e73dfb2b9cherb SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis; 461c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb { 462f10637f2795b147751ef413237389d230b869360mtklein SkAutoExclusive l(DWriteFactoryMutex); 46322253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner // IDWriteFactory2::CreateGlyphRunAnalysis is very bad at aliased glyphs. 46422253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner if (this->getDWriteTypeface()->fFactory2 && 46522253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner (fGridFitMode == DWRITE_GRID_FIT_MODE_DISABLED || 46622253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner fAntiAliasMode == DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE)) 46722253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner { 46822253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner HRM(this->getDWriteTypeface()->fFactory2->CreateGlyphRunAnalysis( 46922253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner &run, 47022253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner &fXform, 47122253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner renderingMode, 47222253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner fMeasuringMode, 47322253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner fGridFitMode, 47422253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner fAntiAliasMode, 47522253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner 0.0f, // baselineOriginX, 47622253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner 0.0f, // baselineOriginY, 47722253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner &glyphRunAnalysis), 47822253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner "Could not create DW2 glyph run analysis."); 47922253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner } else { 48022253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner HRM(this->getDWriteTypeface()->fFactory->CreateGlyphRunAnalysis(&run, 48122253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner 1.0f, // pixelsPerDip, 48222253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner &fXform, 48322253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner renderingMode, 48422253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner fMeasuringMode, 48522253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner 0.0f, // baselineOriginX, 48622253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner 0.0f, // baselineOriginY, 48722253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner &glyphRunAnalysis), 48822253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner "Could not create glyph run analysis."); 48922253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner } 4906440f0b09ede274f93131eebb3ef49e73dfb2b9cherb } 4916440f0b09ede274f93131eebb3ef49e73dfb2b9cherb { 4926440f0b09ede274f93131eebb3ef49e73dfb2b9cherb Shared l(DWriteFactoryMutex); 493c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb HRM(glyphRunAnalysis->GetAlphaTextureBounds(textureType, bbox), 494c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb "Could not get texture bounds."); 495c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb } 496683a37692bc67ef1144922b73a1e871e7e1e842ebungeman return S_OK; 497683a37692bc67ef1144922b73a1e871e7e1e842ebungeman} 498683a37692bc67ef1144922b73a1e871e7e1e842ebungeman 499683a37692bc67ef1144922b73a1e871e7e1e842ebungeman/** GetAlphaTextureBounds succeeds but sometimes returns empty bounds like 500683a37692bc67ef1144922b73a1e871e7e1e842ebungeman * { 0x80000000, 0x80000000, 0x80000000, 0x80000000 } 501683a37692bc67ef1144922b73a1e871e7e1e842ebungeman * for small, but not quite zero, sized glyphs. 502683a37692bc67ef1144922b73a1e871e7e1e842ebungeman * Only set as non-empty if the returned bounds are non-empty. 503683a37692bc67ef1144922b73a1e871e7e1e842ebungeman */ 504683a37692bc67ef1144922b73a1e871e7e1e842ebungemanstatic bool glyph_check_and_set_bounds(SkGlyph* glyph, const RECT& bbox) { 505683a37692bc67ef1144922b73a1e871e7e1e842ebungeman if (bbox.left >= bbox.right || bbox.top >= bbox.bottom) { 506683a37692bc67ef1144922b73a1e871e7e1e842ebungeman return false; 507683a37692bc67ef1144922b73a1e871e7e1e842ebungeman } 508d94e00c985dedccb4b8870de1a822fe75dc1edb1Mike Klein 509d94e00c985dedccb4b8870de1a822fe75dc1edb1Mike Klein // We're trying to pack left and top into int16_t, 510d94e00c985dedccb4b8870de1a822fe75dc1edb1Mike Klein // and width and height into uint16_t, after outsetting by 1. 511d94e00c985dedccb4b8870de1a822fe75dc1edb1Mike Klein if (!SkIRect::MakeXYWH(-32767, -32767, 65535, 65535).contains( 512d94e00c985dedccb4b8870de1a822fe75dc1edb1Mike Klein SkIRect::MakeLTRB(bbox.left, bbox.top, bbox.right, bbox.bottom))) { 513d94e00c985dedccb4b8870de1a822fe75dc1edb1Mike Klein return false; 514d94e00c985dedccb4b8870de1a822fe75dc1edb1Mike Klein } 515d94e00c985dedccb4b8870de1a822fe75dc1edb1Mike Klein 516683a37692bc67ef1144922b73a1e871e7e1e842ebungeman glyph->fWidth = SkToU16(bbox.right - bbox.left); 517683a37692bc67ef1144922b73a1e871e7e1e842ebungeman glyph->fHeight = SkToU16(bbox.bottom - bbox.top); 518683a37692bc67ef1144922b73a1e871e7e1e842ebungeman glyph->fLeft = SkToS16(bbox.left); 519683a37692bc67ef1144922b73a1e871e7e1e842ebungeman glyph->fTop = SkToS16(bbox.top); 520683a37692bc67ef1144922b73a1e871e7e1e842ebungeman return true; 521b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner} 522b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner 523c4b091543b4082fd1a2f356ef3b478073c5f9418kulshinbool SkScalerContext_DW::isColorGlyph(const SkGlyph& glyph) { 524c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin SkTScopedComPtr<IDWriteColorGlyphRunEnumerator> colorLayer; 525e0c9e00cd5ed17a45a988b8b57fa9c09f3574921Ben Wagner return getColorGlyphRun(glyph, &colorLayer); 526c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin} 527c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin 528c4b091543b4082fd1a2f356ef3b478073c5f9418kulshinbool SkScalerContext_DW::getColorGlyphRun(const SkGlyph& glyph, 529c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin IDWriteColorGlyphRunEnumerator** colorGlyph) 530c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin{ 531c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin FLOAT advance = 0; 532c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin UINT16 glyphId = glyph.getGlyphID(); 533c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin 534c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin DWRITE_GLYPH_OFFSET offset; 535c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin offset.advanceOffset = 0.0f; 536c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin offset.ascenderOffset = 0.0f; 537c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin 538c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin DWRITE_GLYPH_RUN run; 539c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin run.glyphCount = 1; 540c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin run.glyphAdvances = &advance; 5417cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman run.fontFace = this->getDWriteTypeface()->fDWriteFontFace.get(); 542c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin run.fontEmSize = SkScalarToFloat(fTextSizeRender); 543c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin run.bidiLevel = 0; 544c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin run.glyphIndices = &glyphId; 545c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin run.isSideways = FALSE; 546c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin run.glyphOffsets = &offset; 547c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin 54822253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner HRESULT hr = this->getDWriteTypeface()->fFactory2->TranslateColorGlyphRun( 549c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin 0, 0, &run, nullptr, fMeasuringMode, &fXform, 0, colorGlyph); 550c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin if (hr == DWRITE_E_NOCOLOR) { 551c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin return false; 552c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin } 553c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin HRBM(hr, "Failed to translate color glyph run"); 554c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin return true; 555c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin} 556c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin 557b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagnervoid SkScalerContext_DW::generateMetrics(SkGlyph* glyph) { 558b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner glyph->fWidth = 0; 559683a37692bc67ef1144922b73a1e871e7e1e842ebungeman glyph->fHeight = 0; 560683a37692bc67ef1144922b73a1e871e7e1e842ebungeman glyph->fLeft = 0; 561683a37692bc67ef1144922b73a1e871e7e1e842ebungeman glyph->fTop = 0; 562b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner 563b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner this->generateAdvance(glyph); 564b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner 565c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin if (fIsColorFont && isColorGlyph(*glyph)) { 566c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin glyph->fMaskFormat = SkMask::kARGB32_Format; 567c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin } 568c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin 569b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner RECT bbox; 570683a37692bc67ef1144922b73a1e871e7e1e842ebungeman HRVM(this->getBoundingBox(glyph, fRenderingMode, fTextureType, &bbox), 571683a37692bc67ef1144922b73a1e871e7e1e842ebungeman "Requested bounding box could not be determined."); 572683a37692bc67ef1144922b73a1e871e7e1e842ebungeman 573683a37692bc67ef1144922b73a1e871e7e1e842ebungeman if (glyph_check_and_set_bounds(glyph, bbox)) { 574683a37692bc67ef1144922b73a1e871e7e1e842ebungeman return; 575683a37692bc67ef1144922b73a1e871e7e1e842ebungeman } 576b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner 577b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner // GetAlphaTextureBounds succeeds but returns an empty RECT if there are no 578b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner // glyphs of the specified texture type. When this happens, try with the 579b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner // alternate texture type. 580683a37692bc67ef1144922b73a1e871e7e1e842ebungeman if (DWRITE_TEXTURE_CLEARTYPE_3x1 == fTextureType) { 581683a37692bc67ef1144922b73a1e871e7e1e842ebungeman HRVM(this->getBoundingBox(glyph, 582683a37692bc67ef1144922b73a1e871e7e1e842ebungeman DWRITE_RENDERING_MODE_ALIASED, 583683a37692bc67ef1144922b73a1e871e7e1e842ebungeman DWRITE_TEXTURE_ALIASED_1x1, 584683a37692bc67ef1144922b73a1e871e7e1e842ebungeman &bbox), 585683a37692bc67ef1144922b73a1e871e7e1e842ebungeman "Fallback bounding box could not be determined."); 586683a37692bc67ef1144922b73a1e871e7e1e842ebungeman if (glyph_check_and_set_bounds(glyph, bbox)) { 587683a37692bc67ef1144922b73a1e871e7e1e842ebungeman glyph->fForceBW = 1; 588b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner } 589b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner } 590683a37692bc67ef1144922b73a1e871e7e1e842ebungeman // TODO: handle the case where a request for DWRITE_TEXTURE_ALIASED_1x1 591683a37692bc67ef1144922b73a1e871e7e1e842ebungeman // fails, and try DWRITE_TEXTURE_CLEARTYPE_3x1. 592e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com} 593e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 594410780677af260e32948b02c0725ef6ad761260cbungemanvoid SkScalerContext_DW::generateFontMetrics(SkPaint::FontMetrics* metrics) { 59596fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (nullptr == metrics) { 596f73c237291bb1fc698f688d8a9b1cdd23838ed18bungeman return; 597e1b9bad0711e557e45fee109fb492d19e35e1d38bungeman@google.com } 598e1b9bad0711e557e45fee109fb492d19e35e1d38bungeman@google.com 599410780677af260e32948b02c0725ef6ad761260cbungeman sk_bzero(metrics, sizeof(*metrics)); 600410780677af260e32948b02c0725ef6ad761260cbungeman 601e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com DWRITE_FONT_METRICS dwfm; 602d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode || 603d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode) 604d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com { 6057cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman this->getDWriteTypeface()->fDWriteFontFace->GetGdiCompatibleMetrics( 606058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com fTextSizeRender, 607d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com 1.0f, // pixelsPerDip 608d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com &fXform, 609d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com &dwfm); 610d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com } else { 6117cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman this->getDWriteTypeface()->fDWriteFontFace->GetMetrics(&dwfm); 612d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com } 613e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 614e1b9bad0711e557e45fee109fb492d19e35e1d38bungeman@google.com SkScalar upem = SkIntToScalar(dwfm.designUnitsPerEm); 615e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 616f73c237291bb1fc698f688d8a9b1cdd23838ed18bungeman metrics->fAscent = -fTextSizeRender * SkIntToScalar(dwfm.ascent) / upem; 617410780677af260e32948b02c0725ef6ad761260cbungeman metrics->fDescent = fTextSizeRender * SkIntToScalar(dwfm.descent) / upem; 618410780677af260e32948b02c0725ef6ad761260cbungeman metrics->fLeading = fTextSizeRender * SkIntToScalar(dwfm.lineGap) / upem; 619410780677af260e32948b02c0725ef6ad761260cbungeman metrics->fXHeight = fTextSizeRender * SkIntToScalar(dwfm.xHeight) / upem; 620a6725fcb14f63734d7668bb0550cd9c128e841b0Koji Ishii metrics->fCapHeight = fTextSizeRender * SkIntToScalar(dwfm.capHeight) / upem; 621410780677af260e32948b02c0725ef6ad761260cbungeman metrics->fUnderlineThickness = fTextSizeRender * SkIntToScalar(dwfm.underlineThickness) / upem; 622410780677af260e32948b02c0725ef6ad761260cbungeman metrics->fUnderlinePosition = -(fTextSizeRender * SkIntToScalar(dwfm.underlinePosition) / upem); 623219f3622ba32a1cb6380212a2ec1947513fbfeb9Ben Wagner metrics->fStrikeoutThickness = fTextSizeRender * SkIntToScalar(dwfm.strikethroughThickness) / upem; 624219f3622ba32a1cb6380212a2ec1947513fbfeb9Ben Wagner metrics->fStrikeoutPosition = -(fTextSizeRender * SkIntToScalar(dwfm.strikethroughPosition) / upem); 625410780677af260e32948b02c0725ef6ad761260cbungeman 6263318da5d1aa19533dd034f90d4bc29a2d2e86b66Ben Wagner metrics->fFlags |= SkPaint::FontMetrics::kUnderlineThicknessIsValid_Flag; 627410780677af260e32948b02c0725ef6ad761260cbungeman metrics->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag; 628219f3622ba32a1cb6380212a2ec1947513fbfeb9Ben Wagner metrics->fFlags |= SkPaint::FontMetrics::kStrikeoutThicknessIsValid_Flag; 629219f3622ba32a1cb6380212a2ec1947513fbfeb9Ben Wagner metrics->fFlags |= SkPaint::FontMetrics::kStrikeoutPositionIsValid_Flag; 630f73c237291bb1fc698f688d8a9b1cdd23838ed18bungeman 6317cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman if (this->getDWriteTypeface()->fDWriteFontFace1.get()) { 632f73c237291bb1fc698f688d8a9b1cdd23838ed18bungeman DWRITE_FONT_METRICS1 dwfm1; 6337cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman this->getDWriteTypeface()->fDWriteFontFace1->GetMetrics(&dwfm1); 634f73c237291bb1fc698f688d8a9b1cdd23838ed18bungeman metrics->fTop = -fTextSizeRender * SkIntToScalar(dwfm1.glyphBoxTop) / upem; 635f73c237291bb1fc698f688d8a9b1cdd23838ed18bungeman metrics->fBottom = -fTextSizeRender * SkIntToScalar(dwfm1.glyphBoxBottom) / upem; 636f73c237291bb1fc698f688d8a9b1cdd23838ed18bungeman metrics->fXMin = fTextSizeRender * SkIntToScalar(dwfm1.glyphBoxLeft) / upem; 637f73c237291bb1fc698f688d8a9b1cdd23838ed18bungeman metrics->fXMax = fTextSizeRender * SkIntToScalar(dwfm1.glyphBoxRight) / upem; 638f73c237291bb1fc698f688d8a9b1cdd23838ed18bungeman 639f73c237291bb1fc698f688d8a9b1cdd23838ed18bungeman metrics->fMaxCharWidth = metrics->fXMax - metrics->fXMin; 640f548444684b9c96f7717aebe645944af4f95d650bungeman return; 641f548444684b9c96f7717aebe645944af4f95d650bungeman } 642f548444684b9c96f7717aebe645944af4f95d650bungeman 6437cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman AutoTDWriteTable<SkOTTableHead> head(this->getDWriteTypeface()->fDWriteFontFace.get()); 644f548444684b9c96f7717aebe645944af4f95d650bungeman if (head.fExists && 645f548444684b9c96f7717aebe645944af4f95d650bungeman head.fSize >= sizeof(SkOTTableHead) && 646f548444684b9c96f7717aebe645944af4f95d650bungeman head->version == SkOTTableHead::version1) 647f548444684b9c96f7717aebe645944af4f95d650bungeman { 648f548444684b9c96f7717aebe645944af4f95d650bungeman metrics->fTop = -fTextSizeRender * (int16_t)SkEndian_SwapBE16(head->yMax) / upem; 649f548444684b9c96f7717aebe645944af4f95d650bungeman metrics->fBottom = -fTextSizeRender * (int16_t)SkEndian_SwapBE16(head->yMin) / upem; 650f548444684b9c96f7717aebe645944af4f95d650bungeman metrics->fXMin = fTextSizeRender * (int16_t)SkEndian_SwapBE16(head->xMin) / upem; 651f548444684b9c96f7717aebe645944af4f95d650bungeman metrics->fXMax = fTextSizeRender * (int16_t)SkEndian_SwapBE16(head->xMax) / upem; 652f548444684b9c96f7717aebe645944af4f95d650bungeman 653f548444684b9c96f7717aebe645944af4f95d650bungeman metrics->fMaxCharWidth = metrics->fXMax - metrics->fXMin; 654f548444684b9c96f7717aebe645944af4f95d650bungeman return; 655f73c237291bb1fc698f688d8a9b1cdd23838ed18bungeman } 656f548444684b9c96f7717aebe645944af4f95d650bungeman 657f548444684b9c96f7717aebe645944af4f95d650bungeman metrics->fTop = metrics->fAscent; 658f548444684b9c96f7717aebe645944af4f95d650bungeman metrics->fBottom = metrics->fDescent; 659e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com} 660e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 661e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com/////////////////////////////////////////////////////////////////////////////// 662e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 663a4083c97d48e8a4f88e2797d7363f141e3d42553Cary Clark#include "SkColorData.h" 664e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 665e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.comstatic void bilevel_to_bw(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph) { 666e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com const int width = glyph.fWidth; 667e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com const size_t dstRB = (width + 7) >> 3; 668e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage); 669e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 670e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com int byteCount = width >> 3; 671e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com int bitCount = width & 7; 672e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 673e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com for (int y = 0; y < glyph.fHeight; ++y) { 674e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com if (byteCount > 0) { 675e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com for (int i = 0; i < byteCount; ++i) { 676e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com unsigned byte = 0; 677e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com byte |= src[0] & (1 << 7); 678e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com byte |= src[1] & (1 << 6); 679e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com byte |= src[2] & (1 << 5); 680e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com byte |= src[3] & (1 << 4); 681e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com byte |= src[4] & (1 << 3); 682e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com byte |= src[5] & (1 << 2); 683e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com byte |= src[6] & (1 << 1); 684e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com byte |= src[7] & (1 << 0); 685e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com dst[i] = byte; 686e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com src += 8; 687e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 688e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 689e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com if (bitCount > 0) { 690e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com unsigned byte = 0; 691e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com unsigned mask = 0x80; 692e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com for (int i = 0; i < bitCount; i++) { 693e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com byte |= (src[i]) & mask; 694e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com mask >>= 1; 695e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 696e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com dst[byteCount] = byte; 697e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 698e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com src += bitCount; 699e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com dst += dstRB; 700e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 701e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com} 702e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 703e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.comtemplate<bool APPLY_PREBLEND> 70422253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagnerstatic void grayscale_to_a8(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph, 70522253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner const uint8_t* table8) { 70622253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner const size_t dstRB = glyph.rowBytes(); 70722253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner const U16CPU width = glyph.fWidth; 70822253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage); 70922253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner 71022253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner for (U16CPU y = 0; y < glyph.fHeight; y++) { 71122253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner for (U16CPU i = 0; i < width; i++) { 71222253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner U8CPU a = *(src++); 71322253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner dst[i] = sk_apply_lut_if<APPLY_PREBLEND>(a, table8); 71422253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner } 71522253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner dst = SkTAddOffset<uint8_t>(dst, dstRB); 71622253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner } 71722253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner} 71822253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner 71922253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagnertemplate<bool APPLY_PREBLEND> 720e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.comstatic void rgb_to_a8(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph, const uint8_t* table8) { 721e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com const size_t dstRB = glyph.rowBytes(); 722e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com const U16CPU width = glyph.fWidth; 723e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage); 724e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 725e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com for (U16CPU y = 0; y < glyph.fHeight; y++) { 726e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com for (U16CPU i = 0; i < width; i++) { 727e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com U8CPU r = *(src++); 728e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com U8CPU g = *(src++); 729e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com U8CPU b = *(src++); 730e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com dst[i] = sk_apply_lut_if<APPLY_PREBLEND>((r + g + b) / 3, table8); 731e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 73222253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner dst = SkTAddOffset<uint8_t>(dst, dstRB); 733e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 734e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com} 735e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 73612f03121bb76214b71677ac0208d74c3c56c3b1fbungemantemplate<bool APPLY_PREBLEND, bool RGB> 737e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.comstatic void rgb_to_lcd16(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph, 738e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) { 739e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com const size_t dstRB = glyph.rowBytes(); 740e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com const U16CPU width = glyph.fWidth; 741e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com uint16_t* SK_RESTRICT dst = static_cast<uint16_t*>(glyph.fImage); 742e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 743e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com for (U16CPU y = 0; y < glyph.fHeight; y++) { 744e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com for (U16CPU i = 0; i < width; i++) { 74512f03121bb76214b71677ac0208d74c3c56c3b1fbungeman U8CPU r, g, b; 74612f03121bb76214b71677ac0208d74c3c56c3b1fbungeman if (RGB) { 74712f03121bb76214b71677ac0208d74c3c56c3b1fbungeman r = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableR); 74812f03121bb76214b71677ac0208d74c3c56c3b1fbungeman g = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableG); 74912f03121bb76214b71677ac0208d74c3c56c3b1fbungeman b = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableB); 75012f03121bb76214b71677ac0208d74c3c56c3b1fbungeman } else { 75112f03121bb76214b71677ac0208d74c3c56c3b1fbungeman b = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableB); 75212f03121bb76214b71677ac0208d74c3c56c3b1fbungeman g = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableG); 75312f03121bb76214b71677ac0208d74c3c56c3b1fbungeman r = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableR); 75412f03121bb76214b71677ac0208d74c3c56c3b1fbungeman } 755e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com dst[i] = SkPack888ToRGB16(r, g, b); 756e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 75722253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner dst = SkTAddOffset<uint16_t>(dst, dstRB); 758e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 759e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com} 760e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 761b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagnerconst void* SkScalerContext_DW::drawDWMask(const SkGlyph& glyph, 762b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner DWRITE_RENDERING_MODE renderingMode, 763b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner DWRITE_TEXTURE_TYPE textureType) 764b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner{ 765d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com int sizeNeeded = glyph.fWidth * glyph.fHeight; 76622253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner if (DWRITE_TEXTURE_CLEARTYPE_3x1 == textureType) { 767d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com sizeNeeded *= 3; 768d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com } 769d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com if (sizeNeeded > fBits.count()) { 770d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com fBits.setCount(sizeNeeded); 771d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com } 772d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com 773d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com // erase 774d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com memset(fBits.begin(), 0, sizeNeeded); 775d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com 776d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com fXform.dx = SkFixedToFloat(glyph.getSubXFixed()); 777d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com fXform.dy = SkFixedToFloat(glyph.getSubYFixed()); 778d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com 779d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com FLOAT advance = 0.0f; 780d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com 781d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com UINT16 index = glyph.getGlyphID(); 782d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com 783d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com DWRITE_GLYPH_OFFSET offset; 784d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com offset.advanceOffset = 0.0f; 785d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com offset.ascenderOffset = 0.0f; 786e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 787d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com DWRITE_GLYPH_RUN run; 788d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com run.glyphCount = 1; 789d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com run.glyphAdvances = &advance; 7907cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman run.fontFace = this->getDWriteTypeface()->fDWriteFontFace.get(); 791058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com run.fontEmSize = SkScalarToFloat(fTextSizeRender); 792d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com run.bidiLevel = 0; 793d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com run.glyphIndices = &index; 794d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com run.isSideways = FALSE; 795d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com run.glyphOffsets = &offset; 796c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb { 7976440f0b09ede274f93131eebb3ef49e73dfb2b9cherb SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis; 7986440f0b09ede274f93131eebb3ef49e73dfb2b9cherb { 799f10637f2795b147751ef413237389d230b869360mtklein SkAutoExclusive l(DWriteFactoryMutex); 80022253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner // IDWriteFactory2::CreateGlyphRunAnalysis is very bad at aliased glyphs. 80122253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner if (this->getDWriteTypeface()->fFactory2 && 80222253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner (fGridFitMode == DWRITE_GRID_FIT_MODE_DISABLED || 80322253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner fAntiAliasMode == DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE)) 80422253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner { 80522253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner HRNM(this->getDWriteTypeface()->fFactory2->CreateGlyphRunAnalysis(&run, 80622253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner &fXform, 80722253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner renderingMode, 80822253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner fMeasuringMode, 80922253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner fGridFitMode, 81022253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner fAntiAliasMode, 81122253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner 0.0f, // baselineOriginX, 81222253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner 0.0f, // baselineOriginY, 81322253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner &glyphRunAnalysis), 81422253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner "Could not create DW2 glyph run analysis."); 81522253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner } else { 81622253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner HRNM(this->getDWriteTypeface()->fFactory->CreateGlyphRunAnalysis(&run, 81722253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner 1.0f, // pixelsPerDip, 81822253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner &fXform, 81922253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner renderingMode, 82022253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner fMeasuringMode, 82122253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner 0.0f, // baselineOriginX, 82222253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner 0.0f, // baselineOriginY, 82322253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner &glyphRunAnalysis), 82422253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner "Could not create glyph run analysis."); 82522253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner } 8266440f0b09ede274f93131eebb3ef49e73dfb2b9cherb } 827c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb //NOTE: this assumes that the glyph has already been measured 828c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb //with an exact same glyph run analysis. 829c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb RECT bbox; 830c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb bbox.left = glyph.fLeft; 831c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb bbox.top = glyph.fTop; 832c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb bbox.right = glyph.fLeft + glyph.fWidth; 833c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb bbox.bottom = glyph.fTop + glyph.fHeight; 8346440f0b09ede274f93131eebb3ef49e73dfb2b9cherb { 8356440f0b09ede274f93131eebb3ef49e73dfb2b9cherb Shared l(DWriteFactoryMutex); 8366440f0b09ede274f93131eebb3ef49e73dfb2b9cherb HRNM(glyphRunAnalysis->CreateAlphaTexture(textureType, 83722253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner &bbox, 83822253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner fBits.begin(), 83922253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner sizeNeeded), 8406440f0b09ede274f93131eebb3ef49e73dfb2b9cherb "Could not draw mask."); 8416440f0b09ede274f93131eebb3ef49e73dfb2b9cherb } 842c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb } 843d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com return fBits.begin(); 844d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com} 845d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com 846c4b091543b4082fd1a2f356ef3b478073c5f9418kulshinvoid SkScalerContext_DW::generateColorGlyphImage(const SkGlyph& glyph) { 847c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin SkASSERT(isColorGlyph(glyph)); 848c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin SkASSERT(glyph.fMaskFormat == SkMask::Format::kARGB32_Format); 849c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin 850c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin memset(glyph.fImage, 0, glyph.computeImageSize()); 851c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin 852c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin SkTScopedComPtr<IDWriteColorGlyphRunEnumerator> colorLayers; 853c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin getColorGlyphRun(glyph, &colorLayers); 854c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin SkASSERT(colorLayers.get()); 855c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin 856c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin SkMatrix matrix = fSkXform; 857c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin matrix.postTranslate(-SkIntToScalar(glyph.fLeft), -SkIntToScalar(glyph.fTop)); 858c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin SkRasterClip rc(SkIRect::MakeWH(glyph.fWidth, glyph.fHeight)); 859c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin SkDraw draw; 860c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin draw.fDst = SkPixmap(SkImageInfo::MakeN32(glyph.fWidth, glyph.fHeight, kPremul_SkAlphaType), 861c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin glyph.fImage, 862c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin glyph.ComputeRowBytes(glyph.fWidth, SkMask::Format::kARGB32_Format)); 863c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin draw.fMatrix = &matrix; 864c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin draw.fRC = &rc; 865c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin 866c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin SkPaint paint; 867c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin if (fRenderingMode != DWRITE_RENDERING_MODE_ALIASED) { 868c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin paint.setFlags(SkPaint::Flags::kAntiAlias_Flag); 869c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin } 870c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin 871c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin BOOL hasNextRun = FALSE; 872c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin while (SUCCEEDED(colorLayers->MoveNext(&hasNextRun)) && hasNextRun) { 873c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin const DWRITE_COLOR_GLYPH_RUN* colorGlyph; 874c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin HRVM(colorLayers->GetCurrentRun(&colorGlyph), "Could not get current color glyph run"); 875c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin 876c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin SkColor color; 877c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin if (colorGlyph->paletteIndex != 0xffff) { 87835ee0e09b4966bd087147e2c9b4c3177e9737d3bMike Reed color = SkColorSetARGB(sk_float_round2int(colorGlyph->runColor.a * 255), 87935ee0e09b4966bd087147e2c9b4c3177e9737d3bMike Reed sk_float_round2int(colorGlyph->runColor.r * 255), 88035ee0e09b4966bd087147e2c9b4c3177e9737d3bMike Reed sk_float_round2int(colorGlyph->runColor.g * 255), 88135ee0e09b4966bd087147e2c9b4c3177e9737d3bMike Reed sk_float_round2int(colorGlyph->runColor.b * 255)); 882c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin } else { 883c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin // If all components of runColor are 0 or (equivalently) paletteIndex is 0xFFFF then 884c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin // the 'current brush' is used. fRec.getLuminanceColor() is kinda sorta what is wanted 885c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin // here, but not really, it will often be the wrong value because it wan't designed for 886c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin // this. 8875f544345d653900ef30212ea1c243947be8bb074bungeman // TODO: implement this fully, bug.skia.org/5788 888c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin color = fRec.getLuminanceColor(); 889c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin } 890c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin paint.setColor(color); 891c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin 892c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin SkPath path; 893c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin SkTScopedComPtr<IDWriteGeometrySink> geometryToPath; 894c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin HRVM(SkDWriteGeometrySink::Create(&path, &geometryToPath), 895c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin "Could not create geometry to path converter."); 896c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin { 897f10637f2795b147751ef413237389d230b869360mtklein SkAutoExclusive l(DWriteFactoryMutex); 898c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin HRVM(colorGlyph->glyphRun.fontFace->GetGlyphRunOutline( 899c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin colorGlyph->glyphRun.fontEmSize, 900c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin colorGlyph->glyphRun.glyphIndices, 901c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin colorGlyph->glyphRun.glyphAdvances, 902c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin colorGlyph->glyphRun.glyphOffsets, 903c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin colorGlyph->glyphRun.glyphCount, 904c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin colorGlyph->glyphRun.isSideways, 905c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin colorGlyph->glyphRun.bidiLevel % 2, //rtl 906c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin geometryToPath.get()), 907c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin "Could not create glyph outline."); 908c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin } 909c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin draw.drawPath(path, paint, nullptr, true /* pathIsMutable */); 910c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin } 911c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin} 912c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin 913d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.comvoid SkScalerContext_DW::generateImage(const SkGlyph& glyph) { 914e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com //Create the mask. 915b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner DWRITE_RENDERING_MODE renderingMode = fRenderingMode; 916b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner DWRITE_TEXTURE_TYPE textureType = fTextureType; 917b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner if (glyph.fForceBW) { 918b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner renderingMode = DWRITE_RENDERING_MODE_ALIASED; 919b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner textureType = DWRITE_TEXTURE_ALIASED_1x1; 920b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner } 921c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin 922c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin if (SkMask::kARGB32_Format == glyph.fMaskFormat) { 923c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin generateColorGlyphImage(glyph); 924c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin return; 925c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin } 926c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin 927b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner const void* bits = this->drawDWMask(glyph, renderingMode, textureType); 928e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com if (!bits) { 929e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com sk_bzero(glyph.fImage, glyph.computeImageSize()); 930e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com return; 931e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 932e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 933e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com //Copy the mask into the glyph. 934e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com const uint8_t* src = (const uint8_t*)bits; 935b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner if (DWRITE_RENDERING_MODE_ALIASED == renderingMode) { 936e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com bilevel_to_bw(src, glyph); 937d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com const_cast<SkGlyph&>(glyph).fMaskFormat = SkMask::kBW_Format; 938d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com } else if (!isLCD(fRec)) { 93922253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner if (textureType == DWRITE_TEXTURE_ALIASED_1x1) { 94022253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner if (fPreBlend.isApplicable()) { 94122253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner grayscale_to_a8<true>(src, glyph, fPreBlend.fG); 94222253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner } else { 94322253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner grayscale_to_a8<false>(src, glyph, fPreBlend.fG); 94422253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner } 945e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } else { 94622253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner if (fPreBlend.isApplicable()) { 94722253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner rgb_to_a8<true>(src, glyph, fPreBlend.fG); 94822253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner } else { 94922253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner rgb_to_a8<false>(src, glyph, fPreBlend.fG); 95022253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner } 951e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 952d54d3fc82456f8789b3e4dff40faeb7b670bcf4breed } else { 953d54d3fc82456f8789b3e4dff40faeb7b670bcf4breed SkASSERT(SkMask::kLCD16_Format == glyph.fMaskFormat); 954a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com if (fPreBlend.isApplicable()) { 95512f03121bb76214b71677ac0208d74c3c56c3b1fbungeman if (fRec.fFlags & SkScalerContext::kLCD_BGROrder_Flag) { 95612f03121bb76214b71677ac0208d74c3c56c3b1fbungeman rgb_to_lcd16<true, false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); 95712f03121bb76214b71677ac0208d74c3c56c3b1fbungeman } else { 95812f03121bb76214b71677ac0208d74c3c56c3b1fbungeman rgb_to_lcd16<true, true>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); 95912f03121bb76214b71677ac0208d74c3c56c3b1fbungeman } 960e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } else { 96112f03121bb76214b71677ac0208d74c3c56c3b1fbungeman if (fRec.fFlags & SkScalerContext::kLCD_BGROrder_Flag) { 96212f03121bb76214b71677ac0208d74c3c56c3b1fbungeman rgb_to_lcd16<false, false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); 96312f03121bb76214b71677ac0208d74c3c56c3b1fbungeman } else { 96412f03121bb76214b71677ac0208d74c3c56c3b1fbungeman rgb_to_lcd16<false, true>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); 96512f03121bb76214b71677ac0208d74c3c56c3b1fbungeman } 966e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 967e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 968e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com} 969e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 9706e9ac12495f3b64b6ea8860bb9f99c43cd33aa08Ben Wagnervoid SkScalerContext_DW::generatePath(SkGlyphID glyph, SkPath* path) { 9712f19b551ac10b96a1a35a147063cd4300d6fe07adcheng SkASSERT(path); 972e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 973e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com path->reset(); 974e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 975e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com SkTScopedComPtr<IDWriteGeometrySink> geometryToPath; 976e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com HRVM(SkDWriteGeometrySink::Create(path, &geometryToPath), 977e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com "Could not create geometry to path converter."); 9786e9ac12495f3b64b6ea8860bb9f99c43cd33aa08Ben Wagner UINT16 glyphId = SkTo<UINT16>(glyph); 979c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb { 980f10637f2795b147751ef413237389d230b869360mtklein SkAutoExclusive l(DWriteFactoryMutex); 981c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb //TODO: convert to<->from DIUs? This would make a difference if hinting. 982c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb //It may not be needed, it appears that DirectWrite only hints at em size. 9837cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman HRVM(this->getDWriteTypeface()->fDWriteFontFace->GetGlyphRunOutline( 9847cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman SkScalarToFloat(fTextSizeRender), 9857cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman &glyphId, 9867cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman nullptr, //advances 9877cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman nullptr, //offsets 9887cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman 1, //num glyphs 9897cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman FALSE, //sideways 9907cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman FALSE, //rtl 9917cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman geometryToPath.get()), 9927cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman "Could not create glyph outline."); 993c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb } 994091f51b794e62942db47ccef6fef143ad1590d12bungeman@google.com 995058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com path->transform(fSkXform); 996e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com} 9971ee76510f5dbf632d30975fc3509ef4f609156d2mtklein 9988f11d4dcafef4447fa68ea0ab28a72589241e9fdMike Klein#endif//defined(SK_BUILD_FOR_WIN) 999