| 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 |