Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(54)

Side by Side Diff: src/ports/SkFontHost_win_dw.cpp

Issue 315173004: Rename SkFontHost_win_dw.cpp SkScalerContext. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « gyp/ports.gyp ('k') | src/ports/SkScalerContext_win_dw.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
8 #include "SkTypes.h"
9 #undef GetGlyphIndices
10
11 #include "SkDWrite.h"
12 #include "SkDWriteGeometrySink.h"
13 #include "SkEndian.h"
14 #include "SkGlyph.h"
15 #include "SkHRESULT.h"
16 #include "SkMaskGamma.h"
17 #include "SkMatrix22.h"
18 #include "SkOTTable_EBLC.h"
19 #include "SkOTTable_EBSC.h"
20 #include "SkPath.h"
21 #include "SkScalerContext.h"
22 #include "SkScalerContext_win_dw.h"
23 #include "SkTScopedComPtr.h"
24 #include "SkTypeface_win_dw.h"
25
26 #include <dwrite.h>
27
28 static bool isLCD(const SkScalerContext::Rec& rec) {
29 return SkMask::kLCD16_Format == rec.fMaskFormat ||
30 SkMask::kLCD32_Format == rec.fMaskFormat;
31 }
32
33 static bool hasBitmapStrike(DWriteFontTypeface* typeface, int size) {
34 {
35 AutoTDWriteTable<SkOTTableEmbeddedBitmapLocation> eblc(typeface->fDWrite FontFace.get());
36 if (!eblc.fExists) {
37 return false;
38 }
39 if (eblc.fSize < sizeof(SkOTTableEmbeddedBitmapLocation)) {
40 return false;
41 }
42 if (eblc->version != SkOTTableEmbeddedBitmapLocation::version_initial) {
43 return false;
44 }
45
46 uint32_t numSizes = SkEndianSwap32(eblc->numSizes);
47 if (eblc.fSize < sizeof(SkOTTableEmbeddedBitmapLocation) +
48 sizeof(SkOTTableEmbeddedBitmapLocation::BitmapSizeTable ) * numSizes)
49 {
50 return false;
51 }
52
53 const SkOTTableEmbeddedBitmapLocation::BitmapSizeTable* sizeTable =
54 SkTAfter<const SkOTTableEmbeddedBitmapLocation::BitmapSizeTable> (eblc.get());
55 for (uint32_t i = 0; i < numSizes; ++i, ++sizeTable) {
56 if (sizeTable->ppemX == size && sizeTable->ppemY == size) {
57 // TODO: determine if we should dig through IndexSubTableArray/I ndexSubTable
58 // to determine the actual number of glyphs with bitmaps.
59
60 // TODO: Ensure that the bitmaps actually cover a significant po rtion of the strike.
61
62 //TODO: Endure that the bitmaps are bi-level.
63 if (sizeTable->endGlyphIndex >= sizeTable->startGlyphIndex + 3) {
64 return true;
65 }
66 }
67 }
68 }
69
70 {
71 AutoTDWriteTable<SkOTTableEmbeddedBitmapScaling> ebsc(typeface->fDWriteF ontFace.get());
72 if (!ebsc.fExists) {
73 return false;
74 }
75 if (ebsc.fSize < sizeof(SkOTTableEmbeddedBitmapScaling)) {
76 return false;
77 }
78 if (ebsc->version != SkOTTableEmbeddedBitmapScaling::version_initial) {
79 return false;
80 }
81
82 uint32_t numSizes = SkEndianSwap32(ebsc->numSizes);
83 if (ebsc.fSize < sizeof(SkOTTableEmbeddedBitmapScaling) +
84 sizeof(SkOTTableEmbeddedBitmapScaling::BitmapScaleTable ) * numSizes)
85 {
86 return false;
87 }
88
89 const SkOTTableEmbeddedBitmapScaling::BitmapScaleTable* scaleTable =
90 SkTAfter<const SkOTTableEmbeddedBitmapScaling::BitmapScaleTable> (ebsc.get());
91 for (uint32_t i = 0; i < numSizes; ++i, ++scaleTable) {
92 if (scaleTable->ppemX == size && scaleTable->ppemY == size) {
93 // EBSC tables are normally only found in bitmap only fonts.
94 return true;
95 }
96 }
97 }
98
99 return false;
100 }
101
102 static bool bothZero(SkScalar a, SkScalar b) {
103 return 0 == a && 0 == b;
104 }
105
106 // returns false if there is any non-90-rotation or skew
107 static bool isAxisAligned(const SkScalerContext::Rec& rec) {
108 return 0 == rec.fPreSkewX &&
109 (bothZero(rec.fPost2x2[0][1], rec.fPost2x2[1][0]) ||
110 bothZero(rec.fPost2x2[0][0], rec.fPost2x2[1][1]));
111 }
112
113 SkScalerContext_DW::SkScalerContext_DW(DWriteFontTypeface* typeface,
114 const SkDescriptor* desc)
115 : SkScalerContext(typeface, desc)
116 , fTypeface(SkRef(typeface))
117 , fGlyphCount(-1) {
118
119 // In general, all glyphs should use CLEARTYPE_NATURAL_SYMMETRIC
120 // except when bi-level rendering is requested or there are embedded
121 // bi-level bitmaps (and the embedded bitmap flag is set and no rotation).
122 //
123 // DirectWrite's IDWriteFontFace::GetRecommendedRenderingMode does not do
124 // this. As a result, determine the actual size of the text and then see if
125 // there are any embedded bi-level bitmaps of that size. If there are, then
126 // force bitmaps by requesting bi-level rendering.
127 //
128 // FreeType allows for separate ppemX and ppemY, but DirectWrite assumes
129 // square pixels and only uses ppemY. Therefore the transform must track any
130 // non-uniform x-scale.
131 //
132 // Also, rotated glyphs should have the same absolute advance widths as
133 // horizontal glyphs and the subpixel flag should not affect glyph shapes.
134
135 // A is the total matrix.
136 SkMatrix A;
137 fRec.getSingleMatrix(&A);
138
139 // h is where A maps the horizontal baseline.
140 SkPoint h = SkPoint::Make(SK_Scalar1, 0);
141 A.mapPoints(&h, 1);
142
143 // G is the Givens Matrix for A (rotational matrix where GA[0][1] == 0).
144 SkMatrix G;
145 SkComputeGivensRotation(h, &G);
146
147 // GA is the matrix A with rotation removed.
148 SkMatrix GA(G);
149 GA.preConcat(A);
150
151 // realTextSize is the actual device size we want (as opposed to the size th e user requested).
152 // gdiTextSize is the size we request when GDI compatible.
153 // If the scale is negative, this means the matrix will do the flip anyway.
154 SkScalar realTextSize = SkScalarAbs(GA.get(SkMatrix::kMScaleY));
155 // Due to floating point math, the lower bits are suspect. Round carefully.
156 SkScalar gdiTextSize = SkScalarRoundToScalar(realTextSize * 64.0f) / 64.0f;
157 if (gdiTextSize == 0) {
158 gdiTextSize = SK_Scalar1;
159 }
160
161 bool bitmapRequested = SkToBool(fRec.fFlags & SkScalerContext::kEmbeddedBitm apText_Flag);
162 bool hasBitmap = false;
163 bool axisAlignedBitmap = false;
164 if (bitmapRequested) {
165 hasBitmap = hasBitmapStrike(typeface, SkScalarTruncToInt(gdiTextSize));
166 axisAlignedBitmap = isAxisAligned(fRec);
167 }
168
169 // If the user requested aliased, do so with aliased compatible metrics.
170 if (SkMask::kBW_Format == fRec.fMaskFormat) {
171 fTextSizeRender = gdiTextSize;
172 fRenderingMode = DWRITE_RENDERING_MODE_ALIASED;
173 fTextureType = DWRITE_TEXTURE_ALIASED_1x1;
174 fTextSizeMeasure = gdiTextSize;
175 fMeasuringMode = DWRITE_MEASURING_MODE_GDI_CLASSIC;
176
177 // If we can use a bitmap, use gdi classic rendering and measurement.
178 // This will not always provide a bitmap, but matches expected behavior.
179 } else if (hasBitmap && axisAlignedBitmap) {
180 fTextSizeRender = gdiTextSize;
181 fRenderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC;
182 fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
183 fTextSizeMeasure = gdiTextSize;
184 fMeasuringMode = DWRITE_MEASURING_MODE_GDI_CLASSIC;
185
186 // If rotated but the horizontal text could have used a bitmap,
187 // render high quality rotated glyphs but measure using bitmap metrics.
188 } else if (hasBitmap) {
189 fTextSizeRender = gdiTextSize;
190 fRenderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
191 fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
192 fTextSizeMeasure = gdiTextSize;
193 fMeasuringMode = DWRITE_MEASURING_MODE_GDI_CLASSIC;
194
195 // The normal case is to use natural symmetric rendering and linear metrics.
196 } else {
197 fTextSizeRender = realTextSize;
198 fRenderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
199 fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
200 fTextSizeMeasure = realTextSize;
201 fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL;
202 }
203
204 if (this->isSubpixel()) {
205 fTextSizeMeasure = realTextSize;
206 fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL;
207 }
208
209 // Remove the realTextSize, as that is the text height scale currently in A.
210 SkScalar scale = SkScalarInvert(realTextSize);
211
212 // fSkXform is the total matrix A without the text height scale.
213 fSkXform = A;
214 fSkXform.preScale(scale, scale); //remove the text height scale.
215
216 fXform.m11 = SkScalarToFloat(fSkXform.getScaleX());
217 fXform.m12 = SkScalarToFloat(fSkXform.getSkewY());
218 fXform.m21 = SkScalarToFloat(fSkXform.getSkewX());
219 fXform.m22 = SkScalarToFloat(fSkXform.getScaleY());
220 fXform.dx = 0;
221 fXform.dy = 0;
222
223 // GsA is the non-rotational part of A without the text height scale.
224 SkMatrix GsA(GA);
225 GsA.preScale(scale, scale); //remove text height scale, G is rotational so r eorders with scale.
226
227 fGsA.m11 = SkScalarToFloat(GsA.get(SkMatrix::kMScaleX));
228 fGsA.m12 = SkScalarToFloat(GsA.get(SkMatrix::kMSkewY)); // This should be ~0 .
229 fGsA.m21 = SkScalarToFloat(GsA.get(SkMatrix::kMSkewX));
230 fGsA.m22 = SkScalarToFloat(GsA.get(SkMatrix::kMScaleY));
231 fGsA.dx = 0;
232 fGsA.dy = 0;
233
234 // fG_inv is G inverse, which is fairly simple since G is 2x2 rotational.
235 fG_inv.setAll(G.get(SkMatrix::kMScaleX), -G.get(SkMatrix::kMSkewX), G.get(Sk Matrix::kMTransX),
236 -G.get(SkMatrix::kMSkewY), G.get(SkMatrix::kMScaleY), G.get(Sk Matrix::kMTransY),
237 G.get(SkMatrix::kMPersp0), G.get(SkMatrix::kMPersp1), G.get(Sk Matrix::kMPersp2));
238 }
239
240 SkScalerContext_DW::~SkScalerContext_DW() {
241 }
242
243 unsigned SkScalerContext_DW::generateGlyphCount() {
244 if (fGlyphCount < 0) {
245 fGlyphCount = fTypeface->fDWriteFontFace->GetGlyphCount();
246 }
247 return fGlyphCount;
248 }
249
250 uint16_t SkScalerContext_DW::generateCharToGlyph(SkUnichar uni) {
251 uint16_t index = 0;
252 fTypeface->fDWriteFontFace->GetGlyphIndices(reinterpret_cast<UINT32*>(&uni), 1, &index);
253 return index;
254 }
255
256 void SkScalerContext_DW::generateAdvance(SkGlyph* glyph) {
257 //Delta is the difference between the right/left side bearing metric
258 //and where the right/left side bearing ends up after hinting.
259 //DirectWrite does not provide this information.
260 glyph->fRsbDelta = 0;
261 glyph->fLsbDelta = 0;
262
263 glyph->fAdvanceX = 0;
264 glyph->fAdvanceY = 0;
265
266 uint16_t glyphId = glyph->getGlyphID();
267 DWRITE_GLYPH_METRICS gm;
268
269 if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode ||
270 DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode)
271 {
272 HRVM(fTypeface->fDWriteFontFace->GetGdiCompatibleGlyphMetrics(
273 fTextSizeMeasure,
274 1.0f, // pixelsPerDip
275 &fGsA,
276 DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode,
277 &glyphId, 1,
278 &gm),
279 "Could not get gdi compatible glyph metrics.");
280 } else {
281 HRVM(fTypeface->fDWriteFontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm) ,
282 "Could not get design metrics.");
283 }
284
285 DWRITE_FONT_METRICS dwfm;
286 fTypeface->fDWriteFontFace->GetMetrics(&dwfm);
287 SkScalar advanceX = SkScalarMulDiv(fTextSizeMeasure,
288 SkIntToScalar(gm.advanceWidth),
289 SkIntToScalar(dwfm.designUnitsPerEm));
290
291 if (!this->isSubpixel()) {
292 advanceX = SkScalarRoundToScalar(advanceX);
293 }
294
295 SkVector vecs[1] = { { advanceX, 0 } };
296 if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode ||
297 DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode)
298 {
299 fG_inv.mapVectors(vecs, SK_ARRAY_COUNT(vecs));
300 } else {
301 fSkXform.mapVectors(vecs, SK_ARRAY_COUNT(vecs));
302 }
303
304 glyph->fAdvanceX = SkScalarToFixed(vecs[0].fX);
305 glyph->fAdvanceY = SkScalarToFixed(vecs[0].fY);
306 }
307
308 void SkScalerContext_DW::generateMetrics(SkGlyph* glyph) {
309 glyph->fWidth = 0;
310
311 this->generateAdvance(glyph);
312
313 //Measure raster size.
314 fXform.dx = SkFixedToFloat(glyph->getSubXFixed());
315 fXform.dy = SkFixedToFloat(glyph->getSubYFixed());
316
317 FLOAT advance = 0;
318
319 UINT16 glyphId = glyph->getGlyphID();
320
321 DWRITE_GLYPH_OFFSET offset;
322 offset.advanceOffset = 0.0f;
323 offset.ascenderOffset = 0.0f;
324
325 DWRITE_GLYPH_RUN run;
326 run.glyphCount = 1;
327 run.glyphAdvances = &advance;
328 run.fontFace = fTypeface->fDWriteFontFace.get();
329 run.fontEmSize = SkScalarToFloat(fTextSizeRender);
330 run.bidiLevel = 0;
331 run.glyphIndices = &glyphId;
332 run.isSideways = FALSE;
333 run.glyphOffsets = &offset;
334
335 SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
336 HRVM(fTypeface->fFactory->CreateGlyphRunAnalysis(
337 &run,
338 1.0f, // pixelsPerDip,
339 &fXform,
340 fRenderingMode,
341 fMeasuringMode,
342 0.0f, // baselineOriginX,
343 0.0f, // baselineOriginY,
344 &glyphRunAnalysis),
345 "Could not create glyph run analysis.");
346
347 RECT bbox;
348 HRVM(glyphRunAnalysis->GetAlphaTextureBounds(fTextureType, &bbox),
349 "Could not get texture bounds.");
350
351 glyph->fWidth = SkToU16(bbox.right - bbox.left);
352 glyph->fHeight = SkToU16(bbox.bottom - bbox.top);
353 glyph->fLeft = SkToS16(bbox.left);
354 glyph->fTop = SkToS16(bbox.top);
355 }
356
357 void SkScalerContext_DW::generateFontMetrics(SkPaint::FontMetrics* mx,
358 SkPaint::FontMetrics* my) {
359 if (!(mx || my))
360 return;
361
362 if (mx) {
363 sk_bzero(mx, sizeof(*mx));
364 }
365 if (my) {
366 sk_bzero(my, sizeof(*my));
367 }
368
369 DWRITE_FONT_METRICS dwfm;
370 if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode ||
371 DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode)
372 {
373 fTypeface->fDWriteFontFace->GetGdiCompatibleMetrics(
374 fTextSizeRender,
375 1.0f, // pixelsPerDip
376 &fXform,
377 &dwfm);
378 } else {
379 fTypeface->fDWriteFontFace->GetMetrics(&dwfm);
380 }
381
382 SkScalar upem = SkIntToScalar(dwfm.designUnitsPerEm);
383 if (mx) {
384 mx->fTop = -fTextSizeRender * SkIntToScalar(dwfm.ascent) / upem;
385 mx->fAscent = mx->fTop;
386 mx->fDescent = fTextSizeRender * SkIntToScalar(dwfm.descent) / upem;
387 mx->fBottom = mx->fDescent;
388 mx->fLeading = fTextSizeRender * SkIntToScalar(dwfm.lineGap) / upem;
389 mx->fXHeight = fTextSizeRender * SkIntToScalar(dwfm.xHeight) / upem;
390 mx->fUnderlineThickness = fTextSizeRender * SkIntToScalar(dwfm.underline Thickness) / upem;
391 mx->fUnderlinePosition = -(fTextSizeRender * SkIntToScalar(dwfm.underlin ePosition) / upem);
392
393 mx->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
394 mx->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
395 }
396
397 if (my) {
398 my->fTop = -fTextSizeRender * SkIntToScalar(dwfm.ascent) / upem;
399 my->fAscent = my->fTop;
400 my->fDescent = fTextSizeRender * SkIntToScalar(dwfm.descent) / upem;
401 my->fBottom = my->fDescent;
402 my->fLeading = fTextSizeRender * SkIntToScalar(dwfm.lineGap) / upem;
403 my->fXHeight = fTextSizeRender * SkIntToScalar(dwfm.xHeight) / upem;
404 my->fUnderlineThickness = fTextSizeRender * SkIntToScalar(dwfm.underline Thickness) / upem;
405 my->fUnderlinePosition = -(fTextSizeRender * SkIntToScalar(dwfm.underlin ePosition) / upem);
406
407 my->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
408 my->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
409 }
410 }
411
412 ///////////////////////////////////////////////////////////////////////////////
413
414 #include "SkColorPriv.h"
415
416 static void bilevel_to_bw(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph) {
417 const int width = glyph.fWidth;
418 const size_t dstRB = (width + 7) >> 3;
419 uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage);
420
421 int byteCount = width >> 3;
422 int bitCount = width & 7;
423
424 for (int y = 0; y < glyph.fHeight; ++y) {
425 if (byteCount > 0) {
426 for (int i = 0; i < byteCount; ++i) {
427 unsigned byte = 0;
428 byte |= src[0] & (1 << 7);
429 byte |= src[1] & (1 << 6);
430 byte |= src[2] & (1 << 5);
431 byte |= src[3] & (1 << 4);
432 byte |= src[4] & (1 << 3);
433 byte |= src[5] & (1 << 2);
434 byte |= src[6] & (1 << 1);
435 byte |= src[7] & (1 << 0);
436 dst[i] = byte;
437 src += 8;
438 }
439 }
440 if (bitCount > 0) {
441 unsigned byte = 0;
442 unsigned mask = 0x80;
443 for (int i = 0; i < bitCount; i++) {
444 byte |= (src[i]) & mask;
445 mask >>= 1;
446 }
447 dst[byteCount] = byte;
448 }
449 src += bitCount;
450 dst += dstRB;
451 }
452 }
453
454 template<bool APPLY_PREBLEND>
455 static void rgb_to_a8(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph, cons t uint8_t* table8) {
456 const size_t dstRB = glyph.rowBytes();
457 const U16CPU width = glyph.fWidth;
458 uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage);
459
460 for (U16CPU y = 0; y < glyph.fHeight; y++) {
461 for (U16CPU i = 0; i < width; i++) {
462 U8CPU r = *(src++);
463 U8CPU g = *(src++);
464 U8CPU b = *(src++);
465 dst[i] = sk_apply_lut_if<APPLY_PREBLEND>((r + g + b) / 3, table8);
466 }
467 dst = (uint8_t*)((char*)dst + dstRB);
468 }
469 }
470
471 template<bool APPLY_PREBLEND>
472 static void rgb_to_lcd16(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph,
473 const uint8_t* tableR, const uint8_t* tableG, const uin t8_t* tableB) {
474 const size_t dstRB = glyph.rowBytes();
475 const U16CPU width = glyph.fWidth;
476 uint16_t* SK_RESTRICT dst = static_cast<uint16_t*>(glyph.fImage);
477
478 for (U16CPU y = 0; y < glyph.fHeight; y++) {
479 for (U16CPU i = 0; i < width; i++) {
480 U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableR);
481 U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableG);
482 U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableB);
483 dst[i] = SkPack888ToRGB16(r, g, b);
484 }
485 dst = (uint16_t*)((char*)dst + dstRB);
486 }
487 }
488
489 template<bool APPLY_PREBLEND>
490 static void rgb_to_lcd32(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph,
491 const uint8_t* tableR, const uint8_t* tableG, const uin t8_t* tableB) {
492 const size_t dstRB = glyph.rowBytes();
493 const U16CPU width = glyph.fWidth;
494 SkPMColor* SK_RESTRICT dst = static_cast<SkPMColor*>(glyph.fImage);
495
496 for (U16CPU y = 0; y < glyph.fHeight; y++) {
497 for (U16CPU i = 0; i < width; i++) {
498 U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableR);
499 U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableG);
500 U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableB);
501 dst[i] = SkPackARGB32(0xFF, r, g, b);
502 }
503 dst = (SkPMColor*)((char*)dst + dstRB);
504 }
505 }
506
507 const void* SkScalerContext_DW::drawDWMask(const SkGlyph& glyph) {
508 int sizeNeeded = glyph.fWidth * glyph.fHeight;
509 if (DWRITE_RENDERING_MODE_ALIASED != fRenderingMode) {
510 sizeNeeded *= 3;
511 }
512 if (sizeNeeded > fBits.count()) {
513 fBits.setCount(sizeNeeded);
514 }
515
516 // erase
517 memset(fBits.begin(), 0, sizeNeeded);
518
519 fXform.dx = SkFixedToFloat(glyph.getSubXFixed());
520 fXform.dy = SkFixedToFloat(glyph.getSubYFixed());
521
522 FLOAT advance = 0.0f;
523
524 UINT16 index = glyph.getGlyphID();
525
526 DWRITE_GLYPH_OFFSET offset;
527 offset.advanceOffset = 0.0f;
528 offset.ascenderOffset = 0.0f;
529
530 DWRITE_GLYPH_RUN run;
531 run.glyphCount = 1;
532 run.glyphAdvances = &advance;
533 run.fontFace = fTypeface->fDWriteFontFace.get();
534 run.fontEmSize = SkScalarToFloat(fTextSizeRender);
535 run.bidiLevel = 0;
536 run.glyphIndices = &index;
537 run.isSideways = FALSE;
538 run.glyphOffsets = &offset;
539
540 SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
541 HRNM(fTypeface->fFactory->CreateGlyphRunAnalysis(&run,
542 1.0f, // pixelsPerDip,
543 &fXform,
544 fRenderingMode,
545 fMeasuringMode,
546 0.0f, // baselineOriginX,
547 0.0f, // baselineOriginY,
548 &glyphRunAnalysis),
549 "Could not create glyph run analysis.");
550
551 //NOTE: this assumes that the glyph has already been measured
552 //with an exact same glyph run analysis.
553 RECT bbox;
554 bbox.left = glyph.fLeft;
555 bbox.top = glyph.fTop;
556 bbox.right = glyph.fLeft + glyph.fWidth;
557 bbox.bottom = glyph.fTop + glyph.fHeight;
558 HRNM(glyphRunAnalysis->CreateAlphaTexture(fTextureType,
559 &bbox,
560 fBits.begin(),
561 sizeNeeded),
562 "Could not draw mask.");
563 return fBits.begin();
564 }
565
566 void SkScalerContext_DW::generateImage(const SkGlyph& glyph) {
567 //Create the mask.
568 const void* bits = this->drawDWMask(glyph);
569 if (!bits) {
570 sk_bzero(glyph.fImage, glyph.computeImageSize());
571 return;
572 }
573
574 //Copy the mask into the glyph.
575 const uint8_t* src = (const uint8_t*)bits;
576 if (DWRITE_RENDERING_MODE_ALIASED == fRenderingMode) {
577 bilevel_to_bw(src, glyph);
578 const_cast<SkGlyph&>(glyph).fMaskFormat = SkMask::kBW_Format;
579 } else if (!isLCD(fRec)) {
580 if (fPreBlend.isApplicable()) {
581 rgb_to_a8<true>(src, glyph, fPreBlend.fG);
582 } else {
583 rgb_to_a8<false>(src, glyph, fPreBlend.fG);
584 }
585 } else if (SkMask::kLCD16_Format == glyph.fMaskFormat) {
586 if (fPreBlend.isApplicable()) {
587 rgb_to_lcd16<true>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend .fB);
588 } else {
589 rgb_to_lcd16<false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlen d.fB);
590 }
591 } else {
592 SkASSERT(SkMask::kLCD32_Format == glyph.fMaskFormat);
593 if (fPreBlend.isApplicable()) {
594 rgb_to_lcd32<true>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend .fB);
595 } else {
596 rgb_to_lcd32<false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlen d.fB);
597 }
598 }
599 }
600
601 void SkScalerContext_DW::generatePath(const SkGlyph& glyph, SkPath* path) {
602 SkASSERT(&glyph && path);
603
604 path->reset();
605
606 SkTScopedComPtr<IDWriteGeometrySink> geometryToPath;
607 HRVM(SkDWriteGeometrySink::Create(path, &geometryToPath),
608 "Could not create geometry to path converter.");
609 uint16_t glyphId = glyph.getGlyphID();
610 //TODO: convert to<->from DIUs? This would make a difference if hinting.
611 //It may not be needed, it appears that DirectWrite only hints at em size.
612 HRVM(fTypeface->fDWriteFontFace->GetGlyphRunOutline(SkScalarToFloat(fTextSiz eRender),
613 &glyphId,
614 NULL, //advances
615 NULL, //offsets
616 1, //num glyphs
617 FALSE, //sideways
618 FALSE, //rtl
619 geometryToPath.get()),
620 "Could not create glyph outline.");
621
622 path->transform(fSkXform);
623 }
OLDNEW
« no previous file with comments | « gyp/ports.gyp ('k') | src/ports/SkScalerContext_win_dw.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698