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 |