| 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 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 109 character = zeroWidthSpaceCharacter; | 109 character = zeroWidthSpaceCharacter; |
| 110 | 110 |
| 111 U16_APPEND(destination, *destinationLength, length, character, error); | 111 U16_APPEND(destination, *destinationLength, length, character, error); |
| 112 ASSERT_UNUSED(error, !error); | 112 ASSERT_UNUSED(error, !error); |
| 113 } | 113 } |
| 114 } | 114 } |
| 115 | 115 |
| 116 HarfBuzzShaper::HarfBuzzShaper(const Font* font, const TextRun& run) | 116 HarfBuzzShaper::HarfBuzzShaper(const Font* font, const TextRun& run) |
| 117 : Shaper(font, run) | 117 : Shaper(font, run) |
| 118 , m_normalizedBufferLength(0) | 118 , m_normalizedBufferLength(0) |
| 119 , m_wordSpacingAdjustment(font->fontDescription().wordSpacing()) | 119 , m_wordSpacingAdjustment(font->getFontDescription().wordSpacing()) |
| 120 , m_letterSpacing(font->fontDescription().letterSpacing()) | 120 , m_letterSpacing(font->getFontDescription().letterSpacing()) |
| 121 , m_expansionOpportunityCount(0) | 121 , m_expansionOpportunityCount(0) |
| 122 { | 122 { |
| 123 m_normalizedBuffer = adoptArrayPtr(new UChar[m_textRun.length() + 1]); | 123 m_normalizedBuffer = adoptArrayPtr(new UChar[m_textRun.length() + 1]); |
| 124 normalizeCharacters(m_textRun, m_textRun.length(), m_normalizedBuffer.get(),
&m_normalizedBufferLength); | 124 normalizeCharacters(m_textRun, m_textRun.length(), m_normalizedBuffer.get(),
&m_normalizedBufferLength); |
| 125 setExpansion(m_textRun.expansion()); | 125 setExpansion(m_textRun.expansion()); |
| 126 setFontFeatures(); | 126 setFontFeatures(); |
| 127 } | 127 } |
| 128 | 128 |
| 129 float HarfBuzzShaper::nextExpansionPerOpportunity() | 129 float HarfBuzzShaper::nextExpansionPerOpportunity() |
| 130 { | 130 { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 m_expansionPerOpportunity = 0; | 164 m_expansionPerOpportunity = 0; |
| 165 } | 165 } |
| 166 | 166 |
| 167 static inline hb_feature_t createFeature(uint8_t c1, uint8_t c2, uint8_t c3, uin
t8_t c4, uint32_t value = 0) | 167 static inline hb_feature_t createFeature(uint8_t c1, uint8_t c2, uint8_t c3, uin
t8_t c4, uint32_t value = 0) |
| 168 { | 168 { |
| 169 return { HB_TAG(c1, c2, c3, c4), value, 0 /* start */, static_cast<unsigned>
(-1) /* end */ }; | 169 return { HB_TAG(c1, c2, c3, c4), value, 0 /* start */, static_cast<unsigned>
(-1) /* end */ }; |
| 170 } | 170 } |
| 171 | 171 |
| 172 void HarfBuzzShaper::setFontFeatures() | 172 void HarfBuzzShaper::setFontFeatures() |
| 173 { | 173 { |
| 174 const FontDescription& description = m_font->fontDescription(); | 174 const FontDescription& description = m_font->getFontDescription(); |
| 175 | 175 |
| 176 static hb_feature_t noKern = createFeature('k', 'e', 'r', 'n'); | 176 static hb_feature_t noKern = createFeature('k', 'e', 'r', 'n'); |
| 177 static hb_feature_t noVkrn = createFeature('v', 'k', 'r', 'n'); | 177 static hb_feature_t noVkrn = createFeature('v', 'k', 'r', 'n'); |
| 178 switch (description.getKerning()) { | 178 switch (description.getKerning()) { |
| 179 case FontDescription::NormalKerning: | 179 case FontDescription::NormalKerning: |
| 180 // kern/vkrn are enabled by default | 180 // kern/vkrn are enabled by default |
| 181 break; | 181 break; |
| 182 case FontDescription::NoneKerning: | 182 case FontDescription::NoneKerning: |
| 183 m_features.append(description.isVerticalAnyUpright() ? noVkrn : noKern); | 183 m_features.append(description.isVerticalAnyUpright() ? noVkrn : noKern); |
| 184 break; | 184 break; |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 325 const FontPlatformData* platformData = &(currentFont->platformData()); | 325 const FontPlatformData* platformData = &(currentFont->platformData()); |
| 326 HarfBuzzFace* face = platformData->harfBuzzFace(); | 326 HarfBuzzFace* face = platformData->harfBuzzFace(); |
| 327 if (!face) { | 327 if (!face) { |
| 328 WTF_LOG_ERROR("Could not create HarfBuzzFace from FontPlatformData."); | 328 WTF_LOG_ERROR("Could not create HarfBuzzFace from FontPlatformData."); |
| 329 return false; | 329 return false; |
| 330 } | 330 } |
| 331 | 331 |
| 332 hb_buffer_set_language(harfBuzzBuffer, language); | 332 hb_buffer_set_language(harfBuzzBuffer, language); |
| 333 hb_buffer_set_script(harfBuzzBuffer, ICUScriptToHBScript(currentRunScript)); | 333 hb_buffer_set_script(harfBuzzBuffer, ICUScriptToHBScript(currentRunScript)); |
| 334 hb_buffer_set_direction(harfBuzzBuffer, TextDirectionToHBDirection(m_textRun
.direction(), | 334 hb_buffer_set_direction(harfBuzzBuffer, TextDirectionToHBDirection(m_textRun
.direction(), |
| 335 m_font->fontDescription().orientation(), currentFont)); | 335 m_font->getFontDescription().orientation(), currentFont)); |
| 336 | 336 |
| 337 addToHarfBuzzBufferInternal(harfBuzzBuffer, | 337 addToHarfBuzzBufferInternal(harfBuzzBuffer, |
| 338 m_font->fontDescription(), m_normalizedBuffer.get(), m_normalizedBufferL
ength, | 338 m_font->getFontDescription(), m_normalizedBuffer.get(), m_normalizedBuff
erLength, |
| 339 startIndex, numCharacters); | 339 startIndex, numCharacters); |
| 340 | 340 |
| 341 HarfBuzzScopedPtr<hb_font_t> harfBuzzFont(face->createFont(currentFontRangeF
rom, currentFontRangeTo), hb_font_destroy); | 341 HarfBuzzScopedPtr<hb_font_t> harfBuzzFont(face->createFont(currentFontRangeF
rom, currentFontRangeTo), hb_font_destroy); |
| 342 hb_shape(harfBuzzFont.get(), harfBuzzBuffer, m_features.isEmpty() ? 0 : m_fe
atures.data(), m_features.size()); | 342 hb_shape(harfBuzzFont.get(), harfBuzzBuffer, m_features.isEmpty() ? 0 : m_fe
atures.data(), m_features.size()); |
| 343 | 343 |
| 344 return true; | 344 return true; |
| 345 } | 345 } |
| 346 | 346 |
| 347 bool HarfBuzzShaper::extractShapeResults(hb_buffer_t* harfBuzzBuffer, | 347 bool HarfBuzzShaper::extractShapeResults(hb_buffer_t* harfBuzzBuffer, |
| 348 ShapeResult* shapeResult, | 348 ShapeResult* shapeResult, |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 452 // whole grapheme. We do not append it here. For the next glyph we | 452 // whole grapheme. We do not append it here. For the next glyph we |
| 453 // encounter, atChange will be true, and the characters corresponding to | 453 // encounter, atChange will be true, and the characters corresponding to |
| 454 // the grapheme will be added to the TODO queue again, attempting to | 454 // the grapheme will be added to the TODO queue again, attempting to |
| 455 // shape the whole grapheme with the next font. | 455 // shape the whole grapheme with the next font. |
| 456 // When we're getting here with the last resort font, we have no other | 456 // When we're getting here with the last resort font, we have no other |
| 457 // choice than adding boxes to the ShapeResult. | 457 // choice than adding boxes to the ShapeResult. |
| 458 if ((currentClusterResult == NotDef && numCharacters) || isLastResort) { | 458 if ((currentClusterResult == NotDef && numCharacters) || isLastResort) { |
| 459 // Here we need to specify glyph positions. | 459 // Here we need to specify glyph positions. |
| 460 OwnPtr<ShapeResult::RunInfo> run = adoptPtr(new ShapeResult::RunInfo
(currentFont, | 460 OwnPtr<ShapeResult::RunInfo> run = adoptPtr(new ShapeResult::RunInfo
(currentFont, |
| 461 TextDirectionToHBDirection(m_textRun.direction(), | 461 TextDirectionToHBDirection(m_textRun.direction(), |
| 462 m_font->fontDescription().orientation(), currentFont), | 462 m_font->getFontDescription().orientation(), currentFont), |
| 463 ICUScriptToHBScript(currentRunScript), | 463 ICUScriptToHBScript(currentRunScript), |
| 464 startIndex, | 464 startIndex, |
| 465 numGlyphsToInsert, numCharacters)); | 465 numGlyphsToInsert, numCharacters)); |
| 466 insertRunIntoShapeResult(shapeResult, run.release(), lastChangePosit
ion, numGlyphsToInsert, harfBuzzBuffer); | 466 insertRunIntoShapeResult(shapeResult, run.release(), lastChangePosit
ion, numGlyphsToInsert, harfBuzzBuffer); |
| 467 } | 467 } |
| 468 lastChangePosition = glyphIndex; | 468 lastChangePosition = glyphIndex; |
| 469 } | 469 } |
| 470 return true; | 470 return true; |
| 471 } | 471 } |
| 472 | 472 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 516 { | 516 { |
| 517 m_holesQueue.append(HolesQueueItem(action, startIndex, numCharacters)); | 517 m_holesQueue.append(HolesQueueItem(action, startIndex, numCharacters)); |
| 518 } | 518 } |
| 519 | 519 |
| 520 PassRefPtr<ShapeResult> HarfBuzzShaper::shapeResult() | 520 PassRefPtr<ShapeResult> HarfBuzzShaper::shapeResult() |
| 521 { | 521 { |
| 522 RefPtr<ShapeResult> result = ShapeResult::create(m_font, | 522 RefPtr<ShapeResult> result = ShapeResult::create(m_font, |
| 523 m_normalizedBufferLength, m_textRun.direction()); | 523 m_normalizedBufferLength, m_textRun.direction()); |
| 524 HarfBuzzScopedPtr<hb_buffer_t> harfBuzzBuffer(hb_buffer_create(), hb_buffer_
destroy); | 524 HarfBuzzScopedPtr<hb_buffer_t> harfBuzzBuffer(hb_buffer_create(), hb_buffer_
destroy); |
| 525 | 525 |
| 526 const FontDescription& fontDescription = m_font->fontDescription(); | 526 const FontDescription& fontDescription = m_font->getFontDescription(); |
| 527 const String& localeString = fontDescription.locale(); | 527 const String& localeString = fontDescription.locale(); |
| 528 CString locale = localeString.latin1(); | 528 CString locale = localeString.latin1(); |
| 529 const hb_language_t language = hb_language_from_string(locale.data(), locale
.length()); | 529 const hb_language_t language = hb_language_from_string(locale.data(), locale
.length()); |
| 530 | 530 |
| 531 RunSegmenter::RunSegmenterRange segmentRange = { | 531 RunSegmenter::RunSegmenterRange segmentRange = { |
| 532 0, | 532 0, |
| 533 0, | 533 0, |
| 534 USCRIPT_INVALID_CODE, | 534 USCRIPT_INVALID_CODE, |
| 535 OrientationIterator::OrientationInvalid, | 535 OrientationIterator::OrientationInvalid, |
| 536 SmallCapsIterator::SmallCapsSameCase, | 536 SmallCapsIterator::SmallCapsSameCase, |
| 537 FontFallbackPriority::Invalid }; | 537 FontFallbackPriority::Invalid }; |
| 538 RunSegmenter runSegmenter( | 538 RunSegmenter runSegmenter( |
| 539 m_normalizedBuffer.get(), | 539 m_normalizedBuffer.get(), |
| 540 m_normalizedBufferLength, | 540 m_normalizedBufferLength, |
| 541 m_font->fontDescription().orientation(), | 541 m_font->getFontDescription().orientation(), |
| 542 fontDescription.variant()); | 542 fontDescription.variant()); |
| 543 | 543 |
| 544 Vector<UChar32> fallbackCharsHint; | 544 Vector<UChar32> fallbackCharsHint; |
| 545 | 545 |
| 546 // TODO: Check whether this treatAsZerowidthspace from the previous script | 546 // TODO: Check whether this treatAsZerowidthspace from the previous script |
| 547 // segmentation plays a role here, does the new scriptRuniterator handle tha
t correctly? | 547 // segmentation plays a role here, does the new scriptRuniterator handle tha
t correctly? |
| 548 while (runSegmenter.consume(&segmentRange)) { | 548 while (runSegmenter.consume(&segmentRange)) { |
| 549 RefPtr<FontFallbackIterator> fallbackIterator = | 549 RefPtr<FontFallbackIterator> fallbackIterator = |
| 550 m_font->createFontFallbackIterator( | 550 m_font->createFontFallbackIterator( |
| 551 segmentRange.fontFallbackPriority); | 551 segmentRange.fontFallbackPriority); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 592 // these features are enabled but when a user agent simulates small
capitals, it must not attempt to | 592 // these features are enabled but when a user agent simulates small
capitals, it must not attempt to |
| 593 // simulate alternates for codepoints which are considered caseless.
" | 593 // simulate alternates for codepoints which are considered caseless.
" |
| 594 const SimpleFontData* smallcapsAdjustedFont = segmentRange.smallCaps
Behavior == SmallCapsIterator::SmallCapsUppercaseNeeded | 594 const SimpleFontData* smallcapsAdjustedFont = segmentRange.smallCaps
Behavior == SmallCapsIterator::SmallCapsUppercaseNeeded |
| 595 ? currentFont->smallCapsFontData(fontDescription).get() | 595 ? currentFont->smallCapsFontData(fontDescription).get() |
| 596 : currentFont; | 596 : currentFont; |
| 597 | 597 |
| 598 // Compatibility with SimpleFontData approach of keeping a flag for
overriding drawing direction. | 598 // Compatibility with SimpleFontData approach of keeping a flag for
overriding drawing direction. |
| 599 // TODO: crbug.com/506224 This should go away in favor of storing th
at information elsewhere, for example in | 599 // TODO: crbug.com/506224 This should go away in favor of storing th
at information elsewhere, for example in |
| 600 // ShapeResult. | 600 // ShapeResult. |
| 601 const SimpleFontData* directionAndSmallCapsAdjustedFont = fontDataAd
justedForOrientation(smallcapsAdjustedFont, | 601 const SimpleFontData* directionAndSmallCapsAdjustedFont = fontDataAd
justedForOrientation(smallcapsAdjustedFont, |
| 602 m_font->fontDescription().orientation(), | 602 m_font->getFontDescription().orientation(), |
| 603 segmentRange.renderOrientation); | 603 segmentRange.renderOrientation); |
| 604 | 604 |
| 605 if (!shapeRange(harfBuzzBuffer.get(), | 605 if (!shapeRange(harfBuzzBuffer.get(), |
| 606 currentQueueItem.m_startIndex, | 606 currentQueueItem.m_startIndex, |
| 607 currentQueueItem.m_numCharacters, | 607 currentQueueItem.m_numCharacters, |
| 608 directionAndSmallCapsAdjustedFont, | 608 directionAndSmallCapsAdjustedFont, |
| 609 currentFontRangeFrom, | 609 currentFontRangeFrom, |
| 610 currentFontRangeTo, | 610 currentFontRangeTo, |
| 611 segmentRange.script, | 611 segmentRange.script, |
| 612 language)) | 612 language)) |
| (...skipping 25 matching lines...) Expand all Loading... |
| 638 | 638 |
| 639 const SimpleFontData* currentFontData = run->m_fontData.get(); | 639 const SimpleFontData* currentFontData = run->m_fontData.get(); |
| 640 const hb_glyph_info_t* glyphInfos = hb_buffer_get_glyph_infos(harfBuzzBuffer
, 0); | 640 const hb_glyph_info_t* glyphInfos = hb_buffer_get_glyph_infos(harfBuzzBuffer
, 0); |
| 641 const hb_glyph_position_t* glyphPositions = hb_buffer_get_glyph_positions(ha
rfBuzzBuffer, 0); | 641 const hb_glyph_position_t* glyphPositions = hb_buffer_get_glyph_positions(ha
rfBuzzBuffer, 0); |
| 642 const unsigned startCluster = HB_DIRECTION_IS_FORWARD(hb_buffer_get_directio
n(harfBuzzBuffer)) | 642 const unsigned startCluster = HB_DIRECTION_IS_FORWARD(hb_buffer_get_directio
n(harfBuzzBuffer)) |
| 643 ? glyphInfos[startGlyph].cluster : glyphInfos[startGlyph + numGlyphs - 1
].cluster; | 643 ? glyphInfos[startGlyph].cluster : glyphInfos[startGlyph + numGlyphs - 1
].cluster; |
| 644 | 644 |
| 645 float totalAdvance = 0.0f; | 645 float totalAdvance = 0.0f; |
| 646 FloatPoint glyphOrigin; | 646 FloatPoint glyphOrigin; |
| 647 float offsetX, offsetY; | 647 float offsetX, offsetY; |
| 648 float* directionOffset = m_font->fontDescription().isVerticalAnyUpright() ?
&offsetY : &offsetX; | 648 float* directionOffset = m_font->getFontDescription().isVerticalAnyUpright()
? &offsetY : &offsetX; |
| 649 bool hasVerticalOffsets = !HB_DIRECTION_IS_HORIZONTAL(run->m_direction); | 649 bool hasVerticalOffsets = !HB_DIRECTION_IS_HORIZONTAL(run->m_direction); |
| 650 | 650 |
| 651 // HarfBuzz returns result in visual order, no need to flip for RTL. | 651 // HarfBuzz returns result in visual order, no need to flip for RTL. |
| 652 for (unsigned i = 0; i < numGlyphs; ++i) { | 652 for (unsigned i = 0; i < numGlyphs; ++i) { |
| 653 bool runEnd = i + 1 == numGlyphs; | 653 bool runEnd = i + 1 == numGlyphs; |
| 654 uint16_t glyph = glyphInfos[startGlyph + i].codepoint; | 654 uint16_t glyph = glyphInfos[startGlyph + i].codepoint; |
| 655 offsetX = harfBuzzPositionToFloat(glyphPositions[startGlyph + i].x_offse
t); | 655 offsetX = harfBuzzPositionToFloat(glyphPositions[startGlyph + i].x_offse
t); |
| 656 offsetY = -harfBuzzPositionToFloat(glyphPositions[startGlyph + i].y_offs
et); | 656 offsetY = -harfBuzzPositionToFloat(glyphPositions[startGlyph + i].y_offs
et); |
| 657 | 657 |
| 658 // One out of x_advance and y_advance is zero, depending on | 658 // One out of x_advance and y_advance is zero, depending on |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 797 } | 797 } |
| 798 | 798 |
| 799 // Don't need to check m_textRun.allowsTrailingExpansion() since it's covere
d by !m_expansionOpportunityCount above | 799 // Don't need to check m_textRun.allowsTrailingExpansion() since it's covere
d by !m_expansionOpportunityCount above |
| 800 spacing += nextExpansionPerOpportunity(); | 800 spacing += nextExpansionPerOpportunity(); |
| 801 m_isAfterExpansion = true; | 801 m_isAfterExpansion = true; |
| 802 return spacing; | 802 return spacing; |
| 803 } | 803 } |
| 804 | 804 |
| 805 | 805 |
| 806 } // namespace blink | 806 } // namespace blink |
| OLD | NEW |