| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 Google Inc. All rights reserved. | 2 * Copyright (c) 2012 Google Inc. All rights reserved. |
| 3 * Copyright (C) 2013 BlackBerry Limited. All rights reserved. | 3 * Copyright (C) 2013 BlackBerry Limited. All rights reserved. |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions are | 6 * modification, are permitted provided that the following conditions are |
| 7 * met: | 7 * met: |
| 8 * | 8 * |
| 9 * * Redistributions of source code must retain the above copyright | 9 * * Redistributions of source code must retain the above copyright |
| 10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 30 */ | 30 */ |
| 31 | 31 |
| 32 #include "platform/fonts/shaping/HarfBuzzShaper.h" | 32 #include "platform/fonts/shaping/HarfBuzzShaper.h" |
| 33 | 33 |
| 34 #include "platform/RuntimeEnabledFeatures.h" | 34 #include "platform/RuntimeEnabledFeatures.h" |
| 35 #include "platform/fonts/Font.h" | 35 #include "platform/fonts/Font.h" |
| 36 #include "platform/fonts/FontDescription.h" |
| 36 #include "platform/fonts/FontFallbackIterator.h" | 37 #include "platform/fonts/FontFallbackIterator.h" |
| 37 #include "platform/fonts/GlyphBuffer.h" | 38 #include "platform/fonts/GlyphBuffer.h" |
| 38 #include "platform/fonts/SmallCapsIterator.h" | 39 #include "platform/fonts/SmallCapsIterator.h" |
| 39 #include "platform/fonts/UTF16TextIterator.h" | 40 #include "platform/fonts/UTF16TextIterator.h" |
| 40 #include "platform/fonts/opentype/OpenTypeCapsSupport.h" | 41 #include "platform/fonts/opentype/OpenTypeCapsSupport.h" |
| 41 #include "platform/fonts/shaping/CaseMappingHarfBuzzBufferFiller.h" | 42 #include "platform/fonts/shaping/CaseMappingHarfBuzzBufferFiller.h" |
| 42 #include "platform/fonts/shaping/HarfBuzzFace.h" | 43 #include "platform/fonts/shaping/HarfBuzzFace.h" |
| 43 #include "platform/fonts/shaping/RunSegmenter.h" | 44 #include "platform/fonts/shaping/RunSegmenter.h" |
| 44 #include "platform/fonts/shaping/ShapeResultInlineHeaders.h" | 45 #include "platform/fonts/shaping/ShapeResultInlineHeaders.h" |
| 45 #include "platform/text/Character.h" | 46 #include "platform/text/Character.h" |
| 46 #include "platform/text/TextBreakIterator.h" | 47 #include "platform/text/TextBreakIterator.h" |
| 47 #include "wtf/Compiler.h" | 48 #include "wtf/Compiler.h" |
| 48 #include "wtf/MathExtras.h" | 49 #include "wtf/MathExtras.h" |
| 49 #include "wtf/PtrUtil.h" | 50 #include "wtf/PtrUtil.h" |
| 50 #include "wtf/text/Unicode.h" | 51 #include "wtf/text/Unicode.h" |
| 51 #include <algorithm> | 52 #include <algorithm> |
| 52 #include <hb.h> | 53 #include <hb.h> |
| 53 #include <memory> | 54 #include <memory> |
| 54 #include <unicode/uchar.h> | 55 #include <unicode/uchar.h> |
| 55 #include <unicode/uscript.h> | 56 #include <unicode/uscript.h> |
| 56 | 57 |
| 57 namespace blink { | 58 namespace blink { |
| 59 using FeaturesVector = Vector<hb_feature_t, 6>; |
| 58 | 60 |
| 59 template <typename T> | 61 template <typename T> |
| 60 class HarfBuzzScopedPtr { | 62 class HarfBuzzScopedPtr { |
| 61 STACK_ALLOCATED(); | 63 STACK_ALLOCATED(); |
| 62 WTF_MAKE_NONCOPYABLE(HarfBuzzScopedPtr); | 64 WTF_MAKE_NONCOPYABLE(HarfBuzzScopedPtr); |
| 63 | 65 |
| 64 public: | 66 public: |
| 65 typedef void (*DestroyFunction)(T*); | 67 typedef void (*DestroyFunction)(T*); |
| 66 | 68 |
| 67 HarfBuzzScopedPtr(T* ptr, DestroyFunction destroy) | 69 HarfBuzzScopedPtr(T* ptr, DestroyFunction destroy) |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 146 const SimpleFontData* fontData) { | 148 const SimpleFontData* fontData) { |
| 147 hb_direction_t harfBuzzDirection = | 149 hb_direction_t harfBuzzDirection = |
| 148 isVerticalAnyUpright(orientation) && | 150 isVerticalAnyUpright(orientation) && |
| 149 !fontData->isTextOrientationFallback() | 151 !fontData->isTextOrientationFallback() |
| 150 ? HB_DIRECTION_TTB | 152 ? HB_DIRECTION_TTB |
| 151 : HB_DIRECTION_LTR; | 153 : HB_DIRECTION_LTR; |
| 152 return dir == RTL ? HB_DIRECTION_REVERSE(harfBuzzDirection) | 154 return dir == RTL ? HB_DIRECTION_REVERSE(harfBuzzDirection) |
| 153 : harfBuzzDirection; | 155 : harfBuzzDirection; |
| 154 } | 156 } |
| 155 | 157 |
| 156 } // namespace | 158 inline bool shapeRange(hb_buffer_t* harfBuzzBuffer, |
| 157 | 159 hb_feature_t* fontFeatures, |
| 158 inline bool HarfBuzzShaper::shapeRange( | 160 unsigned fontFeaturesSize, |
| 159 hb_buffer_t* harfBuzzBuffer, | 161 const SimpleFontData* currentFont, |
| 160 const Font* font, | 162 PassRefPtr<UnicodeRangeSet> currentFontRangeSet, |
| 161 const FeaturesVector& fontFeatures, | 163 UScriptCode currentRunScript, |
| 162 const SimpleFontData* currentFont, | 164 hb_direction_t direction, |
| 163 PassRefPtr<UnicodeRangeSet> currentFontRangeSet, | 165 hb_language_t language) { |
| 164 UScriptCode currentRunScript, | |
| 165 hb_language_t language) { | |
| 166 const FontPlatformData* platformData = &(currentFont->platformData()); | 166 const FontPlatformData* platformData = &(currentFont->platformData()); |
| 167 HarfBuzzFace* face = platformData->harfBuzzFace(); | 167 HarfBuzzFace* face = platformData->harfBuzzFace(); |
| 168 if (!face) { | 168 if (!face) { |
| 169 DLOG(ERROR) << "Could not create HarfBuzzFace from FontPlatformData."; | 169 DLOG(ERROR) << "Could not create HarfBuzzFace from FontPlatformData."; |
| 170 return false; | 170 return false; |
| 171 } | 171 } |
| 172 | 172 |
| 173 hb_buffer_set_language(harfBuzzBuffer, language); | 173 hb_buffer_set_language(harfBuzzBuffer, language); |
| 174 hb_buffer_set_script(harfBuzzBuffer, ICUScriptToHBScript(currentRunScript)); | 174 hb_buffer_set_script(harfBuzzBuffer, ICUScriptToHBScript(currentRunScript)); |
| 175 hb_buffer_set_direction( | 175 hb_buffer_set_direction(harfBuzzBuffer, direction); |
| 176 harfBuzzBuffer, | |
| 177 TextDirectionToHBDirection(m_textRun.direction(), | |
| 178 font->getFontDescription().orientation(), | |
| 179 currentFont)); | |
| 180 | 176 |
| 181 hb_font_t* hbFont = face->getScaledFont(std::move(currentFontRangeSet)); | 177 hb_font_t* hbFont = face->getScaledFont(std::move(currentFontRangeSet)); |
| 182 hb_shape(hbFont, harfBuzzBuffer, | 178 hb_shape(hbFont, harfBuzzBuffer, fontFeatures, fontFeaturesSize); |
| 183 fontFeatures.isEmpty() ? 0 : fontFeatures.data(), | |
| 184 fontFeatures.size()); | |
| 185 | 179 |
| 186 return true; | 180 return true; |
| 187 } | 181 } |
| 188 | 182 |
| 183 } // namespace |
| 184 |
| 189 bool HarfBuzzShaper::extractShapeResults(hb_buffer_t* harfBuzzBuffer, | 185 bool HarfBuzzShaper::extractShapeResults(hb_buffer_t* harfBuzzBuffer, |
| 190 ShapeResult* shapeResult, | 186 ShapeResult* shapeResult, |
| 191 bool& fontCycleQueued, | 187 bool& fontCycleQueued, |
| 192 Deque<HolesQueueItem>* holesQueue, | 188 Deque<HolesQueueItem>* holesQueue, |
| 193 const HolesQueueItem& currentQueueItem, | 189 const HolesQueueItem& currentQueueItem, |
| 194 const Font* font, | 190 const Font* font, |
| 195 const SimpleFontData* currentFont, | 191 const SimpleFontData* currentFont, |
| 196 UScriptCode currentRunScript, | 192 UScriptCode currentRunScript, |
| 197 bool isLastResort) { | 193 bool isLastResort) const { |
| 198 enum ClusterResult { Shaped, NotDef, Unknown }; | 194 enum ClusterResult { Shaped, NotDef, Unknown }; |
| 199 ClusterResult currentClusterResult = Unknown; | 195 ClusterResult currentClusterResult = Unknown; |
| 200 ClusterResult previousClusterResult = Unknown; | 196 ClusterResult previousClusterResult = Unknown; |
| 201 unsigned previousCluster = 0; | 197 unsigned previousCluster = 0; |
| 202 unsigned currentCluster = 0; | 198 unsigned currentCluster = 0; |
| 203 | 199 |
| 204 // Find first notdef glyph in harfBuzzBuffer. | 200 // Find first notdef glyph in harfBuzzBuffer. |
| 205 unsigned numGlyphs = hb_buffer_get_length(harfBuzzBuffer); | 201 unsigned numGlyphs = hb_buffer_get_length(harfBuzzBuffer); |
| 206 hb_glyph_info_t* glyphInfo = hb_buffer_get_glyph_infos(harfBuzzBuffer, 0); | 202 hb_glyph_info_t* glyphInfo = hb_buffer_get_glyph_infos(harfBuzzBuffer, 0); |
| 207 | 203 |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 331 if (runOrientation == FontOrientation::VerticalRotated || | 327 if (runOrientation == FontOrientation::VerticalRotated || |
| 332 (runOrientation == FontOrientation::VerticalMixed && | 328 (runOrientation == FontOrientation::VerticalMixed && |
| 333 renderOrientation == OrientationIterator::OrientationRotateSideways)) | 329 renderOrientation == OrientationIterator::OrientationRotateSideways)) |
| 334 return originalFont->verticalRightOrientationFontData().get(); | 330 return originalFont->verticalRightOrientationFontData().get(); |
| 335 | 331 |
| 336 return originalFont; | 332 return originalFont; |
| 337 } | 333 } |
| 338 | 334 |
| 339 bool HarfBuzzShaper::collectFallbackHintChars( | 335 bool HarfBuzzShaper::collectFallbackHintChars( |
| 340 const Deque<HolesQueueItem>& holesQueue, | 336 const Deque<HolesQueueItem>& holesQueue, |
| 341 Vector<UChar32>& hint) { | 337 Vector<UChar32>& hint) const { |
| 342 if (!holesQueue.size()) | 338 if (!holesQueue.size()) |
| 343 return false; | 339 return false; |
| 344 | 340 |
| 345 hint.clear(); | 341 hint.clear(); |
| 346 | 342 |
| 347 size_t numCharsAdded = 0; | 343 size_t numCharsAdded = 0; |
| 348 for (auto it = holesQueue.begin(); it != holesQueue.end(); ++it) { | 344 for (auto it = holesQueue.begin(); it != holesQueue.end(); ++it) { |
| 349 if (it->m_action == HolesQueueNextFont) | 345 if (it->m_action == HolesQueueNextFont) |
| 350 break; | 346 break; |
| 351 | 347 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 391 | 387 |
| 392 hb_feature_t createFeature(uint8_t c1, | 388 hb_feature_t createFeature(uint8_t c1, |
| 393 uint8_t c2, | 389 uint8_t c2, |
| 394 uint8_t c3, | 390 uint8_t c3, |
| 395 uint8_t c4, | 391 uint8_t c4, |
| 396 uint32_t value = 0) { | 392 uint32_t value = 0) { |
| 397 return {HB_TAG(c1, c2, c3, c4), value, 0 /* start */, | 393 return {HB_TAG(c1, c2, c3, c4), value, 0 /* start */, |
| 398 static_cast<unsigned>(-1) /* end */}; | 394 static_cast<unsigned>(-1) /* end */}; |
| 399 } | 395 } |
| 400 | 396 |
| 401 void setFontFeatures(const Font* font, | 397 void setFontFeatures(const Font* font, FeaturesVector* features) { |
| 402 HarfBuzzShaper::FeaturesVector* features) { | |
| 403 const FontDescription& description = font->getFontDescription(); | 398 const FontDescription& description = font->getFontDescription(); |
| 404 | 399 |
| 405 static hb_feature_t noKern = createFeature('k', 'e', 'r', 'n'); | 400 static hb_feature_t noKern = createFeature('k', 'e', 'r', 'n'); |
| 406 static hb_feature_t noVkrn = createFeature('v', 'k', 'r', 'n'); | 401 static hb_feature_t noVkrn = createFeature('v', 'k', 'r', 'n'); |
| 407 switch (description.getKerning()) { | 402 switch (description.getKerning()) { |
| 408 case FontDescription::NormalKerning: | 403 case FontDescription::NormalKerning: |
| 409 // kern/vkrn are enabled by default | 404 // kern/vkrn are enabled by default |
| 410 break; | 405 break; |
| 411 case FontDescription::NoneKerning: | 406 case FontDescription::NoneKerning: |
| 412 features->append(description.isVerticalAnyUpright() ? noVkrn : noKern); | 407 features->append(description.isVerticalAnyUpright() ? noVkrn : noKern); |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 533 feature.start = 0; | 528 feature.start = 0; |
| 534 feature.end = static_cast<unsigned>(-1); | 529 feature.end = static_cast<unsigned>(-1); |
| 535 features->append(feature); | 530 features->append(feature); |
| 536 } | 531 } |
| 537 } | 532 } |
| 538 | 533 |
| 539 class CapsFeatureSettingsScopedOverlay final { | 534 class CapsFeatureSettingsScopedOverlay final { |
| 540 STACK_ALLOCATED() | 535 STACK_ALLOCATED() |
| 541 | 536 |
| 542 public: | 537 public: |
| 543 CapsFeatureSettingsScopedOverlay(HarfBuzzShaper::FeaturesVector*, | 538 CapsFeatureSettingsScopedOverlay(FeaturesVector*, |
| 544 FontDescription::FontVariantCaps); | 539 FontDescription::FontVariantCaps); |
| 545 CapsFeatureSettingsScopedOverlay() = delete; | 540 CapsFeatureSettingsScopedOverlay() = delete; |
| 546 ~CapsFeatureSettingsScopedOverlay(); | 541 ~CapsFeatureSettingsScopedOverlay(); |
| 547 | 542 |
| 548 private: | 543 private: |
| 549 void overlayCapsFeatures(FontDescription::FontVariantCaps); | 544 void overlayCapsFeatures(FontDescription::FontVariantCaps); |
| 550 void prependCounting(const hb_feature_t&); | 545 void prependCounting(const hb_feature_t&); |
| 551 HarfBuzzShaper::FeaturesVector* m_features; | 546 FeaturesVector* m_features; |
| 552 size_t m_countFeatures; | 547 size_t m_countFeatures; |
| 553 }; | 548 }; |
| 554 | 549 |
| 555 CapsFeatureSettingsScopedOverlay::CapsFeatureSettingsScopedOverlay( | 550 CapsFeatureSettingsScopedOverlay::CapsFeatureSettingsScopedOverlay( |
| 556 HarfBuzzShaper::FeaturesVector* features, | 551 FeaturesVector* features, |
| 557 FontDescription::FontVariantCaps variantCaps) | 552 FontDescription::FontVariantCaps variantCaps) |
| 558 : m_features(features), m_countFeatures(0) { | 553 : m_features(features), m_countFeatures(0) { |
| 559 overlayCapsFeatures(variantCaps); | 554 overlayCapsFeatures(variantCaps); |
| 560 } | 555 } |
| 561 | 556 |
| 562 void CapsFeatureSettingsScopedOverlay::overlayCapsFeatures( | 557 void CapsFeatureSettingsScopedOverlay::overlayCapsFeatures( |
| 563 FontDescription::FontVariantCaps variantCaps) { | 558 FontDescription::FontVariantCaps variantCaps) { |
| 564 static hb_feature_t smcp = createFeature('s', 'm', 'c', 'p', 1); | 559 static hb_feature_t smcp = createFeature('s', 'm', 'c', 'p', 1); |
| 565 static hb_feature_t pcap = createFeature('p', 'c', 'a', 'p', 1); | 560 static hb_feature_t pcap = createFeature('p', 'c', 'a', 'p', 1); |
| 566 static hb_feature_t c2sc = createFeature('c', '2', 's', 'c', 1); | 561 static hb_feature_t c2sc = createFeature('c', '2', 's', 'c', 1); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 594 m_features->prepend(feature); | 589 m_features->prepend(feature); |
| 595 m_countFeatures++; | 590 m_countFeatures++; |
| 596 } | 591 } |
| 597 | 592 |
| 598 CapsFeatureSettingsScopedOverlay::~CapsFeatureSettingsScopedOverlay() { | 593 CapsFeatureSettingsScopedOverlay::~CapsFeatureSettingsScopedOverlay() { |
| 599 m_features->remove(0, m_countFeatures); | 594 m_features->remove(0, m_countFeatures); |
| 600 } | 595 } |
| 601 | 596 |
| 602 } // namespace | 597 } // namespace |
| 603 | 598 |
| 604 PassRefPtr<ShapeResult> HarfBuzzShaper::shapeResult(const Font* font) { | 599 PassRefPtr<ShapeResult> HarfBuzzShaper::shapeResult(const Font* font) const { |
| 605 RefPtr<ShapeResult> result = ShapeResult::create( | 600 RefPtr<ShapeResult> result = ShapeResult::create( |
| 606 font, m_normalizedBufferLength, m_textRun.direction()); | 601 font, m_normalizedBufferLength, m_textRun.direction()); |
| 607 HarfBuzzScopedPtr<hb_buffer_t> harfBuzzBuffer(hb_buffer_create(), | 602 HarfBuzzScopedPtr<hb_buffer_t> harfBuzzBuffer(hb_buffer_create(), |
| 608 hb_buffer_destroy); | 603 hb_buffer_destroy); |
| 609 FeaturesVector fontFeatures; | 604 FeaturesVector fontFeatures; |
| 610 setFontFeatures(font, &fontFeatures); | 605 setFontFeatures(font, &fontFeatures); |
| 611 const FontDescription& fontDescription = font->getFontDescription(); | 606 const FontDescription& fontDescription = font->getFontDescription(); |
| 612 const hb_language_t language = | 607 const hb_language_t language = |
| 613 fontDescription.localeOrDefault().harfbuzzLanguage(); | 608 fontDescription.localeOrDefault().harfbuzzLanguage(); |
| 614 | 609 |
| 615 bool needsCapsHandling = | 610 bool needsCapsHandling = |
| 616 fontDescription.variantCaps() != FontDescription::CapsNormal; | 611 fontDescription.variantCaps() != FontDescription::CapsNormal; |
| 617 OpenTypeCapsSupport capsSupport; | 612 OpenTypeCapsSupport capsSupport; |
| 613 FontOrientation orientation = font->getFontDescription().orientation(); |
| 618 | 614 |
| 619 RunSegmenter::RunSegmenterRange segmentRange = { | 615 RunSegmenter::RunSegmenterRange segmentRange = { |
| 620 0, 0, USCRIPT_INVALID_CODE, OrientationIterator::OrientationInvalid, | 616 0, 0, USCRIPT_INVALID_CODE, OrientationIterator::OrientationInvalid, |
| 621 FontFallbackPriority::Invalid}; | 617 FontFallbackPriority::Invalid}; |
| 622 RunSegmenter runSegmenter(m_normalizedBuffer.get(), m_normalizedBufferLength, | 618 RunSegmenter runSegmenter(m_normalizedBuffer.get(), m_normalizedBufferLength, |
| 623 font->getFontDescription().orientation()); | 619 orientation); |
| 624 | 620 |
| 625 Vector<UChar32> fallbackCharsHint; | 621 Vector<UChar32> fallbackCharsHint; |
| 626 | 622 |
| 627 // TODO: Check whether this treatAsZerowidthspace from the previous script | 623 // TODO: Check whether this treatAsZerowidthspace from the previous script |
| 628 // segmentation plays a role here, does the new scriptRuniterator handle that | 624 // segmentation plays a role here, does the new scriptRuniterator handle that |
| 629 // correctly? | 625 // correctly? |
| 630 Deque<HolesQueueItem> holesQueue; | 626 Deque<HolesQueueItem> holesQueue; |
| 631 while (runSegmenter.consume(&segmentRange)) { | 627 while (runSegmenter.consume(&segmentRange)) { |
| 632 RefPtr<FontFallbackIterator> fallbackIterator = | 628 RefPtr<FontFallbackIterator> fallbackIterator = |
| 633 font->createFontFallbackIterator(segmentRange.fontFallbackPriority); | 629 font->createFontFallbackIterator(segmentRange.fontFallbackPriority); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 650 // define a new API on the shaper which will give us coverage | 646 // define a new API on the shaper which will give us coverage |
| 651 // information? | 647 // information? |
| 652 if (!collectFallbackHintChars(holesQueue, fallbackCharsHint)) { | 648 if (!collectFallbackHintChars(holesQueue, fallbackCharsHint)) { |
| 653 // Give up shaping since we cannot retrieve a font fallback | 649 // Give up shaping since we cannot retrieve a font fallback |
| 654 // font without a hintlist. | 650 // font without a hintlist. |
| 655 holesQueue.clear(); | 651 holesQueue.clear(); |
| 656 break; | 652 break; |
| 657 } | 653 } |
| 658 | 654 |
| 659 currentFontDataForRangeSet = fallbackIterator->next(fallbackCharsHint); | 655 currentFontDataForRangeSet = fallbackIterator->next(fallbackCharsHint); |
| 660 | |
| 661 if (!currentFontDataForRangeSet->fontData()) { | 656 if (!currentFontDataForRangeSet->fontData()) { |
| 662 DCHECK(!holesQueue.size()); | 657 DCHECK(!holesQueue.size()); |
| 663 break; | 658 break; |
| 664 } | 659 } |
| 665 fontCycleQueued = false; | 660 fontCycleQueued = false; |
| 666 continue; | 661 continue; |
| 667 } | 662 } |
| 668 | 663 |
| 664 const SimpleFontData* fontData = currentFontDataForRangeSet->fontData(); |
| 669 SmallCapsIterator::SmallCapsBehavior smallCapsBehavior = | 665 SmallCapsIterator::SmallCapsBehavior smallCapsBehavior = |
| 670 SmallCapsIterator::SmallCapsSameCase; | 666 SmallCapsIterator::SmallCapsSameCase; |
| 671 if (needsCapsHandling) { | 667 if (needsCapsHandling) { |
| 672 capsSupport = | 668 capsSupport = |
| 673 OpenTypeCapsSupport(currentFontDataForRangeSet->fontData() | 669 OpenTypeCapsSupport(fontData->platformData().harfBuzzFace(), |
| 674 ->platformData() | |
| 675 .harfBuzzFace(), | |
| 676 fontDescription.variantCaps(), | 670 fontDescription.variantCaps(), |
| 677 ICUScriptToHBScript(segmentRange.script)); | 671 ICUScriptToHBScript(segmentRange.script)); |
| 678 if (capsSupport.needsRunCaseSplitting()) { | 672 if (capsSupport.needsRunCaseSplitting()) { |
| 679 splitUntilNextCaseChange(m_normalizedBuffer.get(), &holesQueue, | 673 splitUntilNextCaseChange(m_normalizedBuffer.get(), &holesQueue, |
| 680 currentQueueItem, smallCapsBehavior); | 674 currentQueueItem, smallCapsBehavior); |
| 681 } | 675 } |
| 682 } | 676 } |
| 683 | 677 |
| 684 ASSERT(currentQueueItem.m_numCharacters); | 678 ASSERT(currentQueueItem.m_numCharacters); |
| 685 | 679 |
| 686 const SimpleFontData* smallcapsAdjustedFont = | 680 const SimpleFontData* smallcapsAdjustedFont = |
| 687 needsCapsHandling && capsSupport.needsSyntheticFont(smallCapsBehavior) | 681 needsCapsHandling && capsSupport.needsSyntheticFont(smallCapsBehavior) |
| 688 ? currentFontDataForRangeSet->fontData() | 682 ? fontData->smallCapsFontData(fontDescription).get() |
| 689 ->smallCapsFontData(fontDescription) | 683 : fontData; |
| 690 .get() | |
| 691 : currentFontDataForRangeSet->fontData(); | |
| 692 | 684 |
| 693 // Compatibility with SimpleFontData approach of keeping a flag for | 685 // Compatibility with SimpleFontData approach of keeping a flag for |
| 694 // overriding drawing direction. | 686 // overriding drawing direction. |
| 695 // TODO: crbug.com/506224 This should go away in favor of storing that | 687 // TODO: crbug.com/506224 This should go away in favor of storing that |
| 696 // information elsewhere, for example in ShapeResult. | 688 // information elsewhere, for example in ShapeResult. |
| 697 const SimpleFontData* directionAndSmallCapsAdjustedFont = | 689 const SimpleFontData* directionAndSmallCapsAdjustedFont = |
| 698 fontDataAdjustedForOrientation( | 690 fontDataAdjustedForOrientation(smallcapsAdjustedFont, orientation, |
| 699 smallcapsAdjustedFont, font->getFontDescription().orientation(), | 691 segmentRange.renderOrientation); |
| 700 segmentRange.renderOrientation); | |
| 701 | 692 |
| 702 CaseMapIntend caseMapIntend = CaseMapIntend::KeepSameCase; | 693 CaseMapIntend caseMapIntend = CaseMapIntend::KeepSameCase; |
| 703 if (needsCapsHandling) { | 694 if (needsCapsHandling) |
| 704 caseMapIntend = capsSupport.needsCaseChange(smallCapsBehavior); | 695 caseMapIntend = capsSupport.needsCaseChange(smallCapsBehavior); |
| 705 } | |
| 706 | 696 |
| 707 CaseMappingHarfBuzzBufferFiller( | 697 CaseMappingHarfBuzzBufferFiller( |
| 708 caseMapIntend, fontDescription.localeOrDefault(), | 698 caseMapIntend, fontDescription.localeOrDefault(), |
| 709 harfBuzzBuffer.get(), m_normalizedBuffer.get(), | 699 harfBuzzBuffer.get(), m_normalizedBuffer.get(), |
| 710 m_normalizedBufferLength, currentQueueItem.m_startIndex, | 700 m_normalizedBufferLength, currentQueueItem.m_startIndex, |
| 711 currentQueueItem.m_numCharacters); | 701 currentQueueItem.m_numCharacters); |
| 712 | 702 |
| 713 CapsFeatureSettingsScopedOverlay capsOverlay( | 703 CapsFeatureSettingsScopedOverlay capsOverlay( |
| 714 &fontFeatures, capsSupport.fontFeatureToUse(smallCapsBehavior)); | 704 &fontFeatures, capsSupport.fontFeatureToUse(smallCapsBehavior)); |
| 715 | 705 |
| 716 if (!shapeRange(harfBuzzBuffer.get(), font, fontFeatures, | 706 hb_direction_t direction = |
| 717 directionAndSmallCapsAdjustedFont, | 707 TextDirectionToHBDirection(m_textRun.direction(), orientation, |
| 708 directionAndSmallCapsAdjustedFont); |
| 709 |
| 710 if (!shapeRange(harfBuzzBuffer.get(), |
| 711 fontFeatures.isEmpty() ? 0 : fontFeatures.data(), |
| 712 fontFeatures.size(), directionAndSmallCapsAdjustedFont, |
| 718 currentFontDataForRangeSet->ranges(), segmentRange.script, | 713 currentFontDataForRangeSet->ranges(), segmentRange.script, |
| 719 language)) | 714 direction, language)) |
| 720 DLOG(ERROR) << "Shaping range failed."; | 715 DLOG(ERROR) << "Shaping range failed."; |
| 721 | 716 |
| 722 if (!extractShapeResults( | 717 if (!extractShapeResults( |
| 723 harfBuzzBuffer.get(), result.get(), fontCycleQueued, &holesQueue, | 718 harfBuzzBuffer.get(), result.get(), fontCycleQueued, &holesQueue, |
| 724 currentQueueItem, font, directionAndSmallCapsAdjustedFont, | 719 currentQueueItem, font, directionAndSmallCapsAdjustedFont, |
| 725 segmentRange.script, !fallbackIterator->hasNext())) | 720 segmentRange.script, !fallbackIterator->hasNext())) |
| 726 DLOG(ERROR) << "Shape result extraction failed."; | 721 DLOG(ERROR) << "Shape result extraction failed."; |
| 727 | 722 |
| 728 hb_buffer_reset(harfBuzzBuffer.get()); | 723 hb_buffer_reset(harfBuzzBuffer.get()); |
| 729 } | 724 } |
| 730 } | 725 } |
| 731 return result.release(); | 726 return result.release(); |
| 732 } | 727 } |
| 733 | 728 |
| 734 } // namespace blink | 729 } // namespace blink |
| OLD | NEW |