OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkTypes.h" | 8 #include "SkTypes.h" |
9 #undef GetGlyphIndices | 9 #undef GetGlyphIndices |
10 | 10 |
11 #include "SkDWrite.h" | 11 #include "SkDWrite.h" |
12 #include "SkDWriteGeometrySink.h" | 12 #include "SkDWriteGeometrySink.h" |
13 #include "SkEndian.h" | 13 #include "SkEndian.h" |
14 #include "SkGlyph.h" | 14 #include "SkGlyph.h" |
15 #include "SkHRESULT.h" | 15 #include "SkHRESULT.h" |
16 #include "SkMaskGamma.h" | 16 #include "SkMaskGamma.h" |
17 #include "SkMatrix22.h" | 17 #include "SkMatrix22.h" |
18 #include "SkOTTable_EBLC.h" | 18 #include "SkOTTable_EBLC.h" |
19 #include "SkOTTable_EBSC.h" | 19 #include "SkOTTable_EBSC.h" |
20 #include "SkOTTable_gasp.h" | 20 #include "SkOTTable_gasp.h" |
| 21 #include "SkOTTable_maxp.h" |
21 #include "SkPath.h" | 22 #include "SkPath.h" |
22 #include "SkScalerContext.h" | 23 #include "SkScalerContext.h" |
23 #include "SkScalerContext_win_dw.h" | 24 #include "SkScalerContext_win_dw.h" |
24 #include "SkTScopedComPtr.h" | 25 #include "SkTScopedComPtr.h" |
25 #include "SkTypeface_win_dw.h" | 26 #include "SkTypeface_win_dw.h" |
26 | 27 |
27 #include <dwrite.h> | 28 #include <dwrite.h> |
28 | 29 |
29 static bool isLCD(const SkScalerContext::Rec& rec) { | 30 static bool isLCD(const SkScalerContext::Rec& rec) { |
30 return SkMask::kLCD16_Format == rec.fMaskFormat || | 31 return SkMask::kLCD16_Format == rec.fMaskFormat || |
31 SkMask::kLCD32_Format == rec.fMaskFormat; | 32 SkMask::kLCD32_Format == rec.fMaskFormat; |
32 } | 33 } |
33 | 34 |
| 35 static bool is_hinted_without_gasp(DWriteFontTypeface* typeface) { |
| 36 AutoTDWriteTable<SkOTTableMaximumProfile> maxp(typeface->fDWriteFontFace.get
()); |
| 37 if (!maxp.fExists) { |
| 38 return false; |
| 39 } |
| 40 if (maxp.fSize < sizeof(SkOTTableMaximumProfile::Version::TT)) { |
| 41 return false; |
| 42 } |
| 43 if (maxp->version.version != SkOTTableMaximumProfile::Version::TT::VERSION)
{ |
| 44 return false; |
| 45 } |
| 46 |
| 47 if (0 == maxp->version.tt.maxSizeOfInstructions) { |
| 48 // No hints. |
| 49 return false; |
| 50 } |
| 51 |
| 52 AutoTDWriteTable<SkOTTableGridAndScanProcedure> gasp(typeface->fDWriteFontFa
ce.get()); |
| 53 return !gasp.fExists; |
| 54 } |
| 55 |
34 /** A PPEMRange is inclusive, [min, max]. */ | 56 /** A PPEMRange is inclusive, [min, max]. */ |
35 struct PPEMRange { | 57 struct PPEMRange { |
36 int min; | 58 int min; |
37 int max; | 59 int max; |
38 }; | 60 }; |
39 | 61 |
40 /** If the rendering mode for the specified 'size' is gridfit, then place | 62 /** If the rendering mode for the specified 'size' is gridfit, then place |
41 * the gridfit range into 'range'. Otherwise, leave 'range' alone. | 63 * the gridfit range into 'range'. Otherwise, leave 'range' alone. |
42 */ | 64 */ |
43 static void expand_range_if_gridfit_only(DWriteFontTypeface* typeface, int size,
PPEMRange* range) { | 65 static void expand_range_if_gridfit_only(DWriteFontTypeface* typeface, int size,
PPEMRange* range) { |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
247 | 269 |
248 // If rotated but the horizontal text could have used a bitmap, | 270 // If rotated but the horizontal text could have used a bitmap, |
249 // render high quality rotated glyphs but measure using bitmap metrics. | 271 // render high quality rotated glyphs but measure using bitmap metrics. |
250 } else if (treatLikeBitmap) { | 272 } else if (treatLikeBitmap) { |
251 fTextSizeRender = gdiTextSize; | 273 fTextSizeRender = gdiTextSize; |
252 fRenderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC; | 274 fRenderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC; |
253 fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1; | 275 fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1; |
254 fTextSizeMeasure = gdiTextSize; | 276 fTextSizeMeasure = gdiTextSize; |
255 fMeasuringMode = DWRITE_MEASURING_MODE_GDI_CLASSIC; | 277 fMeasuringMode = DWRITE_MEASURING_MODE_GDI_CLASSIC; |
256 | 278 |
| 279 // Fonts that have hints but no gasp table get non-symmetric rendering. |
| 280 // Usually such fonts have low quality hints which were never tested |
| 281 // with anything but GDI ClearType classic. Such fonts often rely on |
| 282 // drop out control in the y direction in order to be legible. |
| 283 } else if (is_hinted_without_gasp(typeface)) { |
| 284 fTextSizeRender = gdiTextSize; |
| 285 fRenderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL; |
| 286 fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1; |
| 287 fTextSizeMeasure = realTextSize; |
| 288 fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL; |
| 289 |
257 // The normal case is to use natural symmetric rendering and linear metrics. | 290 // The normal case is to use natural symmetric rendering and linear metrics. |
258 } else { | 291 } else { |
259 fTextSizeRender = realTextSize; | 292 fTextSizeRender = realTextSize; |
260 fRenderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC; | 293 fRenderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC; |
261 fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1; | 294 fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1; |
262 fTextSizeMeasure = realTextSize; | 295 fTextSizeMeasure = realTextSize; |
263 fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL; | 296 fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL; |
264 } | 297 } |
265 | 298 |
266 if (this->isSubpixel()) { | 299 if (this->isSubpixel()) { |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
347 DWRITE_FONT_METRICS dwfm; | 380 DWRITE_FONT_METRICS dwfm; |
348 fTypeface->fDWriteFontFace->GetMetrics(&dwfm); | 381 fTypeface->fDWriteFontFace->GetMetrics(&dwfm); |
349 SkScalar advanceX = SkScalarMulDiv(fTextSizeMeasure, | 382 SkScalar advanceX = SkScalarMulDiv(fTextSizeMeasure, |
350 SkIntToScalar(gm.advanceWidth), | 383 SkIntToScalar(gm.advanceWidth), |
351 SkIntToScalar(dwfm.designUnitsPerEm)); | 384 SkIntToScalar(dwfm.designUnitsPerEm)); |
352 | 385 |
353 SkVector vecs[1] = { { advanceX, 0 } }; | 386 SkVector vecs[1] = { { advanceX, 0 } }; |
354 if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode || | 387 if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode || |
355 DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode) | 388 DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode) |
356 { | 389 { |
| 390 // DirectWrite produced 'compatible' metrics, but while close, |
| 391 // the end result is not always an integer as it would be with GDI. |
| 392 vecs[0].fX = SkScalarRoundToScalar(advanceX); |
357 fG_inv.mapVectors(vecs, SK_ARRAY_COUNT(vecs)); | 393 fG_inv.mapVectors(vecs, SK_ARRAY_COUNT(vecs)); |
358 } else { | 394 } else { |
359 fSkXform.mapVectors(vecs, SK_ARRAY_COUNT(vecs)); | 395 fSkXform.mapVectors(vecs, SK_ARRAY_COUNT(vecs)); |
360 } | 396 } |
361 | 397 |
362 glyph->fAdvanceX = SkScalarToFixed(vecs[0].fX); | 398 glyph->fAdvanceX = SkScalarToFixed(vecs[0].fX); |
363 glyph->fAdvanceY = SkScalarToFixed(vecs[0].fY); | 399 glyph->fAdvanceY = SkScalarToFixed(vecs[0].fY); |
364 } | 400 } |
365 | 401 |
366 void SkScalerContext_DW::generateMetrics(SkGlyph* glyph) { | 402 void SkScalerContext_DW::generateMetrics(SkGlyph* glyph) { |
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
672 NULL, //advances | 708 NULL, //advances |
673 NULL, //offsets | 709 NULL, //offsets |
674 1, //num glyphs | 710 1, //num glyphs |
675 FALSE, //sideways | 711 FALSE, //sideways |
676 FALSE, //rtl | 712 FALSE, //rtl |
677 geometryToPath.get()), | 713 geometryToPath.get()), |
678 "Could not create glyph outline."); | 714 "Could not create glyph outline."); |
679 | 715 |
680 path->transform(fSkXform); | 716 path->transform(fSkXform); |
681 } | 717 } |
OLD | NEW |