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" 9e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com#undef GetGlyphIndices 10e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 1172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkDWrite.h" 12e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com#include "SkDWriteGeometrySink.h" 13e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com#include "SkEndian.h" 14e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com#include "SkGlyph.h" 15e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com#include "SkHRESULT.h" 16e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com#include "SkMaskGamma.h" 17058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com#include "SkMatrix22.h" 18058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com#include "SkOTTable_EBLC.h" 19058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com#include "SkOTTable_EBSC.h" 209ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger#include "SkOTTable_gasp.h" 219ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger#include "SkOTTable_maxp.h" 22e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com#include "SkPath.h" 2351daa25a2b16bca578e78b7ea1e5815b9abb8b0bbungeman#include "SkScalerContext.h" 2451daa25a2b16bca578e78b7ea1e5815b9abb8b0bbungeman#include "SkScalerContext_win_dw.h" 25e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com#include "SkTScopedComPtr.h" 2651daa25a2b16bca578e78b7ea1e5815b9abb8b0bbungeman#include "SkTypeface_win_dw.h" 27e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 28e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com#include <dwrite.h> 294e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger#include <dwrite_1.h> 30e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 31e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.comstatic bool isLCD(const SkScalerContext::Rec& rec) { 32e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com return SkMask::kLCD16_Format == rec.fMaskFormat || 33e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com SkMask::kLCD32_Format == rec.fMaskFormat; 34e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com} 35e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 369ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenbergerstatic bool is_hinted_without_gasp(DWriteFontTypeface* typeface) { 379ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger AutoTDWriteTable<SkOTTableMaximumProfile> maxp(typeface->fDWriteFontFace.get()); 389ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger if (!maxp.fExists) { 399ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger return false; 409ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger } 419ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger if (maxp.fSize < sizeof(SkOTTableMaximumProfile::Version::TT)) { 429ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger return false; 439ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger } 449ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger if (maxp->version.version != SkOTTableMaximumProfile::Version::TT::VERSION) { 459ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger return false; 469ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger } 479ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger 489ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger if (0 == maxp->version.tt.maxSizeOfInstructions) { 499ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger // No hints. 509ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger return false; 519ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger } 529ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger 539ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger AutoTDWriteTable<SkOTTableGridAndScanProcedure> gasp(typeface->fDWriteFontFace.get()); 549ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger return !gasp.fExists; 559ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger} 569ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger 579ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger/** A PPEMRange is inclusive, [min, max]. */ 589ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenbergerstruct PPEMRange { 599ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger int min; 609ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger int max; 619ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger}; 629ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger 639ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger/** If the rendering mode for the specified 'size' is gridfit, then place 649ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger * the gridfit range into 'range'. Otherwise, leave 'range' alone. 659ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger */ 669ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenbergerstatic void expand_range_if_gridfit_only(DWriteFontTypeface* typeface, int size, PPEMRange* range) { 679ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger AutoTDWriteTable<SkOTTableGridAndScanProcedure> gasp(typeface->fDWriteFontFace.get()); 689ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger if (!gasp.fExists) { 699ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger return; 709ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger } 719ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger if (gasp.fSize < sizeof(SkOTTableGridAndScanProcedure)) { 729ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger return; 739ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger } 749ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger if (gasp->version != SkOTTableGridAndScanProcedure::version0 && 759ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger gasp->version != SkOTTableGridAndScanProcedure::version1) 769ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger { 779ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger return ; 789ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger } 799ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger 809ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger uint16_t numRanges = SkEndianSwap16(gasp->numRanges); 819ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger if (numRanges > 1024 || 829ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger gasp.fSize < sizeof(SkOTTableGridAndScanProcedure) + 839ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger sizeof(SkOTTableGridAndScanProcedure::GaspRange) * numRanges) 849ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger { 859ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger return; 869ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger } 879ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger 889ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger const SkOTTableGridAndScanProcedure::GaspRange* rangeTable = 899ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger SkTAfter<const SkOTTableGridAndScanProcedure::GaspRange>(gasp.get()); 909ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger int minPPEM = -1; 919ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger for (uint16_t i = 0; i < numRanges; ++i, ++rangeTable) { 929ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger int maxPPEM = SkEndianSwap16(rangeTable->maxPPEM); 939ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger // Test that the size is in range and the range is gridfit only. 949ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger if (minPPEM < size && size <= maxPPEM && 959ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger rangeTable->flags.raw.value == SkOTTableGridAndScanProcedure::GaspRange::behavior::Raw::GridfitMask) 969ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger { 979ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger range->min = minPPEM + 1; 989ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger range->max = maxPPEM; 999ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger return; 1009ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger } 1019ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger minPPEM = maxPPEM; 1029ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger } 1039ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger 1049ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger return; 1059ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger} 1069ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger 1079ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenbergerstatic bool has_bitmap_strike(DWriteFontTypeface* typeface, PPEMRange range) { 108058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com { 109058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com AutoTDWriteTable<SkOTTableEmbeddedBitmapLocation> eblc(typeface->fDWriteFontFace.get()); 110058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com if (!eblc.fExists) { 111058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com return false; 112058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com } 113058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com if (eblc.fSize < sizeof(SkOTTableEmbeddedBitmapLocation)) { 114058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com return false; 115058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com } 116058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com if (eblc->version != SkOTTableEmbeddedBitmapLocation::version_initial) { 117058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com return false; 118058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com } 119058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 120058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com uint32_t numSizes = SkEndianSwap32(eblc->numSizes); 1219ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger if (numSizes > 1024 || 1229ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger eblc.fSize < sizeof(SkOTTableEmbeddedBitmapLocation) + 123058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com sizeof(SkOTTableEmbeddedBitmapLocation::BitmapSizeTable) * numSizes) 124058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com { 125058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com return false; 126058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com } 127058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 128058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com const SkOTTableEmbeddedBitmapLocation::BitmapSizeTable* sizeTable = 129058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com SkTAfter<const SkOTTableEmbeddedBitmapLocation::BitmapSizeTable>(eblc.get()); 130058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com for (uint32_t i = 0; i < numSizes; ++i, ++sizeTable) { 1319ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger if (sizeTable->ppemX == sizeTable->ppemY && 1329ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger range.min <= sizeTable->ppemX && sizeTable->ppemX <= range.max) 1339ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger { 134058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // TODO: determine if we should dig through IndexSubTableArray/IndexSubTable 135058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // to determine the actual number of glyphs with bitmaps. 136058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 137058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // TODO: Ensure that the bitmaps actually cover a significant portion of the strike. 138058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 1399ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger // TODO: Ensure that the bitmaps are bi-level? 140058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com if (sizeTable->endGlyphIndex >= sizeTable->startGlyphIndex + 3) { 141058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com return true; 142058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com } 143058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com } 144058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com } 145058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com } 146058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 147058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com { 148058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com AutoTDWriteTable<SkOTTableEmbeddedBitmapScaling> ebsc(typeface->fDWriteFontFace.get()); 149058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com if (!ebsc.fExists) { 150058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com return false; 151058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com } 152058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com if (ebsc.fSize < sizeof(SkOTTableEmbeddedBitmapScaling)) { 153058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com return false; 154058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com } 155058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com if (ebsc->version != SkOTTableEmbeddedBitmapScaling::version_initial) { 156058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com return false; 157058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com } 158058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 159058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com uint32_t numSizes = SkEndianSwap32(ebsc->numSizes); 1609ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger if (numSizes > 1024 || 1619ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger ebsc.fSize < sizeof(SkOTTableEmbeddedBitmapScaling) + 162058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com sizeof(SkOTTableEmbeddedBitmapScaling::BitmapScaleTable) * numSizes) 163058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com { 164058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com return false; 165058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com } 166058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 167058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com const SkOTTableEmbeddedBitmapScaling::BitmapScaleTable* scaleTable = 168058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com SkTAfter<const SkOTTableEmbeddedBitmapScaling::BitmapScaleTable>(ebsc.get()); 169058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com for (uint32_t i = 0; i < numSizes; ++i, ++scaleTable) { 1709ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger if (scaleTable->ppemX == scaleTable->ppemY && 1719ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger range.min <= scaleTable->ppemX && scaleTable->ppemX <= range.max) { 172058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // EBSC tables are normally only found in bitmap only fonts. 173058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com return true; 174058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com } 175058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com } 176058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com } 177058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 178058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com return false; 179058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com} 180058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 1819ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenbergerstatic bool both_zero(SkScalar a, SkScalar b) { 182058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com return 0 == a && 0 == b; 183058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com} 184058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 185058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com// returns false if there is any non-90-rotation or skew 1869ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenbergerstatic bool is_axis_aligned(const SkScalerContext::Rec& rec) { 187058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com return 0 == rec.fPreSkewX && 1889ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger (both_zero(rec.fPost2x2[0][1], rec.fPost2x2[1][0]) || 1899ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger both_zero(rec.fPost2x2[0][0], rec.fPost2x2[1][1])); 190058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com} 191058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 19230ddd615c447fed73286151b463af20d309c85f1reed@google.comSkScalerContext_DW::SkScalerContext_DW(DWriteFontTypeface* typeface, 1936eddc77f6a0078570471277954c07d73b3a921d8bungeman@google.com const SkDescriptor* desc) 1940da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com : SkScalerContext(typeface, desc) 1950da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com , fTypeface(SkRef(typeface)) 196e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com , fGlyphCount(-1) { 197e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 198058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // In general, all glyphs should use CLEARTYPE_NATURAL_SYMMETRIC 199058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // except when bi-level rendering is requested or there are embedded 200058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // bi-level bitmaps (and the embedded bitmap flag is set and no rotation). 201058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // 202058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // DirectWrite's IDWriteFontFace::GetRecommendedRenderingMode does not do 203058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // this. As a result, determine the actual size of the text and then see if 204058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // there are any embedded bi-level bitmaps of that size. If there are, then 205058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // force bitmaps by requesting bi-level rendering. 206058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // 207058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // FreeType allows for separate ppemX and ppemY, but DirectWrite assumes 208058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // square pixels and only uses ppemY. Therefore the transform must track any 209058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // non-uniform x-scale. 210058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // 211058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // Also, rotated glyphs should have the same absolute advance widths as 212058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // horizontal glyphs and the subpixel flag should not affect glyph shapes. 213058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 214058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // A is the total matrix. 215058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com SkMatrix A; 216058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com fRec.getSingleMatrix(&A); 217058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 218058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // h is where A maps the horizontal baseline. 219058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com SkPoint h = SkPoint::Make(SK_Scalar1, 0); 220058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com A.mapPoints(&h, 1); 221058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 222058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // G is the Givens Matrix for A (rotational matrix where GA[0][1] == 0). 223058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com SkMatrix G; 224058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com SkComputeGivensRotation(h, &G); 225058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 226058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // GA is the matrix A with rotation removed. 227058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com SkMatrix GA(G); 228058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com GA.preConcat(A); 229058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 230058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // realTextSize is the actual device size we want (as opposed to the size the user requested). 231058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // gdiTextSize is the size we request when GDI compatible. 232058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // If the scale is negative, this means the matrix will do the flip anyway. 233058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com SkScalar realTextSize = SkScalarAbs(GA.get(SkMatrix::kMScaleY)); 234058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // Due to floating point math, the lower bits are suspect. Round carefully. 2357c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com SkScalar gdiTextSize = SkScalarRoundToScalar(realTextSize * 64.0f) / 64.0f; 236058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com if (gdiTextSize == 0) { 237058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com gdiTextSize = SK_Scalar1; 238058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com } 239058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 2407c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com bool bitmapRequested = SkToBool(fRec.fFlags & SkScalerContext::kEmbeddedBitmapText_Flag); 2419ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger bool treatLikeBitmap = false; 2427c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com bool axisAlignedBitmap = false; 2437c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com if (bitmapRequested) { 2449ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger // When embedded bitmaps are requested, treat the entire range like 2459ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger // a bitmap strike if the range is gridfit only and contains a bitmap. 2469ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger int bitmapPPEM = SkScalarTruncToInt(gdiTextSize); 2479ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger PPEMRange range = { bitmapPPEM, bitmapPPEM }; 2489ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger expand_range_if_gridfit_only(typeface, bitmapPPEM, &range); 2499ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger treatLikeBitmap = has_bitmap_strike(typeface, range); 2509ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger 2519ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger axisAlignedBitmap = is_axis_aligned(fRec); 2527c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com } 253058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 2547c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com // If the user requested aliased, do so with aliased compatible metrics. 2557c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com if (SkMask::kBW_Format == fRec.fMaskFormat) { 256058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com fTextSizeRender = gdiTextSize; 257d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com fRenderingMode = DWRITE_RENDERING_MODE_ALIASED; 258d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com fTextureType = DWRITE_TEXTURE_ALIASED_1x1; 259058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com fTextSizeMeasure = gdiTextSize; 260058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com fMeasuringMode = DWRITE_MEASURING_MODE_GDI_CLASSIC; 261df1640d413c16abf4527960642aca41581808699bungeman 2627c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com // If we can use a bitmap, use gdi classic rendering and measurement. 2637c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com // This will not always provide a bitmap, but matches expected behavior. 2649ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger } else if (treatLikeBitmap && axisAlignedBitmap) { 2657c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com fTextSizeRender = gdiTextSize; 2667c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com fRenderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC; 2677c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1; 2687c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com fTextSizeMeasure = gdiTextSize; 2697c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com fMeasuringMode = DWRITE_MEASURING_MODE_GDI_CLASSIC; 270df1640d413c16abf4527960642aca41581808699bungeman 2717c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com // If rotated but the horizontal text could have used a bitmap, 2727c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com // render high quality rotated glyphs but measure using bitmap metrics. 2739ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger } else if (treatLikeBitmap) { 274058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com fTextSizeRender = gdiTextSize; 275058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com fRenderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC; 276058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1; 277058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com fTextSizeMeasure = gdiTextSize; 278d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com fMeasuringMode = DWRITE_MEASURING_MODE_GDI_CLASSIC; 2797c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com 2809ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger // Fonts that have hints but no gasp table get non-symmetric rendering. 2819ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger // Usually such fonts have low quality hints which were never tested 2829ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger // with anything but GDI ClearType classic. Such fonts often rely on 2839ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger // drop out control in the y direction in order to be legible. 2849ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger } else if (is_hinted_without_gasp(typeface)) { 2859ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger fTextSizeRender = gdiTextSize; 2869ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger fRenderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL; 2879ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1; 2889ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger fTextSizeMeasure = realTextSize; 2899ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL; 2909ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger 2917c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com // The normal case is to use natural symmetric rendering and linear metrics. 292d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com } else { 293058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com fTextSizeRender = realTextSize; 294d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com fRenderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC; 295d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1; 296058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com fTextSizeMeasure = realTextSize; 297d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL; 298d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com } 299d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com 300d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com if (this->isSubpixel()) { 301058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com fTextSizeMeasure = realTextSize; 302d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL; 303d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com } 304058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 305058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // Remove the realTextSize, as that is the text height scale currently in A. 306058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com SkScalar scale = SkScalarInvert(realTextSize); 307058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 308058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // fSkXform is the total matrix A without the text height scale. 309058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com fSkXform = A; 310058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com fSkXform.preScale(scale, scale); //remove the text height scale. 311058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 312058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com fXform.m11 = SkScalarToFloat(fSkXform.getScaleX()); 313058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com fXform.m12 = SkScalarToFloat(fSkXform.getSkewY()); 314058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com fXform.m21 = SkScalarToFloat(fSkXform.getSkewX()); 315058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com fXform.m22 = SkScalarToFloat(fSkXform.getScaleY()); 316058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com fXform.dx = 0; 317058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com fXform.dy = 0; 318058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 319058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // GsA is the non-rotational part of A without the text height scale. 320058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com SkMatrix GsA(GA); 321058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com GsA.preScale(scale, scale); //remove text height scale, G is rotational so reorders with scale. 322058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 323058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com fGsA.m11 = SkScalarToFloat(GsA.get(SkMatrix::kMScaleX)); 324058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com fGsA.m12 = SkScalarToFloat(GsA.get(SkMatrix::kMSkewY)); // This should be ~0. 325058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com fGsA.m21 = SkScalarToFloat(GsA.get(SkMatrix::kMSkewX)); 326058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com fGsA.m22 = SkScalarToFloat(GsA.get(SkMatrix::kMScaleY)); 327e4ae0bc5caeed52e07c7e5939fa4ac38d9e408abbungeman@google.com fGsA.dx = 0; 328e4ae0bc5caeed52e07c7e5939fa4ac38d9e408abbungeman@google.com fGsA.dy = 0; 329058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com 330058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com // fG_inv is G inverse, which is fairly simple since G is 2x2 rotational. 331058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com fG_inv.setAll(G.get(SkMatrix::kMScaleX), -G.get(SkMatrix::kMSkewX), G.get(SkMatrix::kMTransX), 332058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com -G.get(SkMatrix::kMSkewY), G.get(SkMatrix::kMScaleY), G.get(SkMatrix::kMTransY), 333058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com G.get(SkMatrix::kMPersp0), G.get(SkMatrix::kMPersp1), G.get(SkMatrix::kMPersp2)); 334e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com} 335e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 33630ddd615c447fed73286151b463af20d309c85f1reed@google.comSkScalerContext_DW::~SkScalerContext_DW() { 337e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com} 338e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 33930ddd615c447fed73286151b463af20d309c85f1reed@google.comunsigned SkScalerContext_DW::generateGlyphCount() { 340e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com if (fGlyphCount < 0) { 341e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com fGlyphCount = fTypeface->fDWriteFontFace->GetGlyphCount(); 342e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 343e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com return fGlyphCount; 344e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com} 345e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 34630ddd615c447fed73286151b463af20d309c85f1reed@google.comuint16_t SkScalerContext_DW::generateCharToGlyph(SkUnichar uni) { 347e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com uint16_t index = 0; 348e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com fTypeface->fDWriteFontFace->GetGlyphIndices(reinterpret_cast<UINT32*>(&uni), 1, &index); 349e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com return index; 350e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com} 351e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 35230ddd615c447fed73286151b463af20d309c85f1reed@google.comvoid SkScalerContext_DW::generateAdvance(SkGlyph* glyph) { 353e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com //Delta is the difference between the right/left side bearing metric 354e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com //and where the right/left side bearing ends up after hinting. 355e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com //DirectWrite does not provide this information. 356e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com glyph->fRsbDelta = 0; 357e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com glyph->fLsbDelta = 0; 358d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 359e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com glyph->fAdvanceX = 0; 360e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com glyph->fAdvanceY = 0; 361e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 362e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com uint16_t glyphId = glyph->getGlyphID(); 363e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com DWRITE_GLYPH_METRICS gm; 364d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com 365d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode || 366d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode) 367d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com { 368d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com HRVM(fTypeface->fDWriteFontFace->GetGdiCompatibleGlyphMetrics( 369058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com fTextSizeMeasure, 370d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com 1.0f, // pixelsPerDip 371058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com &fGsA, 372d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode, 373d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com &glyphId, 1, 374d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com &gm), 375d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com "Could not get gdi compatible glyph metrics."); 376d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com } else { 377d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com HRVM(fTypeface->fDWriteFontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm), 378d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com "Could not get design metrics."); 379d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com } 380e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 381e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com DWRITE_FONT_METRICS dwfm; 382e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com fTypeface->fDWriteFontFace->GetMetrics(&dwfm); 383058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com SkScalar advanceX = SkScalarMulDiv(fTextSizeMeasure, 384e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com SkIntToScalar(gm.advanceWidth), 385e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com SkIntToScalar(dwfm.designUnitsPerEm)); 386d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 387e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com SkVector vecs[1] = { { advanceX, 0 } }; 388058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode || 389058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode) 390058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com { 3919ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger // DirectWrite produced 'compatible' metrics, but while close, 3929ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger // the end result is not always an integer as it would be with GDI. 3939ed58377b45739aa8f9dc1b02049ab29c137a838Derek Sollenberger vecs[0].fX = SkScalarRoundToScalar(advanceX); 394058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com fG_inv.mapVectors(vecs, SK_ARRAY_COUNT(vecs)); 395058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com } else { 396058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com fSkXform.mapVectors(vecs, SK_ARRAY_COUNT(vecs)); 397058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com } 398e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 399e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com glyph->fAdvanceX = SkScalarToFixed(vecs[0].fX); 400e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com glyph->fAdvanceY = SkScalarToFixed(vecs[0].fY); 401e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com} 402e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 40330ddd615c447fed73286151b463af20d309c85f1reed@google.comvoid SkScalerContext_DW::generateMetrics(SkGlyph* glyph) { 404e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com glyph->fWidth = 0; 405e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 406e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com this->generateAdvance(glyph); 407e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 408e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com //Measure raster size. 409e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com fXform.dx = SkFixedToFloat(glyph->getSubXFixed()); 410e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com fXform.dy = SkFixedToFloat(glyph->getSubYFixed()); 411e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 412e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com FLOAT advance = 0; 413e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 414e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com UINT16 glyphId = glyph->getGlyphID(); 415e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 416e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com DWRITE_GLYPH_OFFSET offset; 417e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com offset.advanceOffset = 0.0f; 418e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com offset.ascenderOffset = 0.0f; 419e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 420e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com DWRITE_GLYPH_RUN run; 421e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com run.glyphCount = 1; 422e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com run.glyphAdvances = &advance; 423e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com run.fontFace = fTypeface->fDWriteFontFace.get(); 424058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com run.fontEmSize = SkScalarToFloat(fTextSizeRender); 425e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com run.bidiLevel = 0; 426e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com run.glyphIndices = &glyphId; 427e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com run.isSideways = FALSE; 428e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com run.glyphOffsets = &offset; 429e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 430e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis; 4316eddc77f6a0078570471277954c07d73b3a921d8bungeman@google.com HRVM(fTypeface->fFactory->CreateGlyphRunAnalysis( 4326eddc77f6a0078570471277954c07d73b3a921d8bungeman@google.com &run, 4336eddc77f6a0078570471277954c07d73b3a921d8bungeman@google.com 1.0f, // pixelsPerDip, 4346eddc77f6a0078570471277954c07d73b3a921d8bungeman@google.com &fXform, 435d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com fRenderingMode, 436d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com fMeasuringMode, 4376eddc77f6a0078570471277954c07d73b3a921d8bungeman@google.com 0.0f, // baselineOriginX, 4386eddc77f6a0078570471277954c07d73b3a921d8bungeman@google.com 0.0f, // baselineOriginY, 4396eddc77f6a0078570471277954c07d73b3a921d8bungeman@google.com &glyphRunAnalysis), 440e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com "Could not create glyph run analysis."); 441d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 442e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com RECT bbox; 443d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com HRVM(glyphRunAnalysis->GetAlphaTextureBounds(fTextureType, &bbox), 444e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com "Could not get texture bounds."); 445e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 446e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com glyph->fWidth = SkToU16(bbox.right - bbox.left); 447e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com glyph->fHeight = SkToU16(bbox.bottom - bbox.top); 448e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com glyph->fLeft = SkToS16(bbox.left); 449e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com glyph->fTop = SkToS16(bbox.top); 450e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com} 451e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 45230ddd615c447fed73286151b463af20d309c85f1reed@google.comvoid SkScalerContext_DW::generateFontMetrics(SkPaint::FontMetrics* mx, 453d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com SkPaint::FontMetrics* my) { 454e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com if (!(mx || my)) 455e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com return; 456e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 457e1b9bad0711e557e45fee109fb492d19e35e1d38bungeman@google.com if (mx) { 458e1b9bad0711e557e45fee109fb492d19e35e1d38bungeman@google.com sk_bzero(mx, sizeof(*mx)); 459e1b9bad0711e557e45fee109fb492d19e35e1d38bungeman@google.com } 460e1b9bad0711e557e45fee109fb492d19e35e1d38bungeman@google.com if (my) { 461e1b9bad0711e557e45fee109fb492d19e35e1d38bungeman@google.com sk_bzero(my, sizeof(*my)); 462e1b9bad0711e557e45fee109fb492d19e35e1d38bungeman@google.com } 463e1b9bad0711e557e45fee109fb492d19e35e1d38bungeman@google.com 464e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com DWRITE_FONT_METRICS dwfm; 465d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode || 466d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode) 467d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com { 468d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com fTypeface->fDWriteFontFace->GetGdiCompatibleMetrics( 469058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com fTextSizeRender, 470d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com 1.0f, // pixelsPerDip 471d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com &fXform, 472d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com &dwfm); 473d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com } else { 474d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com fTypeface->fDWriteFontFace->GetMetrics(&dwfm); 475d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com } 476e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 477e1b9bad0711e557e45fee109fb492d19e35e1d38bungeman@google.com SkScalar upem = SkIntToScalar(dwfm.designUnitsPerEm); 478e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com if (mx) { 479058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com mx->fTop = -fTextSizeRender * SkIntToScalar(dwfm.ascent) / upem; 4807687578d3a42b528f536c2f3437104fac04c4ae4bungeman@google.com mx->fAscent = mx->fTop; 481058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com mx->fDescent = fTextSizeRender * SkIntToScalar(dwfm.descent) / upem; 4827687578d3a42b528f536c2f3437104fac04c4ae4bungeman@google.com mx->fBottom = mx->fDescent; 483058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com mx->fLeading = fTextSizeRender * SkIntToScalar(dwfm.lineGap) / upem; 484058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com mx->fXHeight = fTextSizeRender * SkIntToScalar(dwfm.xHeight) / upem; 4857584c298e0aff93911b4b7a0bb5b62c47c48b938bungeman@google.com mx->fUnderlineThickness = fTextSizeRender * SkIntToScalar(dwfm.underlineThickness) / upem; 4867584c298e0aff93911b4b7a0bb5b62c47c48b938bungeman@google.com mx->fUnderlinePosition = -(fTextSizeRender * SkIntToScalar(dwfm.underlinePosition) / upem); 4870bc406df48ac6f358ab8dcff08f71fe9c32b79decommit-bot@chromium.org 4880bc406df48ac6f358ab8dcff08f71fe9c32b79decommit-bot@chromium.org mx->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag; 4890bc406df48ac6f358ab8dcff08f71fe9c32b79decommit-bot@chromium.org mx->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag; 490e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 491e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 492e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com if (my) { 4934e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger my->fAscent = -fTextSizeRender * SkIntToScalar(dwfm.ascent) / upem; 494058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com my->fDescent = fTextSizeRender * SkIntToScalar(dwfm.descent) / upem; 495058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com my->fLeading = fTextSizeRender * SkIntToScalar(dwfm.lineGap) / upem; 496058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com my->fXHeight = fTextSizeRender * SkIntToScalar(dwfm.xHeight) / upem; 4977584c298e0aff93911b4b7a0bb5b62c47c48b938bungeman@google.com my->fUnderlineThickness = fTextSizeRender * SkIntToScalar(dwfm.underlineThickness) / upem; 4987584c298e0aff93911b4b7a0bb5b62c47c48b938bungeman@google.com my->fUnderlinePosition = -(fTextSizeRender * SkIntToScalar(dwfm.underlinePosition) / upem); 4990bc406df48ac6f358ab8dcff08f71fe9c32b79decommit-bot@chromium.org 5000bc406df48ac6f358ab8dcff08f71fe9c32b79decommit-bot@chromium.org my->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag; 5010bc406df48ac6f358ab8dcff08f71fe9c32b79decommit-bot@chromium.org my->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag; 5024e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger 5034e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger if (NULL != fTypeface->fDWriteFontFace1.get()) { 5044e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger DWRITE_FONT_METRICS1 dwfm1; 5054e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger fTypeface->fDWriteFontFace1->GetMetrics(&dwfm1); 5064e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger my->fTop = -fTextSizeRender * SkIntToScalar(dwfm1.glyphBoxTop) / upem; 5074e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger my->fBottom = -fTextSizeRender * SkIntToScalar(dwfm1.glyphBoxBottom) / upem; 5084e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger my->fXMin = fTextSizeRender * SkIntToScalar(dwfm1.glyphBoxLeft) / upem; 5094e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger my->fXMax = fTextSizeRender * SkIntToScalar(dwfm1.glyphBoxRight) / upem; 5104e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger 5114e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger my->fMaxCharWidth = my->fXMax - my->fXMin; 5124e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger } else { 5134e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger AutoTDWriteTable<SkOTTableHead> head(fTypeface->fDWriteFontFace.get()); 5144e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger if (head.fExists && 5154e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger head.fSize >= sizeof(SkOTTableHead) && 5164e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger head->version == SkOTTableHead::version1) 5174e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger { 5184e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger my->fTop = -fTextSizeRender * (int16_t)SkEndian_SwapBE16(head->yMax) / upem; 5194e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger my->fBottom = -fTextSizeRender * (int16_t)SkEndian_SwapBE16(head->yMin) / upem; 5204e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger my->fXMin = fTextSizeRender * (int16_t)SkEndian_SwapBE16(head->xMin) / upem; 5214e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger my->fXMax = fTextSizeRender * (int16_t)SkEndian_SwapBE16(head->xMax) / upem; 5224e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger 5234e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger my->fMaxCharWidth = my->fXMax - my->fXMin; 5244e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger } else { 5254e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger my->fTop = my->fAscent; 5264e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger my->fBottom = my->fDescent; 5274e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger } 5284e4a89dab47d74874d6a79c4b34d89ffbfb386afDerek Sollenberger } 529e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 530e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com} 531e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 532e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com/////////////////////////////////////////////////////////////////////////////// 533e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 534e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com#include "SkColorPriv.h" 535e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 536e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.comstatic void bilevel_to_bw(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph) { 537e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com const int width = glyph.fWidth; 538e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com const size_t dstRB = (width + 7) >> 3; 539e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage); 540e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 541e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com int byteCount = width >> 3; 542e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com int bitCount = width & 7; 543e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 544e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com for (int y = 0; y < glyph.fHeight; ++y) { 545e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com if (byteCount > 0) { 546e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com for (int i = 0; i < byteCount; ++i) { 547e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com unsigned byte = 0; 548e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com byte |= src[0] & (1 << 7); 549e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com byte |= src[1] & (1 << 6); 550e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com byte |= src[2] & (1 << 5); 551e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com byte |= src[3] & (1 << 4); 552e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com byte |= src[4] & (1 << 3); 553e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com byte |= src[5] & (1 << 2); 554e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com byte |= src[6] & (1 << 1); 555e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com byte |= src[7] & (1 << 0); 556e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com dst[i] = byte; 557e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com src += 8; 558e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 559e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 560e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com if (bitCount > 0) { 561e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com unsigned byte = 0; 562e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com unsigned mask = 0x80; 563e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com for (int i = 0; i < bitCount; i++) { 564e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com byte |= (src[i]) & mask; 565e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com mask >>= 1; 566e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 567e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com dst[byteCount] = byte; 568e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 569e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com src += bitCount; 570e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com dst += dstRB; 571e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 572e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com} 573e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 574e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.comtemplate<bool APPLY_PREBLEND> 575e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.comstatic void rgb_to_a8(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph, const uint8_t* table8) { 576e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com const size_t dstRB = glyph.rowBytes(); 577e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com const U16CPU width = glyph.fWidth; 578e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage); 579e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 580e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com for (U16CPU y = 0; y < glyph.fHeight; y++) { 581e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com for (U16CPU i = 0; i < width; i++) { 582e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com U8CPU r = *(src++); 583e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com U8CPU g = *(src++); 584e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com U8CPU b = *(src++); 585e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com dst[i] = sk_apply_lut_if<APPLY_PREBLEND>((r + g + b) / 3, table8); 586e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 587e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com dst = (uint8_t*)((char*)dst + dstRB); 588e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 589e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com} 590e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 591e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.comtemplate<bool APPLY_PREBLEND> 592e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.comstatic void rgb_to_lcd16(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph, 593e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) { 594e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com const size_t dstRB = glyph.rowBytes(); 595e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com const U16CPU width = glyph.fWidth; 596e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com uint16_t* SK_RESTRICT dst = static_cast<uint16_t*>(glyph.fImage); 597e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 598e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com for (U16CPU y = 0; y < glyph.fHeight; y++) { 599e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com for (U16CPU i = 0; i < width; i++) { 600e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableR); 601e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableG); 602e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableB); 603e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com dst[i] = SkPack888ToRGB16(r, g, b); 604e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 605e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com dst = (uint16_t*)((char*)dst + dstRB); 606e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 607e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com} 608e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 609e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.comtemplate<bool APPLY_PREBLEND> 610e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.comstatic void rgb_to_lcd32(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph, 611e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) { 612e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com const size_t dstRB = glyph.rowBytes(); 613e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com const U16CPU width = glyph.fWidth; 614e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com SkPMColor* SK_RESTRICT dst = static_cast<SkPMColor*>(glyph.fImage); 615e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 616e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com for (U16CPU y = 0; y < glyph.fHeight; y++) { 617e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com for (U16CPU i = 0; i < width; i++) { 618e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableR); 619e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableG); 620e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableB); 621e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com dst[i] = SkPackARGB32(0xFF, r, g, b); 622e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 623e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com dst = (SkPMColor*)((char*)dst + dstRB); 624e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 625e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com} 626e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 627d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.comconst void* SkScalerContext_DW::drawDWMask(const SkGlyph& glyph) { 628d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com int sizeNeeded = glyph.fWidth * glyph.fHeight; 629d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com if (DWRITE_RENDERING_MODE_ALIASED != fRenderingMode) { 630d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com sizeNeeded *= 3; 631d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com } 632d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com if (sizeNeeded > fBits.count()) { 633d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com fBits.setCount(sizeNeeded); 634d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com } 635d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com 636d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com // erase 637d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com memset(fBits.begin(), 0, sizeNeeded); 638d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com 639d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com fXform.dx = SkFixedToFloat(glyph.getSubXFixed()); 640d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com fXform.dy = SkFixedToFloat(glyph.getSubYFixed()); 641d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com 642d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com FLOAT advance = 0.0f; 643d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com 644d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com UINT16 index = glyph.getGlyphID(); 645d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com 646d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com DWRITE_GLYPH_OFFSET offset; 647d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com offset.advanceOffset = 0.0f; 648d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com offset.ascenderOffset = 0.0f; 649e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 650d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com DWRITE_GLYPH_RUN run; 651d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com run.glyphCount = 1; 652d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com run.glyphAdvances = &advance; 653d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com run.fontFace = fTypeface->fDWriteFontFace.get(); 654058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com run.fontEmSize = SkScalarToFloat(fTextSizeRender); 655d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com run.bidiLevel = 0; 656d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com run.glyphIndices = &index; 657d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com run.isSideways = FALSE; 658d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com run.glyphOffsets = &offset; 659d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com 660d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis; 661d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com HRNM(fTypeface->fFactory->CreateGlyphRunAnalysis(&run, 662d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com 1.0f, // pixelsPerDip, 663d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com &fXform, 664d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com fRenderingMode, 665d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com fMeasuringMode, 666d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com 0.0f, // baselineOriginX, 667d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com 0.0f, // baselineOriginY, 668d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com &glyphRunAnalysis), 669d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com "Could not create glyph run analysis."); 670d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com 671d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com //NOTE: this assumes that the glyph has already been measured 672d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com //with an exact same glyph run analysis. 673d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com RECT bbox; 674d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com bbox.left = glyph.fLeft; 675d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com bbox.top = glyph.fTop; 676d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com bbox.right = glyph.fLeft + glyph.fWidth; 677d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com bbox.bottom = glyph.fTop + glyph.fHeight; 678d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com HRNM(glyphRunAnalysis->CreateAlphaTexture(fTextureType, 679d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com &bbox, 680d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com fBits.begin(), 681d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com sizeNeeded), 682d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com "Could not draw mask."); 683d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com return fBits.begin(); 684d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com} 685d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com 686d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.comvoid SkScalerContext_DW::generateImage(const SkGlyph& glyph) { 687e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com //Create the mask. 688d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com const void* bits = this->drawDWMask(glyph); 689e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com if (!bits) { 690e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com sk_bzero(glyph.fImage, glyph.computeImageSize()); 691e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com return; 692e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 693e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 694e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com //Copy the mask into the glyph. 695e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com const uint8_t* src = (const uint8_t*)bits; 696d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com if (DWRITE_RENDERING_MODE_ALIASED == fRenderingMode) { 697e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com bilevel_to_bw(src, glyph); 698d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com const_cast<SkGlyph&>(glyph).fMaskFormat = SkMask::kBW_Format; 699d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com } else if (!isLCD(fRec)) { 700a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com if (fPreBlend.isApplicable()) { 701a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com rgb_to_a8<true>(src, glyph, fPreBlend.fG); 702e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } else { 703a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com rgb_to_a8<false>(src, glyph, fPreBlend.fG); 704e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 705e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } else if (SkMask::kLCD16_Format == glyph.fMaskFormat) { 706a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com if (fPreBlend.isApplicable()) { 707a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com rgb_to_lcd16<true>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); 708e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } else { 709a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com rgb_to_lcd16<false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); 710e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 711e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } else { 712e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com SkASSERT(SkMask::kLCD32_Format == glyph.fMaskFormat); 713a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com if (fPreBlend.isApplicable()) { 714a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com rgb_to_lcd32<true>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); 715e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } else { 716a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com rgb_to_lcd32<false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); 717e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 718e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com } 719e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com} 720e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 72130ddd615c447fed73286151b463af20d309c85f1reed@google.comvoid SkScalerContext_DW::generatePath(const SkGlyph& glyph, SkPath* path) { 722e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com SkASSERT(&glyph && path); 723e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 724e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com path->reset(); 725e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 726e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com SkTScopedComPtr<IDWriteGeometrySink> geometryToPath; 727e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com HRVM(SkDWriteGeometrySink::Create(path, &geometryToPath), 728e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com "Could not create geometry to path converter."); 729e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com uint16_t glyphId = glyph.getGlyphID(); 730e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com //TODO: convert to<->from DIUs? This would make a difference if hinting. 731e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com //It may not be needed, it appears that DirectWrite only hints at em size. 732058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com HRVM(fTypeface->fDWriteFontFace->GetGlyphRunOutline(SkScalarToFloat(fTextSizeRender), 733e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com &glyphId, 734e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com NULL, //advances 735e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com NULL, //offsets 736e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com 1, //num glyphs 737e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com FALSE, //sideways 738e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com FALSE, //rtl 739e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com geometryToPath.get()), 740e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com "Could not create glyph outline."); 741091f51b794e62942db47ccef6fef143ad1590d12bungeman@google.com 742058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com path->transform(fSkXform); 743e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com} 744