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 |
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
391 vecs[0].fX = SkScalarRoundToScalar(advanceX); | 391 vecs[0].fX = SkScalarRoundToScalar(advanceX); |
392 fG_inv.mapVectors(vecs, SK_ARRAY_COUNT(vecs)); | 392 fG_inv.mapVectors(vecs, SK_ARRAY_COUNT(vecs)); |
393 } else { | 393 } else { |
394 fSkXform.mapVectors(vecs, SK_ARRAY_COUNT(vecs)); | 394 fSkXform.mapVectors(vecs, SK_ARRAY_COUNT(vecs)); |
395 } | 395 } |
396 | 396 |
397 glyph->fAdvanceX = SkScalarToFixed(vecs[0].fX); | 397 glyph->fAdvanceX = SkScalarToFixed(vecs[0].fX); |
398 glyph->fAdvanceY = SkScalarToFixed(vecs[0].fY); | 398 glyph->fAdvanceY = SkScalarToFixed(vecs[0].fY); |
399 } | 399 } |
400 | 400 |
401 void SkScalerContext_DW::generateMetrics(SkGlyph* glyph) { | 401 void SkScalerContext_DW::getBoundingBox(SkGlyph* glyph, |
402 glyph->fWidth = 0; | 402 DWRITE_RENDERING_MODE renderingMode, |
403 | 403 DWRITE_TEXTURE_TYPE textureType, |
404 this->generateAdvance(glyph); | 404 RECT* bbox) |
405 | 405 { |
406 //Measure raster size. | 406 //Measure raster size. |
407 fXform.dx = SkFixedToFloat(glyph->getSubXFixed()); | 407 fXform.dx = SkFixedToFloat(glyph->getSubXFixed()); |
408 fXform.dy = SkFixedToFloat(glyph->getSubYFixed()); | 408 fXform.dy = SkFixedToFloat(glyph->getSubYFixed()); |
409 | 409 |
410 FLOAT advance = 0; | 410 FLOAT advance = 0; |
411 | 411 |
412 UINT16 glyphId = glyph->getGlyphID(); | 412 UINT16 glyphId = glyph->getGlyphID(); |
413 | 413 |
414 DWRITE_GLYPH_OFFSET offset; | 414 DWRITE_GLYPH_OFFSET offset; |
415 offset.advanceOffset = 0.0f; | 415 offset.advanceOffset = 0.0f; |
416 offset.ascenderOffset = 0.0f; | 416 offset.ascenderOffset = 0.0f; |
417 | 417 |
418 DWRITE_GLYPH_RUN run; | 418 DWRITE_GLYPH_RUN run; |
419 run.glyphCount = 1; | 419 run.glyphCount = 1; |
420 run.glyphAdvances = &advance; | 420 run.glyphAdvances = &advance; |
421 run.fontFace = fTypeface->fDWriteFontFace.get(); | 421 run.fontFace = fTypeface->fDWriteFontFace.get(); |
422 run.fontEmSize = SkScalarToFloat(fTextSizeRender); | 422 run.fontEmSize = SkScalarToFloat(fTextSizeRender); |
423 run.bidiLevel = 0; | 423 run.bidiLevel = 0; |
424 run.glyphIndices = &glyphId; | 424 run.glyphIndices = &glyphId; |
425 run.isSideways = FALSE; | 425 run.isSideways = FALSE; |
426 run.glyphOffsets = &offset; | 426 run.glyphOffsets = &offset; |
427 | 427 |
428 SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis; | 428 SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis; |
429 HRVM(fTypeface->fFactory->CreateGlyphRunAnalysis( | 429 HRVM(fTypeface->fFactory->CreateGlyphRunAnalysis( |
430 &run, | 430 &run, |
431 1.0f, // pixelsPerDip, | 431 1.0f, // pixelsPerDip, |
432 &fXform, | 432 &fXform, |
433 fRenderingMode, | 433 renderingMode, |
434 fMeasuringMode, | 434 fMeasuringMode, |
435 0.0f, // baselineOriginX, | 435 0.0f, // baselineOriginX, |
436 0.0f, // baselineOriginY, | 436 0.0f, // baselineOriginY, |
437 &glyphRunAnalysis), | 437 &glyphRunAnalysis), |
438 "Could not create glyph run analysis."); | 438 "Could not create glyph run analysis."); |
439 | 439 |
| 440 HRVM(glyphRunAnalysis->GetAlphaTextureBounds(textureType, bbox), |
| 441 "Could not get texture bounds."); |
| 442 } |
| 443 |
| 444 void SkScalerContext_DW::generateMetrics(SkGlyph* glyph) { |
| 445 glyph->fWidth = 0; |
| 446 |
| 447 this->generateAdvance(glyph); |
| 448 |
440 RECT bbox; | 449 RECT bbox; |
441 HRVM(glyphRunAnalysis->GetAlphaTextureBounds(fTextureType, &bbox), | 450 this->getBoundingBox(glyph, fRenderingMode, fTextureType, &bbox); |
442 "Could not get texture bounds."); | 451 |
| 452 // GetAlphaTextureBounds succeeds but returns an empty RECT if there are no |
| 453 // glyphs of the specified texture type. When this happens, try with the |
| 454 // alternate texture type. |
| 455 if (bbox.left == bbox.right || bbox.top == bbox.bottom) { |
| 456 if (DWRITE_TEXTURE_CLEARTYPE_3x1 == fTextureType) { |
| 457 this->getBoundingBox(glyph, |
| 458 DWRITE_RENDERING_MODE_ALIASED, |
| 459 DWRITE_TEXTURE_ALIASED_1x1, |
| 460 &bbox); |
| 461 if (bbox.left != bbox.right && bbox.top != bbox.bottom) { |
| 462 glyph->fForceBW = 1; |
| 463 } |
| 464 } |
| 465 // TODO: handle the case where a request for DWRITE_TEXTURE_ALIASED_1x1 |
| 466 // fails, and try DWRITE_TEXTURE_CLEARTYPE_3x1. |
| 467 } |
443 | 468 |
444 glyph->fWidth = SkToU16(bbox.right - bbox.left); | 469 glyph->fWidth = SkToU16(bbox.right - bbox.left); |
445 glyph->fHeight = SkToU16(bbox.bottom - bbox.top); | 470 glyph->fHeight = SkToU16(bbox.bottom - bbox.top); |
446 glyph->fLeft = SkToS16(bbox.left); | 471 glyph->fLeft = SkToS16(bbox.left); |
447 glyph->fTop = SkToS16(bbox.top); | 472 glyph->fTop = SkToS16(bbox.top); |
448 } | 473 } |
449 | 474 |
450 void SkScalerContext_DW::generateFontMetrics(SkPaint::FontMetrics* metrics) { | 475 void SkScalerContext_DW::generateFontMetrics(SkPaint::FontMetrics* metrics) { |
451 if (NULL == metrics) { | 476 if (NULL == metrics) { |
452 return; | 477 return; |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
595 for (U16CPU i = 0; i < width; i++) { | 620 for (U16CPU i = 0; i < width; i++) { |
596 U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableR); | 621 U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableR); |
597 U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableG); | 622 U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableG); |
598 U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableB); | 623 U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableB); |
599 dst[i] = SkPackARGB32(0xFF, r, g, b); | 624 dst[i] = SkPackARGB32(0xFF, r, g, b); |
600 } | 625 } |
601 dst = (SkPMColor*)((char*)dst + dstRB); | 626 dst = (SkPMColor*)((char*)dst + dstRB); |
602 } | 627 } |
603 } | 628 } |
604 | 629 |
605 const void* SkScalerContext_DW::drawDWMask(const SkGlyph& glyph) { | 630 const void* SkScalerContext_DW::drawDWMask(const SkGlyph& glyph, |
| 631 DWRITE_RENDERING_MODE renderingMode, |
| 632 DWRITE_TEXTURE_TYPE textureType) |
| 633 { |
606 int sizeNeeded = glyph.fWidth * glyph.fHeight; | 634 int sizeNeeded = glyph.fWidth * glyph.fHeight; |
607 if (DWRITE_RENDERING_MODE_ALIASED != fRenderingMode) { | 635 if (DWRITE_RENDERING_MODE_ALIASED != renderingMode) { |
608 sizeNeeded *= 3; | 636 sizeNeeded *= 3; |
609 } | 637 } |
610 if (sizeNeeded > fBits.count()) { | 638 if (sizeNeeded > fBits.count()) { |
611 fBits.setCount(sizeNeeded); | 639 fBits.setCount(sizeNeeded); |
612 } | 640 } |
613 | 641 |
614 // erase | 642 // erase |
615 memset(fBits.begin(), 0, sizeNeeded); | 643 memset(fBits.begin(), 0, sizeNeeded); |
616 | 644 |
617 fXform.dx = SkFixedToFloat(glyph.getSubXFixed()); | 645 fXform.dx = SkFixedToFloat(glyph.getSubXFixed()); |
(...skipping 14 matching lines...) Expand all Loading... |
632 run.fontEmSize = SkScalarToFloat(fTextSizeRender); | 660 run.fontEmSize = SkScalarToFloat(fTextSizeRender); |
633 run.bidiLevel = 0; | 661 run.bidiLevel = 0; |
634 run.glyphIndices = &index; | 662 run.glyphIndices = &index; |
635 run.isSideways = FALSE; | 663 run.isSideways = FALSE; |
636 run.glyphOffsets = &offset; | 664 run.glyphOffsets = &offset; |
637 | 665 |
638 SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis; | 666 SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis; |
639 HRNM(fTypeface->fFactory->CreateGlyphRunAnalysis(&run, | 667 HRNM(fTypeface->fFactory->CreateGlyphRunAnalysis(&run, |
640 1.0f, // pixelsPerDip, | 668 1.0f, // pixelsPerDip, |
641 &fXform, | 669 &fXform, |
642 fRenderingMode, | 670 renderingMode, |
643 fMeasuringMode, | 671 fMeasuringMode, |
644 0.0f, // baselineOriginX, | 672 0.0f, // baselineOriginX, |
645 0.0f, // baselineOriginY, | 673 0.0f, // baselineOriginY, |
646 &glyphRunAnalysis), | 674 &glyphRunAnalysis), |
647 "Could not create glyph run analysis."); | 675 "Could not create glyph run analysis."); |
648 | 676 |
649 //NOTE: this assumes that the glyph has already been measured | 677 //NOTE: this assumes that the glyph has already been measured |
650 //with an exact same glyph run analysis. | 678 //with an exact same glyph run analysis. |
651 RECT bbox; | 679 RECT bbox; |
652 bbox.left = glyph.fLeft; | 680 bbox.left = glyph.fLeft; |
653 bbox.top = glyph.fTop; | 681 bbox.top = glyph.fTop; |
654 bbox.right = glyph.fLeft + glyph.fWidth; | 682 bbox.right = glyph.fLeft + glyph.fWidth; |
655 bbox.bottom = glyph.fTop + glyph.fHeight; | 683 bbox.bottom = glyph.fTop + glyph.fHeight; |
656 HRNM(glyphRunAnalysis->CreateAlphaTexture(fTextureType, | 684 HRNM(glyphRunAnalysis->CreateAlphaTexture(textureType, |
657 &bbox, | 685 &bbox, |
658 fBits.begin(), | 686 fBits.begin(), |
659 sizeNeeded), | 687 sizeNeeded), |
660 "Could not draw mask."); | 688 "Could not draw mask."); |
661 return fBits.begin(); | 689 return fBits.begin(); |
662 } | 690 } |
663 | 691 |
664 void SkScalerContext_DW::generateImage(const SkGlyph& glyph) { | 692 void SkScalerContext_DW::generateImage(const SkGlyph& glyph) { |
665 //Create the mask. | 693 //Create the mask. |
666 const void* bits = this->drawDWMask(glyph); | 694 DWRITE_RENDERING_MODE renderingMode = fRenderingMode; |
| 695 DWRITE_TEXTURE_TYPE textureType = fTextureType; |
| 696 if (glyph.fForceBW) { |
| 697 renderingMode = DWRITE_RENDERING_MODE_ALIASED; |
| 698 textureType = DWRITE_TEXTURE_ALIASED_1x1; |
| 699 } |
| 700 const void* bits = this->drawDWMask(glyph, renderingMode, textureType); |
667 if (!bits) { | 701 if (!bits) { |
668 sk_bzero(glyph.fImage, glyph.computeImageSize()); | 702 sk_bzero(glyph.fImage, glyph.computeImageSize()); |
669 return; | 703 return; |
670 } | 704 } |
671 | 705 |
672 //Copy the mask into the glyph. | 706 //Copy the mask into the glyph. |
673 const uint8_t* src = (const uint8_t*)bits; | 707 const uint8_t* src = (const uint8_t*)bits; |
674 if (DWRITE_RENDERING_MODE_ALIASED == fRenderingMode) { | 708 if (DWRITE_RENDERING_MODE_ALIASED == renderingMode) { |
675 bilevel_to_bw(src, glyph); | 709 bilevel_to_bw(src, glyph); |
676 const_cast<SkGlyph&>(glyph).fMaskFormat = SkMask::kBW_Format; | 710 const_cast<SkGlyph&>(glyph).fMaskFormat = SkMask::kBW_Format; |
677 } else if (!isLCD(fRec)) { | 711 } else if (!isLCD(fRec)) { |
678 if (fPreBlend.isApplicable()) { | 712 if (fPreBlend.isApplicable()) { |
679 rgb_to_a8<true>(src, glyph, fPreBlend.fG); | 713 rgb_to_a8<true>(src, glyph, fPreBlend.fG); |
680 } else { | 714 } else { |
681 rgb_to_a8<false>(src, glyph, fPreBlend.fG); | 715 rgb_to_a8<false>(src, glyph, fPreBlend.fG); |
682 } | 716 } |
683 } else if (SkMask::kLCD16_Format == glyph.fMaskFormat) { | 717 } else if (SkMask::kLCD16_Format == glyph.fMaskFormat) { |
684 if (fPreBlend.isApplicable()) { | 718 if (fPreBlend.isApplicable()) { |
(...skipping 27 matching lines...) Expand all Loading... |
712 NULL, //advances | 746 NULL, //advances |
713 NULL, //offsets | 747 NULL, //offsets |
714 1, //num glyphs | 748 1, //num glyphs |
715 FALSE, //sideways | 749 FALSE, //sideways |
716 FALSE, //rtl | 750 FALSE, //rtl |
717 geometryToPath.get()), | 751 geometryToPath.get()), |
718 "Could not create glyph outline."); | 752 "Could not create glyph outline."); |
719 | 753 |
720 path->transform(fSkXform); | 754 path->transform(fSkXform); |
721 } | 755 } |
OLD | NEW |