SkScalerContext_win_dw.cpp 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190
  1. /*
  2. * Copyright 2011 Google Inc.
  3. *
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the LICENSE file.
  6. */
  7. #include "src/utils/win/SkDWriteNTDDI_VERSION.h"
  8. #include "include/core/SkTypes.h"
  9. #if defined(SK_BUILD_FOR_WIN)
  10. #undef GetGlyphIndices
  11. #include "include/codec/SkCodec.h"
  12. #include "include/core/SkFontMetrics.h"
  13. #include "include/core/SkPath.h"
  14. #include "include/private/SkMutex.h"
  15. #include "include/private/SkTo.h"
  16. #include "src/core/SkDraw.h"
  17. #include "src/core/SkEndian.h"
  18. #include "src/core/SkGlyph.h"
  19. #include "src/core/SkMaskGamma.h"
  20. #include "src/core/SkRasterClip.h"
  21. #include "src/core/SkScalerContext.h"
  22. #include "src/core/SkSharedMutex.h"
  23. #include "src/ports/SkScalerContext_win_dw.h"
  24. #include "src/ports/SkTypeface_win_dw.h"
  25. #include "src/sfnt/SkOTTable_EBLC.h"
  26. #include "src/sfnt/SkOTTable_EBSC.h"
  27. #include "src/sfnt/SkOTTable_gasp.h"
  28. #include "src/sfnt/SkOTTable_maxp.h"
  29. #include "src/utils/SkMatrix22.h"
  30. #include "src/utils/win/SkDWrite.h"
  31. #include "src/utils/win/SkDWriteGeometrySink.h"
  32. #include "src/utils/win/SkHRESULT.h"
  33. #include "src/utils/win/SkTScopedComPtr.h"
  34. #include <dwrite.h>
  35. #include <dwrite_1.h>
  36. #include <dwrite_3.h>
  37. /* Note:
  38. * In versions 8 and 8.1 of Windows, some calls in DWrite are not thread safe.
  39. * The DWriteFactoryMutex protects the calls that are problematic.
  40. */
  41. static SkSharedMutex DWriteFactoryMutex;
  42. typedef SkAutoSharedMutexExclusive Exclusive;
  43. typedef SkAutoSharedMutexShared Shared;
  44. static bool isLCD(const SkScalerContextRec& rec) {
  45. return SkMask::kLCD16_Format == rec.fMaskFormat;
  46. }
  47. static bool is_hinted(DWriteFontTypeface* typeface) {
  48. Exclusive l(DWriteFactoryMutex);
  49. AutoTDWriteTable<SkOTTableMaximumProfile> maxp(typeface->fDWriteFontFace.get());
  50. if (!maxp.fExists) {
  51. return false;
  52. }
  53. if (maxp.fSize < sizeof(SkOTTableMaximumProfile::Version::TT)) {
  54. return false;
  55. }
  56. if (maxp->version.version != SkOTTableMaximumProfile::Version::TT::VERSION) {
  57. return false;
  58. }
  59. return (0 != maxp->version.tt.maxSizeOfInstructions);
  60. }
  61. /** A GaspRange is inclusive, [min, max]. */
  62. struct GaspRange {
  63. using Behavior = SkOTTableGridAndScanProcedure::GaspRange::behavior;
  64. GaspRange(int min, int max, int version, Behavior flags)
  65. : fMin(min), fMax(max), fVersion(version), fFlags(flags) { }
  66. int fMin;
  67. int fMax;
  68. int fVersion;
  69. Behavior fFlags;
  70. };
  71. bool get_gasp_range(DWriteFontTypeface* typeface, int size, GaspRange* range) {
  72. AutoTDWriteTable<SkOTTableGridAndScanProcedure> gasp(typeface->fDWriteFontFace.get());
  73. if (!gasp.fExists) {
  74. return false;
  75. }
  76. if (gasp.fSize < sizeof(SkOTTableGridAndScanProcedure)) {
  77. return false;
  78. }
  79. if (gasp->version != SkOTTableGridAndScanProcedure::version0 &&
  80. gasp->version != SkOTTableGridAndScanProcedure::version1)
  81. {
  82. return false;
  83. }
  84. uint16_t numRanges = SkEndianSwap16(gasp->numRanges);
  85. if (numRanges > 1024 ||
  86. gasp.fSize < sizeof(SkOTTableGridAndScanProcedure) +
  87. sizeof(SkOTTableGridAndScanProcedure::GaspRange) * numRanges)
  88. {
  89. return false;
  90. }
  91. const SkOTTableGridAndScanProcedure::GaspRange* rangeTable =
  92. SkTAfter<const SkOTTableGridAndScanProcedure::GaspRange>(gasp.get());
  93. int minPPEM = -1;
  94. for (uint16_t i = 0; i < numRanges; ++i, ++rangeTable) {
  95. int maxPPEM = SkEndianSwap16(rangeTable->maxPPEM);
  96. if (minPPEM < size && size <= maxPPEM) {
  97. range->fMin = minPPEM + 1;
  98. range->fMax = maxPPEM;
  99. range->fVersion = SkEndian_SwapBE16(gasp->version);
  100. range->fFlags = rangeTable->flags;
  101. return true;
  102. }
  103. minPPEM = maxPPEM;
  104. }
  105. return false;
  106. }
  107. /** If the rendering mode for the specified 'size' is gridfit, then place
  108. * the gridfit range into 'range'. Otherwise, leave 'range' alone.
  109. */
  110. static bool is_gridfit_only(GaspRange::Behavior flags) {
  111. return flags.raw.value == GaspRange::Behavior::Raw::GridfitMask;
  112. }
  113. static bool has_bitmap_strike(DWriteFontTypeface* typeface, GaspRange range) {
  114. Exclusive l(DWriteFactoryMutex);
  115. {
  116. AutoTDWriteTable<SkOTTableEmbeddedBitmapLocation> eblc(typeface->fDWriteFontFace.get());
  117. if (!eblc.fExists) {
  118. return false;
  119. }
  120. if (eblc.fSize < sizeof(SkOTTableEmbeddedBitmapLocation)) {
  121. return false;
  122. }
  123. if (eblc->version != SkOTTableEmbeddedBitmapLocation::version_initial) {
  124. return false;
  125. }
  126. uint32_t numSizes = SkEndianSwap32(eblc->numSizes);
  127. if (numSizes > 1024 ||
  128. eblc.fSize < sizeof(SkOTTableEmbeddedBitmapLocation) +
  129. sizeof(SkOTTableEmbeddedBitmapLocation::BitmapSizeTable) * numSizes)
  130. {
  131. return false;
  132. }
  133. const SkOTTableEmbeddedBitmapLocation::BitmapSizeTable* sizeTable =
  134. SkTAfter<const SkOTTableEmbeddedBitmapLocation::BitmapSizeTable>(eblc.get());
  135. for (uint32_t i = 0; i < numSizes; ++i, ++sizeTable) {
  136. if (sizeTable->ppemX == sizeTable->ppemY &&
  137. range.fMin <= sizeTable->ppemX && sizeTable->ppemX <= range.fMax)
  138. {
  139. // TODO: determine if we should dig through IndexSubTableArray/IndexSubTable
  140. // to determine the actual number of glyphs with bitmaps.
  141. // TODO: Ensure that the bitmaps actually cover a significant portion of the strike.
  142. // TODO: Ensure that the bitmaps are bi-level?
  143. if (sizeTable->endGlyphIndex >= sizeTable->startGlyphIndex + 3) {
  144. return true;
  145. }
  146. }
  147. }
  148. }
  149. {
  150. AutoTDWriteTable<SkOTTableEmbeddedBitmapScaling> ebsc(typeface->fDWriteFontFace.get());
  151. if (!ebsc.fExists) {
  152. return false;
  153. }
  154. if (ebsc.fSize < sizeof(SkOTTableEmbeddedBitmapScaling)) {
  155. return false;
  156. }
  157. if (ebsc->version != SkOTTableEmbeddedBitmapScaling::version_initial) {
  158. return false;
  159. }
  160. uint32_t numSizes = SkEndianSwap32(ebsc->numSizes);
  161. if (numSizes > 1024 ||
  162. ebsc.fSize < sizeof(SkOTTableEmbeddedBitmapScaling) +
  163. sizeof(SkOTTableEmbeddedBitmapScaling::BitmapScaleTable) * numSizes)
  164. {
  165. return false;
  166. }
  167. const SkOTTableEmbeddedBitmapScaling::BitmapScaleTable* scaleTable =
  168. SkTAfter<const SkOTTableEmbeddedBitmapScaling::BitmapScaleTable>(ebsc.get());
  169. for (uint32_t i = 0; i < numSizes; ++i, ++scaleTable) {
  170. if (scaleTable->ppemX == scaleTable->ppemY &&
  171. range.fMin <= scaleTable->ppemX && scaleTable->ppemX <= range.fMax) {
  172. // EBSC tables are normally only found in bitmap only fonts.
  173. return true;
  174. }
  175. }
  176. }
  177. return false;
  178. }
  179. static bool both_zero(SkScalar a, SkScalar b) {
  180. return 0 == a && 0 == b;
  181. }
  182. // returns false if there is any non-90-rotation or skew
  183. static bool is_axis_aligned(const SkScalerContextRec& rec) {
  184. return 0 == rec.fPreSkewX &&
  185. (both_zero(rec.fPost2x2[0][1], rec.fPost2x2[1][0]) ||
  186. both_zero(rec.fPost2x2[0][0], rec.fPost2x2[1][1]));
  187. }
  188. SkScalerContext_DW::SkScalerContext_DW(sk_sp<DWriteFontTypeface> typefaceRef,
  189. const SkScalerContextEffects& effects,
  190. const SkDescriptor* desc)
  191. : SkScalerContext(std::move(typefaceRef), effects, desc)
  192. , fGlyphCount(-1) {
  193. DWriteFontTypeface* typeface = this->getDWriteTypeface();
  194. fIsColorFont = typeface->fFactory2 &&
  195. typeface->fDWriteFontFace2 &&
  196. typeface->fDWriteFontFace2->IsColorFont();
  197. // In general, all glyphs should use NATURAL_SYMMETRIC
  198. // except when bi-level rendering is requested or there are embedded
  199. // bi-level bitmaps (and the embedded bitmap flag is set and no rotation).
  200. //
  201. // DirectWrite's IDWriteFontFace::GetRecommendedRenderingMode does not do
  202. // this. As a result, determine the actual size of the text and then see if
  203. // there are any embedded bi-level bitmaps of that size. If there are, then
  204. // force bitmaps by requesting bi-level rendering.
  205. //
  206. // FreeType allows for separate ppemX and ppemY, but DirectWrite assumes
  207. // square pixels and only uses ppemY. Therefore the transform must track any
  208. // non-uniform x-scale.
  209. //
  210. // Also, rotated glyphs should have the same absolute advance widths as
  211. // horizontal glyphs and the subpixel flag should not affect glyph shapes.
  212. SkVector scale;
  213. fRec.computeMatrices(SkScalerContextRec::kVertical_PreMatrixScale, &scale, &fSkXform);
  214. fXform.m11 = SkScalarToFloat(fSkXform.getScaleX());
  215. fXform.m12 = SkScalarToFloat(fSkXform.getSkewY());
  216. fXform.m21 = SkScalarToFloat(fSkXform.getSkewX());
  217. fXform.m22 = SkScalarToFloat(fSkXform.getScaleY());
  218. fXform.dx = 0;
  219. fXform.dy = 0;
  220. // realTextSize is the actual device size we want (as opposed to the size the user requested).
  221. // gdiTextSize is the size we request when GDI compatible.
  222. // If the scale is negative, this means the matrix will do the flip anyway.
  223. const SkScalar realTextSize = scale.fY;
  224. // Due to floating point math, the lower bits are suspect. Round carefully.
  225. SkScalar gdiTextSize = SkScalarRoundToScalar(realTextSize * 64.0f) / 64.0f;
  226. if (gdiTextSize == 0) {
  227. gdiTextSize = SK_Scalar1;
  228. }
  229. bool bitmapRequested = SkToBool(fRec.fFlags & SkScalerContext::kEmbeddedBitmapText_Flag);
  230. bool treatLikeBitmap = false;
  231. bool axisAlignedBitmap = false;
  232. if (bitmapRequested) {
  233. // When embedded bitmaps are requested, treat the entire range like
  234. // a bitmap strike if the range is gridfit only and contains a bitmap.
  235. int bitmapPPEM = SkScalarTruncToInt(gdiTextSize);
  236. GaspRange range(bitmapPPEM, bitmapPPEM, 0, GaspRange::Behavior());
  237. if (get_gasp_range(typeface, bitmapPPEM, &range)) {
  238. if (!is_gridfit_only(range.fFlags)) {
  239. range = GaspRange(bitmapPPEM, bitmapPPEM, 0, GaspRange::Behavior());
  240. }
  241. }
  242. treatLikeBitmap = has_bitmap_strike(typeface, range);
  243. axisAlignedBitmap = is_axis_aligned(fRec);
  244. }
  245. GaspRange range(0, 0xFFFF, 0, GaspRange::Behavior());
  246. // If the user requested aliased, do so with aliased compatible metrics.
  247. if (SkMask::kBW_Format == fRec.fMaskFormat) {
  248. fTextSizeRender = gdiTextSize;
  249. fRenderingMode = DWRITE_RENDERING_MODE_ALIASED;
  250. fTextureType = DWRITE_TEXTURE_ALIASED_1x1;
  251. fTextSizeMeasure = gdiTextSize;
  252. fMeasuringMode = DWRITE_MEASURING_MODE_GDI_CLASSIC;
  253. // If we can use a bitmap, use gdi classic rendering and measurement.
  254. // This will not always provide a bitmap, but matches expected behavior.
  255. } else if (treatLikeBitmap && axisAlignedBitmap) {
  256. fTextSizeRender = gdiTextSize;
  257. fRenderingMode = DWRITE_RENDERING_MODE_GDI_CLASSIC;
  258. fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
  259. fTextSizeMeasure = gdiTextSize;
  260. fMeasuringMode = DWRITE_MEASURING_MODE_GDI_CLASSIC;
  261. // If rotated but the horizontal text could have used a bitmap,
  262. // render high quality rotated glyphs but measure using bitmap metrics.
  263. } else if (treatLikeBitmap) {
  264. fTextSizeRender = gdiTextSize;
  265. fRenderingMode = DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC;
  266. fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
  267. fTextSizeMeasure = gdiTextSize;
  268. fMeasuringMode = DWRITE_MEASURING_MODE_GDI_CLASSIC;
  269. // If the font has a gasp table version 1, use it to determine symmetric rendering.
  270. } else if (get_gasp_range(typeface, SkScalarRoundToInt(gdiTextSize), &range) &&
  271. range.fVersion >= 1)
  272. {
  273. fTextSizeRender = realTextSize;
  274. fRenderingMode = range.fFlags.field.SymmetricSmoothing
  275. ? DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
  276. : DWRITE_RENDERING_MODE_NATURAL;
  277. fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
  278. fTextSizeMeasure = realTextSize;
  279. fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL;
  280. // If the requested size is above 20px or there are no bytecode hints, use symmetric rendering.
  281. } else if (realTextSize > SkIntToScalar(20) || !is_hinted(typeface)) {
  282. fTextSizeRender = realTextSize;
  283. fRenderingMode = DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC;
  284. fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
  285. fTextSizeMeasure = realTextSize;
  286. fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL;
  287. // Fonts with hints, no gasp or gasp version 0, and below 20px get non-symmetric rendering.
  288. // Often such fonts have hints which were only tested with GDI ClearType classic.
  289. // Some of these fonts rely on drop out control in the y direction in order to be legible.
  290. // Tenor Sans
  291. // https://fonts.google.com/specimen/Tenor+Sans
  292. // Gill Sans W04
  293. // https://cdn.leagueoflegends.com/lolkit/1.1.9/resources/fonts/gill-sans-w04-book.woff
  294. // https://na.leagueoflegends.com/en/news/game-updates/patch/patch-410-notes
  295. // See https://crbug.com/385897
  296. } else {
  297. fTextSizeRender = gdiTextSize;
  298. fRenderingMode = DWRITE_RENDERING_MODE_NATURAL;
  299. fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
  300. fTextSizeMeasure = realTextSize;
  301. fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL;
  302. }
  303. // DirectWrite2 allows for grayscale hinting.
  304. fAntiAliasMode = DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE;
  305. if (typeface->fFactory2 && typeface->fDWriteFontFace2 &&
  306. SkMask::kA8_Format == fRec.fMaskFormat &&
  307. !(fRec.fFlags & SkScalerContext::kGenA8FromLCD_Flag))
  308. {
  309. // DWRITE_TEXTURE_ALIASED_1x1 is now misnamed, it must also be used with grayscale.
  310. fTextureType = DWRITE_TEXTURE_ALIASED_1x1;
  311. fAntiAliasMode = DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE;
  312. }
  313. // DirectWrite2 allows hinting to be disabled.
  314. fGridFitMode = DWRITE_GRID_FIT_MODE_ENABLED;
  315. if (fRec.getHinting() == SkFontHinting::kNone) {
  316. fGridFitMode = DWRITE_GRID_FIT_MODE_DISABLED;
  317. if (fRenderingMode != DWRITE_RENDERING_MODE_ALIASED) {
  318. fRenderingMode = DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC;
  319. }
  320. }
  321. if (this->isLinearMetrics()) {
  322. fTextSizeMeasure = realTextSize;
  323. fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL;
  324. }
  325. }
  326. SkScalerContext_DW::~SkScalerContext_DW() {
  327. }
  328. unsigned SkScalerContext_DW::generateGlyphCount() {
  329. if (fGlyphCount < 0) {
  330. fGlyphCount = this->getDWriteTypeface()->fDWriteFontFace->GetGlyphCount();
  331. }
  332. return fGlyphCount;
  333. }
  334. bool SkScalerContext_DW::generateAdvance(SkGlyph* glyph) {
  335. glyph->fAdvanceX = 0;
  336. glyph->fAdvanceY = 0;
  337. uint16_t glyphId = glyph->getGlyphID();
  338. DWRITE_GLYPH_METRICS gm;
  339. if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode ||
  340. DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode)
  341. {
  342. Exclusive l(DWriteFactoryMutex);
  343. HRBM(this->getDWriteTypeface()->fDWriteFontFace->GetGdiCompatibleGlyphMetrics(
  344. fTextSizeMeasure,
  345. 1.0f, // pixelsPerDip
  346. // This parameter does not act like the lpmat2 parameter to GetGlyphOutlineW.
  347. // If it did then GsA here and G_inv below to mapVectors.
  348. nullptr,
  349. DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode,
  350. &glyphId, 1,
  351. &gm),
  352. "Could not get gdi compatible glyph metrics.");
  353. } else {
  354. Exclusive l(DWriteFactoryMutex);
  355. HRBM(this->getDWriteTypeface()->fDWriteFontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm),
  356. "Could not get design metrics.");
  357. }
  358. DWRITE_FONT_METRICS dwfm;
  359. {
  360. Shared l(DWriteFactoryMutex);
  361. this->getDWriteTypeface()->fDWriteFontFace->GetMetrics(&dwfm);
  362. }
  363. SkScalar advanceX = fTextSizeMeasure * gm.advanceWidth / dwfm.designUnitsPerEm;
  364. SkVector advance = { advanceX, 0 };
  365. if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode ||
  366. DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode)
  367. {
  368. // DirectWrite produced 'compatible' metrics, but while close,
  369. // the end result is not always an integer as it would be with GDI.
  370. advance.fX = SkScalarRoundToScalar(advance.fX);
  371. }
  372. fSkXform.mapVectors(&advance, 1);
  373. glyph->fAdvanceX = SkScalarToFloat(advance.fX);
  374. glyph->fAdvanceY = SkScalarToFloat(advance.fY);
  375. return true;
  376. }
  377. HRESULT SkScalerContext_DW::getBoundingBox(SkGlyph* glyph,
  378. DWRITE_RENDERING_MODE renderingMode,
  379. DWRITE_TEXTURE_TYPE textureType,
  380. RECT* bbox)
  381. {
  382. //Measure raster size.
  383. fXform.dx = SkFixedToFloat(glyph->getSubXFixed());
  384. fXform.dy = SkFixedToFloat(glyph->getSubYFixed());
  385. FLOAT advance = 0;
  386. UINT16 glyphId = glyph->getGlyphID();
  387. DWRITE_GLYPH_OFFSET offset;
  388. offset.advanceOffset = 0.0f;
  389. offset.ascenderOffset = 0.0f;
  390. DWRITE_GLYPH_RUN run;
  391. run.glyphCount = 1;
  392. run.glyphAdvances = &advance;
  393. run.fontFace = this->getDWriteTypeface()->fDWriteFontFace.get();
  394. run.fontEmSize = SkScalarToFloat(fTextSizeRender);
  395. run.bidiLevel = 0;
  396. run.glyphIndices = &glyphId;
  397. run.isSideways = FALSE;
  398. run.glyphOffsets = &offset;
  399. SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
  400. {
  401. Exclusive l(DWriteFactoryMutex);
  402. // IDWriteFactory2::CreateGlyphRunAnalysis is very bad at aliased glyphs.
  403. if (this->getDWriteTypeface()->fFactory2 &&
  404. (fGridFitMode == DWRITE_GRID_FIT_MODE_DISABLED ||
  405. fAntiAliasMode == DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE))
  406. {
  407. HRM(this->getDWriteTypeface()->fFactory2->CreateGlyphRunAnalysis(
  408. &run,
  409. &fXform,
  410. renderingMode,
  411. fMeasuringMode,
  412. fGridFitMode,
  413. fAntiAliasMode,
  414. 0.0f, // baselineOriginX,
  415. 0.0f, // baselineOriginY,
  416. &glyphRunAnalysis),
  417. "Could not create DW2 glyph run analysis.");
  418. } else {
  419. HRM(this->getDWriteTypeface()->fFactory->CreateGlyphRunAnalysis(&run,
  420. 1.0f, // pixelsPerDip,
  421. &fXform,
  422. renderingMode,
  423. fMeasuringMode,
  424. 0.0f, // baselineOriginX,
  425. 0.0f, // baselineOriginY,
  426. &glyphRunAnalysis),
  427. "Could not create glyph run analysis.");
  428. }
  429. }
  430. {
  431. Shared l(DWriteFactoryMutex);
  432. HRM(glyphRunAnalysis->GetAlphaTextureBounds(textureType, bbox),
  433. "Could not get texture bounds.");
  434. }
  435. return S_OK;
  436. }
  437. bool SkScalerContext_DW::isColorGlyph(const SkGlyph& glyph) {
  438. SkTScopedComPtr<IDWriteColorGlyphRunEnumerator> colorLayer;
  439. return getColorGlyphRun(glyph, &colorLayer);
  440. }
  441. bool SkScalerContext_DW::isPngGlyph(const SkGlyph& glyph) {
  442. if (!this->getDWriteTypeface()->fDWriteFontFace4) {
  443. return false;
  444. }
  445. DWRITE_GLYPH_IMAGE_FORMATS f;
  446. IDWriteFontFace4* fontFace4 = this->getDWriteTypeface()->fDWriteFontFace4.get();
  447. HRBM(fontFace4->GetGlyphImageFormats(glyph.getGlyphID(), 0, UINT32_MAX, &f),
  448. "Cannot get glyph image formats.");
  449. return f & DWRITE_GLYPH_IMAGE_FORMATS_PNG;
  450. }
  451. bool SkScalerContext_DW::getColorGlyphRun(const SkGlyph& glyph,
  452. IDWriteColorGlyphRunEnumerator** colorGlyph)
  453. {
  454. FLOAT advance = 0;
  455. UINT16 glyphId = glyph.getGlyphID();
  456. DWRITE_GLYPH_OFFSET offset;
  457. offset.advanceOffset = 0.0f;
  458. offset.ascenderOffset = 0.0f;
  459. DWRITE_GLYPH_RUN run;
  460. run.glyphCount = 1;
  461. run.glyphAdvances = &advance;
  462. run.fontFace = this->getDWriteTypeface()->fDWriteFontFace.get();
  463. run.fontEmSize = SkScalarToFloat(fTextSizeRender);
  464. run.bidiLevel = 0;
  465. run.glyphIndices = &glyphId;
  466. run.isSideways = FALSE;
  467. run.glyphOffsets = &offset;
  468. HRESULT hr = this->getDWriteTypeface()->fFactory2->TranslateColorGlyphRun(
  469. 0, 0, &run, nullptr, fMeasuringMode, &fXform, 0, colorGlyph);
  470. if (hr == DWRITE_E_NOCOLOR) {
  471. return false;
  472. }
  473. HRBM(hr, "Failed to translate color glyph run");
  474. return true;
  475. }
  476. void SkScalerContext_DW::generateColorMetrics(SkGlyph* glyph) {
  477. SkTScopedComPtr<IDWriteColorGlyphRunEnumerator> colorLayers;
  478. HRVM(getColorGlyphRun(*glyph, &colorLayers), "Could not get color glyph run");
  479. SkASSERT(colorLayers.get());
  480. SkRect bounds = SkRect::MakeEmpty();
  481. BOOL hasNextRun = FALSE;
  482. while (SUCCEEDED(colorLayers->MoveNext(&hasNextRun)) && hasNextRun) {
  483. const DWRITE_COLOR_GLYPH_RUN* colorGlyph;
  484. HRVM(colorLayers->GetCurrentRun(&colorGlyph), "Could not get current color glyph run");
  485. SkPath path;
  486. SkTScopedComPtr<IDWriteGeometrySink> geometryToPath;
  487. HRVM(SkDWriteGeometrySink::Create(&path, &geometryToPath),
  488. "Could not create geometry to path converter.");
  489. {
  490. Exclusive l(DWriteFactoryMutex);
  491. HRVM(colorGlyph->glyphRun.fontFace->GetGlyphRunOutline(
  492. colorGlyph->glyphRun.fontEmSize,
  493. colorGlyph->glyphRun.glyphIndices,
  494. colorGlyph->glyphRun.glyphAdvances,
  495. colorGlyph->glyphRun.glyphOffsets,
  496. colorGlyph->glyphRun.glyphCount,
  497. colorGlyph->glyphRun.isSideways,
  498. colorGlyph->glyphRun.bidiLevel % 2, //rtl
  499. geometryToPath.get()),
  500. "Could not create glyph outline.");
  501. }
  502. bounds.join(path.getBounds());
  503. }
  504. SkMatrix matrix = fSkXform;
  505. if (this->isSubpixel()) {
  506. matrix.postTranslate(SkFixedToScalar(glyph->getSubXFixed()),
  507. SkFixedToScalar(glyph->getSubYFixed()));
  508. }
  509. matrix.mapRect(&bounds);
  510. // Round float bound values into integer.
  511. SkIRect ibounds = bounds.roundOut();
  512. glyph->fWidth = ibounds.fRight - ibounds.fLeft;
  513. glyph->fHeight = ibounds.fBottom - ibounds.fTop;
  514. glyph->fLeft = ibounds.fLeft;
  515. glyph->fTop = ibounds.fTop;
  516. }
  517. namespace {
  518. struct Context {
  519. SkTScopedComPtr<IDWriteFontFace4> fontFace4;
  520. void* glyphDataContext;
  521. Context(IDWriteFontFace4* face4, void* context)
  522. : fontFace4(SkRefComPtr(face4))
  523. , glyphDataContext(context)
  524. {}
  525. };
  526. static void ReleaseProc(const void* ptr, void* context) {
  527. Context* ctx = (Context*)context;
  528. ctx->fontFace4->ReleaseGlyphImageData(ctx->glyphDataContext);
  529. delete ctx;
  530. }
  531. }
  532. void SkScalerContext_DW::generatePngMetrics(SkGlyph* glyph) {
  533. SkASSERT(isPngGlyph(*glyph));
  534. SkASSERT(glyph->fMaskFormat == SkMask::Format::kARGB32_Format);
  535. SkASSERT(this->getDWriteTypeface()->fDWriteFontFace4);
  536. IDWriteFontFace4* fontFace4 = this->getDWriteTypeface()->fDWriteFontFace4.get();
  537. DWRITE_GLYPH_IMAGE_DATA glyphData;
  538. void* glyphDataContext;
  539. HRVM(fontFace4->GetGlyphImageData(glyph->getGlyphID(),
  540. fTextSizeRender,
  541. DWRITE_GLYPH_IMAGE_FORMATS_PNG,
  542. &glyphData,
  543. &glyphDataContext),
  544. "Glyph image data could not be acquired.");
  545. Context* context = new Context(fontFace4, glyphDataContext);
  546. sk_sp<SkData> data = SkData::MakeWithProc(glyphData.imageData,
  547. glyphData.imageDataSize,
  548. &ReleaseProc,
  549. context);
  550. std::unique_ptr<SkCodec> codec = SkCodec::MakeFromData(std::move(data));
  551. if (!codec) {
  552. return;
  553. }
  554. SkImageInfo info = codec->getInfo();
  555. SkRect bounds = SkRect::MakeLTRB(SkIntToScalar(info.bounds().fLeft),
  556. SkIntToScalar(info.bounds().fTop),
  557. SkIntToScalar(info.bounds().fRight),
  558. SkIntToScalar(info.bounds().fBottom));
  559. SkMatrix matrix = fSkXform;
  560. SkScalar scale = fTextSizeRender / glyphData.pixelsPerEm;
  561. matrix.preScale(scale, scale);
  562. matrix.preTranslate(-glyphData.horizontalLeftOrigin.x, -glyphData.horizontalLeftOrigin.y);
  563. if (this->isSubpixel()) {
  564. matrix.postTranslate(SkFixedToScalar(glyph->getSubXFixed()),
  565. SkFixedToScalar(glyph->getSubYFixed()));
  566. }
  567. matrix.mapRect(&bounds);
  568. bounds.roundOut();
  569. glyph->fWidth = bounds.width();
  570. glyph->fHeight = bounds.height();
  571. glyph->fLeft = bounds.left();
  572. glyph->fTop = bounds.top();
  573. return;
  574. }
  575. void SkScalerContext_DW::generateMetrics(SkGlyph* glyph) {
  576. // GetAlphaTextureBounds succeeds but sometimes returns empty bounds like
  577. // { 0x80000000, 0x80000000, 0x80000000, 0x80000000 }
  578. // for small, but not quite zero, sized glyphs.
  579. // Only set as non-empty if the returned bounds are non-empty.
  580. auto glyphCheckAndSetBounds = [](SkGlyph* glyph, const RECT& bbox) {
  581. if (bbox.left >= bbox.right || bbox.top >= bbox.bottom) {
  582. return false;
  583. }
  584. // We're trying to pack left and top into int16_t,
  585. // and width and height into uint16_t, after outsetting by 1.
  586. if (!SkIRect::MakeXYWH(-32767, -32767, 65535, 65535).contains(
  587. SkIRect::MakeLTRB(bbox.left, bbox.top, bbox.right, bbox.bottom))) {
  588. return false;
  589. }
  590. glyph->fWidth = SkToU16(bbox.right - bbox.left);
  591. glyph->fHeight = SkToU16(bbox.bottom - bbox.top);
  592. glyph->fLeft = SkToS16(bbox.left);
  593. glyph->fTop = SkToS16(bbox.top);
  594. return true;
  595. };
  596. glyph->fWidth = 0;
  597. glyph->fHeight = 0;
  598. glyph->fLeft = 0;
  599. glyph->fTop = 0;
  600. glyph->fMaskFormat = fRec.fMaskFormat;
  601. if (!this->generateAdvance(glyph)) {
  602. return;
  603. }
  604. if (fIsColorFont && isColorGlyph(*glyph)) {
  605. glyph->fMaskFormat = SkMask::kARGB32_Format;
  606. generateColorMetrics(glyph);
  607. return;
  608. }
  609. if (fIsColorFont && isPngGlyph(*glyph)) {
  610. glyph->fMaskFormat = SkMask::kARGB32_Format;
  611. generatePngMetrics(glyph);
  612. return;
  613. }
  614. RECT bbox;
  615. HRVM(this->getBoundingBox(glyph, fRenderingMode, fTextureType, &bbox),
  616. "Requested bounding box could not be determined.");
  617. if (glyphCheckAndSetBounds(glyph, bbox)) {
  618. return;
  619. }
  620. // GetAlphaTextureBounds succeeds but returns an empty RECT if there are no
  621. // glyphs of the specified texture type or it is too big for smoothing.
  622. // When this happens, try with the alternate texture type.
  623. if (DWRITE_TEXTURE_ALIASED_1x1 != fTextureType ||
  624. DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE == fAntiAliasMode)
  625. {
  626. HRVM(this->getBoundingBox(glyph,
  627. DWRITE_RENDERING_MODE_ALIASED,
  628. DWRITE_TEXTURE_ALIASED_1x1,
  629. &bbox),
  630. "Fallback bounding box could not be determined.");
  631. if (glyphCheckAndSetBounds(glyph, bbox)) {
  632. glyph->fForceBW = 1;
  633. glyph->fMaskFormat = SkMask::kBW_Format;
  634. }
  635. }
  636. // TODO: handle the case where a request for DWRITE_TEXTURE_ALIASED_1x1
  637. // fails, and try DWRITE_TEXTURE_CLEARTYPE_3x1.
  638. }
  639. void SkScalerContext_DW::generateFontMetrics(SkFontMetrics* metrics) {
  640. if (nullptr == metrics) {
  641. return;
  642. }
  643. sk_bzero(metrics, sizeof(*metrics));
  644. DWRITE_FONT_METRICS dwfm;
  645. if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode ||
  646. DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode)
  647. {
  648. this->getDWriteTypeface()->fDWriteFontFace->GetGdiCompatibleMetrics(
  649. fTextSizeRender,
  650. 1.0f, // pixelsPerDip
  651. &fXform,
  652. &dwfm);
  653. } else {
  654. this->getDWriteTypeface()->fDWriteFontFace->GetMetrics(&dwfm);
  655. }
  656. SkScalar upem = SkIntToScalar(dwfm.designUnitsPerEm);
  657. metrics->fAscent = -fTextSizeRender * SkIntToScalar(dwfm.ascent) / upem;
  658. metrics->fDescent = fTextSizeRender * SkIntToScalar(dwfm.descent) / upem;
  659. metrics->fLeading = fTextSizeRender * SkIntToScalar(dwfm.lineGap) / upem;
  660. metrics->fXHeight = fTextSizeRender * SkIntToScalar(dwfm.xHeight) / upem;
  661. metrics->fCapHeight = fTextSizeRender * SkIntToScalar(dwfm.capHeight) / upem;
  662. metrics->fUnderlineThickness = fTextSizeRender * SkIntToScalar(dwfm.underlineThickness) / upem;
  663. metrics->fUnderlinePosition = -(fTextSizeRender * SkIntToScalar(dwfm.underlinePosition) / upem);
  664. metrics->fStrikeoutThickness = fTextSizeRender * SkIntToScalar(dwfm.strikethroughThickness) / upem;
  665. metrics->fStrikeoutPosition = -(fTextSizeRender * SkIntToScalar(dwfm.strikethroughPosition) / upem);
  666. metrics->fFlags |= SkFontMetrics::kUnderlineThicknessIsValid_Flag;
  667. metrics->fFlags |= SkFontMetrics::kUnderlinePositionIsValid_Flag;
  668. metrics->fFlags |= SkFontMetrics::kStrikeoutThicknessIsValid_Flag;
  669. metrics->fFlags |= SkFontMetrics::kStrikeoutPositionIsValid_Flag;
  670. if (this->getDWriteTypeface()->fDWriteFontFace1.get()) {
  671. DWRITE_FONT_METRICS1 dwfm1;
  672. this->getDWriteTypeface()->fDWriteFontFace1->GetMetrics(&dwfm1);
  673. metrics->fTop = -fTextSizeRender * SkIntToScalar(dwfm1.glyphBoxTop) / upem;
  674. metrics->fBottom = -fTextSizeRender * SkIntToScalar(dwfm1.glyphBoxBottom) / upem;
  675. metrics->fXMin = fTextSizeRender * SkIntToScalar(dwfm1.glyphBoxLeft) / upem;
  676. metrics->fXMax = fTextSizeRender * SkIntToScalar(dwfm1.glyphBoxRight) / upem;
  677. metrics->fMaxCharWidth = metrics->fXMax - metrics->fXMin;
  678. return;
  679. }
  680. AutoTDWriteTable<SkOTTableHead> head(this->getDWriteTypeface()->fDWriteFontFace.get());
  681. if (head.fExists &&
  682. head.fSize >= sizeof(SkOTTableHead) &&
  683. head->version == SkOTTableHead::version1)
  684. {
  685. metrics->fTop = -fTextSizeRender * (int16_t)SkEndian_SwapBE16(head->yMax) / upem;
  686. metrics->fBottom = -fTextSizeRender * (int16_t)SkEndian_SwapBE16(head->yMin) / upem;
  687. metrics->fXMin = fTextSizeRender * (int16_t)SkEndian_SwapBE16(head->xMin) / upem;
  688. metrics->fXMax = fTextSizeRender * (int16_t)SkEndian_SwapBE16(head->xMax) / upem;
  689. metrics->fMaxCharWidth = metrics->fXMax - metrics->fXMin;
  690. return;
  691. }
  692. metrics->fTop = metrics->fAscent;
  693. metrics->fBottom = metrics->fDescent;
  694. }
  695. ///////////////////////////////////////////////////////////////////////////////
  696. #include "include/private/SkColorData.h"
  697. void SkScalerContext_DW::BilevelToBW(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph) {
  698. const int width = glyph.width();
  699. const size_t dstRB = (width + 7) >> 3;
  700. uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage);
  701. int byteCount = width >> 3;
  702. int bitCount = width & 7;
  703. for (int y = 0; y < glyph.height(); ++y) {
  704. if (byteCount > 0) {
  705. for (int i = 0; i < byteCount; ++i) {
  706. unsigned byte = 0;
  707. byte |= src[0] & (1 << 7);
  708. byte |= src[1] & (1 << 6);
  709. byte |= src[2] & (1 << 5);
  710. byte |= src[3] & (1 << 4);
  711. byte |= src[4] & (1 << 3);
  712. byte |= src[5] & (1 << 2);
  713. byte |= src[6] & (1 << 1);
  714. byte |= src[7] & (1 << 0);
  715. dst[i] = byte;
  716. src += 8;
  717. }
  718. }
  719. if (bitCount > 0) {
  720. unsigned byte = 0;
  721. unsigned mask = 0x80;
  722. for (int i = 0; i < bitCount; i++) {
  723. byte |= (src[i]) & mask;
  724. mask >>= 1;
  725. }
  726. dst[byteCount] = byte;
  727. }
  728. src += bitCount;
  729. dst += dstRB;
  730. }
  731. }
  732. template<bool APPLY_PREBLEND>
  733. void SkScalerContext_DW::GrayscaleToA8(const uint8_t* SK_RESTRICT src,
  734. const SkGlyph& glyph,
  735. const uint8_t* table8) {
  736. const size_t dstRB = glyph.rowBytes();
  737. const int width = glyph.width();
  738. uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage);
  739. for (int y = 0; y < glyph.height(); y++) {
  740. for (int i = 0; i < width; i++) {
  741. U8CPU a = *(src++);
  742. dst[i] = sk_apply_lut_if<APPLY_PREBLEND>(a, table8);
  743. }
  744. dst = SkTAddOffset<uint8_t>(dst, dstRB);
  745. }
  746. }
  747. template<bool APPLY_PREBLEND>
  748. void SkScalerContext_DW::RGBToA8(const uint8_t* SK_RESTRICT src,
  749. const SkGlyph& glyph,
  750. const uint8_t* table8) {
  751. const size_t dstRB = glyph.rowBytes();
  752. const int width = glyph.width();
  753. uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage);
  754. for (int y = 0; y < glyph.height(); y++) {
  755. for (int i = 0; i < width; i++) {
  756. U8CPU r = *(src++);
  757. U8CPU g = *(src++);
  758. U8CPU b = *(src++);
  759. dst[i] = sk_apply_lut_if<APPLY_PREBLEND>((r + g + b) / 3, table8);
  760. }
  761. dst = SkTAddOffset<uint8_t>(dst, dstRB);
  762. }
  763. }
  764. template<bool APPLY_PREBLEND, bool RGB>
  765. void SkScalerContext_DW::RGBToLcd16(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph,
  766. const uint8_t* tableR, const uint8_t* tableG,
  767. const uint8_t* tableB) {
  768. const size_t dstRB = glyph.rowBytes();
  769. const int width = glyph.width();
  770. uint16_t* SK_RESTRICT dst = static_cast<uint16_t*>(glyph.fImage);
  771. for (int y = 0; y < glyph.height(); y++) {
  772. for (int i = 0; i < width; i++) {
  773. U8CPU r, g, b;
  774. if (RGB) {
  775. r = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableR);
  776. g = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableG);
  777. b = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableB);
  778. } else {
  779. b = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableB);
  780. g = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableG);
  781. r = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableR);
  782. }
  783. dst[i] = SkPack888ToRGB16(r, g, b);
  784. }
  785. dst = SkTAddOffset<uint16_t>(dst, dstRB);
  786. }
  787. }
  788. const void* SkScalerContext_DW::drawDWMask(const SkGlyph& glyph,
  789. DWRITE_RENDERING_MODE renderingMode,
  790. DWRITE_TEXTURE_TYPE textureType)
  791. {
  792. int sizeNeeded = glyph.width() * glyph.height();
  793. if (DWRITE_TEXTURE_CLEARTYPE_3x1 == textureType) {
  794. sizeNeeded *= 3;
  795. }
  796. if (sizeNeeded > fBits.count()) {
  797. fBits.setCount(sizeNeeded);
  798. }
  799. // erase
  800. memset(fBits.begin(), 0, sizeNeeded);
  801. fXform.dx = SkFixedToFloat(glyph.getSubXFixed());
  802. fXform.dy = SkFixedToFloat(glyph.getSubYFixed());
  803. FLOAT advance = 0.0f;
  804. UINT16 index = glyph.getGlyphID();
  805. DWRITE_GLYPH_OFFSET offset;
  806. offset.advanceOffset = 0.0f;
  807. offset.ascenderOffset = 0.0f;
  808. DWRITE_GLYPH_RUN run;
  809. run.glyphCount = 1;
  810. run.glyphAdvances = &advance;
  811. run.fontFace = this->getDWriteTypeface()->fDWriteFontFace.get();
  812. run.fontEmSize = SkScalarToFloat(fTextSizeRender);
  813. run.bidiLevel = 0;
  814. run.glyphIndices = &index;
  815. run.isSideways = FALSE;
  816. run.glyphOffsets = &offset;
  817. {
  818. SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
  819. {
  820. Exclusive l(DWriteFactoryMutex);
  821. // IDWriteFactory2::CreateGlyphRunAnalysis is very bad at aliased glyphs.
  822. if (this->getDWriteTypeface()->fFactory2 &&
  823. (fGridFitMode == DWRITE_GRID_FIT_MODE_DISABLED ||
  824. fAntiAliasMode == DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE))
  825. {
  826. HRNM(this->getDWriteTypeface()->fFactory2->CreateGlyphRunAnalysis(&run,
  827. &fXform,
  828. renderingMode,
  829. fMeasuringMode,
  830. fGridFitMode,
  831. fAntiAliasMode,
  832. 0.0f, // baselineOriginX,
  833. 0.0f, // baselineOriginY,
  834. &glyphRunAnalysis),
  835. "Could not create DW2 glyph run analysis.");
  836. } else {
  837. HRNM(this->getDWriteTypeface()->fFactory->CreateGlyphRunAnalysis(&run,
  838. 1.0f, // pixelsPerDip,
  839. &fXform,
  840. renderingMode,
  841. fMeasuringMode,
  842. 0.0f, // baselineOriginX,
  843. 0.0f, // baselineOriginY,
  844. &glyphRunAnalysis),
  845. "Could not create glyph run analysis.");
  846. }
  847. }
  848. //NOTE: this assumes that the glyph has already been measured
  849. //with an exact same glyph run analysis.
  850. RECT bbox;
  851. bbox.left = glyph.left();
  852. bbox.top = glyph.top();
  853. bbox.right = glyph.left() + glyph.width();
  854. bbox.bottom = glyph.top() + glyph.height();
  855. {
  856. Shared l(DWriteFactoryMutex);
  857. HRNM(glyphRunAnalysis->CreateAlphaTexture(textureType,
  858. &bbox,
  859. fBits.begin(),
  860. sizeNeeded),
  861. "Could not draw mask.");
  862. }
  863. }
  864. return fBits.begin();
  865. }
  866. void SkScalerContext_DW::generateColorGlyphImage(const SkGlyph& glyph) {
  867. SkASSERT(isColorGlyph(glyph));
  868. SkASSERT(glyph.fMaskFormat == SkMask::Format::kARGB32_Format);
  869. memset(glyph.fImage, 0, glyph.imageSize());
  870. SkTScopedComPtr<IDWriteColorGlyphRunEnumerator> colorLayers;
  871. getColorGlyphRun(glyph, &colorLayers);
  872. SkASSERT(colorLayers.get());
  873. SkMatrix matrix = fSkXform;
  874. matrix.postTranslate(-SkIntToScalar(glyph.left()), -SkIntToScalar(glyph.top()));
  875. if (this->isSubpixel()) {
  876. matrix.postTranslate(SkFixedToScalar(glyph.getSubXFixed()),
  877. SkFixedToScalar(glyph.getSubYFixed()));
  878. }
  879. SkRasterClip rc(SkIRect::MakeWH(glyph.width(), glyph.height()));
  880. SkDraw draw;
  881. draw.fDst = SkPixmap(SkImageInfo::MakeN32(glyph.width(), glyph.height(), kPremul_SkAlphaType),
  882. glyph.fImage,
  883. glyph.rowBytesUsingFormat(SkMask::Format::kARGB32_Format));
  884. draw.fMatrix = &matrix;
  885. draw.fRC = &rc;
  886. SkPaint paint;
  887. paint.setAntiAlias(fRenderingMode != DWRITE_RENDERING_MODE_ALIASED);
  888. BOOL hasNextRun = FALSE;
  889. while (SUCCEEDED(colorLayers->MoveNext(&hasNextRun)) && hasNextRun) {
  890. const DWRITE_COLOR_GLYPH_RUN* colorGlyph;
  891. HRVM(colorLayers->GetCurrentRun(&colorGlyph), "Could not get current color glyph run");
  892. SkColor color;
  893. if (colorGlyph->paletteIndex != 0xffff) {
  894. color = SkColorSetARGB(sk_float_round2int(colorGlyph->runColor.a * 255),
  895. sk_float_round2int(colorGlyph->runColor.r * 255),
  896. sk_float_round2int(colorGlyph->runColor.g * 255),
  897. sk_float_round2int(colorGlyph->runColor.b * 255));
  898. } else {
  899. // If all components of runColor are 0 or (equivalently) paletteIndex is 0xFFFF then
  900. // the 'current brush' is used. fRec.getLuminanceColor() is kinda sorta what is wanted
  901. // here, but not really, it will often be the wrong value because it wan't designed for
  902. // this.
  903. // TODO: implement this fully, bug.skia.org/5788
  904. color = fRec.getLuminanceColor();
  905. }
  906. paint.setColor(color);
  907. SkPath path;
  908. SkTScopedComPtr<IDWriteGeometrySink> geometryToPath;
  909. HRVM(SkDWriteGeometrySink::Create(&path, &geometryToPath),
  910. "Could not create geometry to path converter.");
  911. {
  912. Exclusive l(DWriteFactoryMutex);
  913. HRVM(colorGlyph->glyphRun.fontFace->GetGlyphRunOutline(
  914. colorGlyph->glyphRun.fontEmSize,
  915. colorGlyph->glyphRun.glyphIndices,
  916. colorGlyph->glyphRun.glyphAdvances,
  917. colorGlyph->glyphRun.glyphOffsets,
  918. colorGlyph->glyphRun.glyphCount,
  919. colorGlyph->glyphRun.isSideways,
  920. colorGlyph->glyphRun.bidiLevel % 2, //rtl
  921. geometryToPath.get()),
  922. "Could not create glyph outline.");
  923. }
  924. draw.drawPath(path, paint, nullptr, true /* pathIsMutable */);
  925. }
  926. }
  927. void SkScalerContext_DW::generatePngGlyphImage(const SkGlyph& glyph) {
  928. SkASSERT(isPngGlyph(glyph));
  929. SkASSERT(glyph.fMaskFormat == SkMask::Format::kARGB32_Format);
  930. SkASSERT(this->getDWriteTypeface()->fDWriteFontFace4);
  931. IDWriteFontFace4* fontFace4 = this->getDWriteTypeface()->fDWriteFontFace4.get();
  932. DWRITE_GLYPH_IMAGE_DATA glyphData;
  933. void* glyphDataContext;
  934. HRVM(fontFace4->GetGlyphImageData(glyph.getGlyphID(),
  935. fTextSizeRender,
  936. DWRITE_GLYPH_IMAGE_FORMATS_PNG,
  937. &glyphData,
  938. &glyphDataContext),
  939. "Glyph image data could not be acquired.");
  940. Context* context = new Context(fontFace4, glyphDataContext);
  941. sk_sp<SkData> data = SkData::MakeWithProc(glyphData.imageData,
  942. glyphData.imageDataSize,
  943. &ReleaseProc,
  944. context);
  945. sk_sp<SkImage> image = SkImage::MakeFromEncoded(std::move(data));
  946. SkBitmap dstBitmap;
  947. dstBitmap.setInfo(SkImageInfo::Make(glyph.width(), glyph.height(),
  948. kN32_SkColorType,
  949. kPremul_SkAlphaType),
  950. glyph.rowBytes());
  951. dstBitmap.setPixels(glyph.fImage);
  952. SkCanvas canvas(dstBitmap);
  953. canvas.clear(SK_ColorTRANSPARENT);
  954. canvas.translate(-glyph.left(), -glyph.top());
  955. if (this->isSubpixel()) {
  956. canvas.translate(SkFixedToScalar(glyph.getSubXFixed()),
  957. SkFixedToScalar(glyph.getSubYFixed()));
  958. }
  959. canvas.concat(fSkXform);
  960. SkScalar ratio = fTextSizeRender / glyphData.pixelsPerEm;
  961. canvas.scale(ratio, ratio);
  962. canvas.translate(-glyphData.horizontalLeftOrigin.x, -glyphData.horizontalLeftOrigin.y);
  963. canvas.drawImage(image, 0, 0, nullptr);
  964. }
  965. void SkScalerContext_DW::generateImage(const SkGlyph& glyph) {
  966. //Create the mask.
  967. DWRITE_RENDERING_MODE renderingMode = fRenderingMode;
  968. DWRITE_TEXTURE_TYPE textureType = fTextureType;
  969. if (glyph.fForceBW) {
  970. renderingMode = DWRITE_RENDERING_MODE_ALIASED;
  971. textureType = DWRITE_TEXTURE_ALIASED_1x1;
  972. }
  973. if (SkMask::kARGB32_Format == glyph.fMaskFormat) {
  974. if (fIsColorFont) {
  975. if (isColorGlyph(glyph)) {
  976. generateColorGlyphImage(glyph);
  977. return;
  978. } else if (isPngGlyph(glyph)) {
  979. generatePngGlyphImage(glyph);
  980. return;
  981. }
  982. }
  983. SkDEBUGFAIL("Could not generate image from the given color font format.");
  984. return;
  985. }
  986. const void* bits = this->drawDWMask(glyph, renderingMode, textureType);
  987. if (!bits) {
  988. sk_bzero(glyph.fImage, glyph.imageSize());
  989. return;
  990. }
  991. //Copy the mask into the glyph.
  992. const uint8_t* src = (const uint8_t*)bits;
  993. if (DWRITE_RENDERING_MODE_ALIASED == renderingMode) {
  994. SkASSERT(SkMask::kBW_Format == glyph.fMaskFormat);
  995. SkASSERT(DWRITE_TEXTURE_ALIASED_1x1 == textureType);
  996. BilevelToBW(src, glyph);
  997. } else if (!isLCD(fRec)) {
  998. if (textureType == DWRITE_TEXTURE_ALIASED_1x1) {
  999. if (fPreBlend.isApplicable()) {
  1000. GrayscaleToA8<true>(src, glyph, fPreBlend.fG);
  1001. } else {
  1002. GrayscaleToA8<false>(src, glyph, fPreBlend.fG);
  1003. }
  1004. } else {
  1005. if (fPreBlend.isApplicable()) {
  1006. RGBToA8<true>(src, glyph, fPreBlend.fG);
  1007. } else {
  1008. RGBToA8<false>(src, glyph, fPreBlend.fG);
  1009. }
  1010. }
  1011. } else {
  1012. SkASSERT(SkMask::kLCD16_Format == glyph.fMaskFormat);
  1013. if (fPreBlend.isApplicable()) {
  1014. if (fRec.fFlags & SkScalerContext::kLCD_BGROrder_Flag) {
  1015. RGBToLcd16<true, false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
  1016. } else {
  1017. RGBToLcd16<true, true>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
  1018. }
  1019. } else {
  1020. if (fRec.fFlags & SkScalerContext::kLCD_BGROrder_Flag) {
  1021. RGBToLcd16<false, false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
  1022. } else {
  1023. RGBToLcd16<false, true>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
  1024. }
  1025. }
  1026. }
  1027. }
  1028. bool SkScalerContext_DW::generatePath(SkGlyphID glyph, SkPath* path) {
  1029. SkASSERT(path);
  1030. path->reset();
  1031. SkTScopedComPtr<IDWriteGeometrySink> geometryToPath;
  1032. HRBM(SkDWriteGeometrySink::Create(path, &geometryToPath),
  1033. "Could not create geometry to path converter.");
  1034. UINT16 glyphId = SkTo<UINT16>(glyph);
  1035. {
  1036. Exclusive l(DWriteFactoryMutex);
  1037. //TODO: convert to<->from DIUs? This would make a difference if hinting.
  1038. //It may not be needed, it appears that DirectWrite only hints at em size.
  1039. HRBM(this->getDWriteTypeface()->fDWriteFontFace->GetGlyphRunOutline(
  1040. SkScalarToFloat(fTextSizeRender),
  1041. &glyphId,
  1042. nullptr, //advances
  1043. nullptr, //offsets
  1044. 1, //num glyphs
  1045. FALSE, //sideways
  1046. FALSE, //rtl
  1047. geometryToPath.get()),
  1048. "Could not create glyph outline.");
  1049. }
  1050. path->transform(fSkXform);
  1051. return true;
  1052. }
  1053. #endif//defined(SK_BUILD_FOR_WIN)