Chromium Code Reviews| 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 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 341 // Don't normalize tabs as they are not treated as spaces for word-end. | 341 // Don't normalize tabs as they are not treated as spaces for word-end. |
| 342 if (Font::treatAsSpace(character) && character != '\t') | 342 if (Font::treatAsSpace(character) && character != '\t') |
| 343 character = ' '; | 343 character = ' '; |
| 344 else if (Font::treatAsZeroWidthSpaceInComplexScript(character)) | 344 else if (Font::treatAsZeroWidthSpaceInComplexScript(character)) |
| 345 character = zeroWidthSpace; | 345 character = zeroWidthSpace; |
| 346 U16_APPEND(destination, *destinationLength, length, character, error); | 346 U16_APPEND(destination, *destinationLength, length, character, error); |
| 347 ASSERT_UNUSED(error, !error); | 347 ASSERT_UNUSED(error, !error); |
| 348 } | 348 } |
| 349 } | 349 } |
| 350 | 350 |
| 351 HarfBuzzShaper::HarfBuzzShaper(const Font* font, const TextRun& run) | 351 HarfBuzzShaper::HarfBuzzShaper(const Font* font, const TextRun& run, bool forTex tEmphasis) |
| 352 : m_font(font) | 352 : m_font(font) |
| 353 , m_normalizedBufferLength(0) | 353 , m_normalizedBufferLength(0) |
| 354 , m_run(run) | 354 , m_run(run) |
| 355 , m_wordSpacingAdjustment(font->wordSpacing()) | 355 , m_wordSpacingAdjustment(font->wordSpacing()) |
| 356 , m_padding(0) | 356 , m_padding(0) |
| 357 , m_padPerWordBreak(0) | 357 , m_padPerWordBreak(0) |
| 358 , m_padError(0) | 358 , m_padError(0) |
| 359 , m_letterSpacing(font->letterSpacing()) | 359 , m_letterSpacing(font->letterSpacing()) |
| 360 , m_fromIndex(0) | 360 , m_fromIndex(0) |
| 361 , m_toIndex(m_run.length()) | 361 , m_toIndex(m_run.length()) |
| 362 , m_forTextEmphasis(forTextEmphasis) | |
| 362 { | 363 { |
| 363 m_normalizedBuffer = adoptArrayPtr(new UChar[m_run.length() + 1]); | 364 m_normalizedBuffer = adoptArrayPtr(new UChar[m_run.length() + 1]); |
| 364 normalizeCharacters(m_run, m_run.length(), m_normalizedBuffer.get(), &m_norm alizedBufferLength); | 365 normalizeCharacters(m_run, m_run.length(), m_normalizedBuffer.get(), &m_norm alizedBufferLength); |
| 365 setPadding(m_run.expansion()); | 366 setPadding(m_run.expansion()); |
| 366 setFontFeatures(); | 367 setFontFeatures(); |
| 367 } | 368 } |
| 368 | 369 |
| 369 static void normalizeSpacesAndMirrorChars(const UChar* source, unsigned length, UChar* destination, unsigned* destinationLength, HarfBuzzShaper::NormalizeMode n ormalizeMode) | 370 static void normalizeSpacesAndMirrorChars(const UChar* source, unsigned length, UChar* destination, unsigned* destinationLength, HarfBuzzShaper::NormalizeMode n ormalizeMode) |
| 370 { | 371 { |
| 371 unsigned position = 0; | 372 unsigned position = 0; |
| (...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 667 | 668 |
| 668 hb_buffer_set_script(harfBuzzBuffer.get(), currentRun->script()); | 669 hb_buffer_set_script(harfBuzzBuffer.get(), currentRun->script()); |
| 669 hb_buffer_set_direction(harfBuzzBuffer.get(), currentRun->rtl() ? HB_DIR ECTION_RTL : HB_DIRECTION_LTR); | 670 hb_buffer_set_direction(harfBuzzBuffer.get(), currentRun->rtl() ? HB_DIR ECTION_RTL : HB_DIRECTION_LTR); |
| 670 | 671 |
| 671 hb_segment_properties_t props; | 672 hb_segment_properties_t props; |
| 672 hb_buffer_get_segment_properties(harfBuzzBuffer.get(), &props); | 673 hb_buffer_get_segment_properties(harfBuzzBuffer.get(), &props); |
| 673 | 674 |
| 674 const UChar* src = m_normalizedBuffer.get() + currentRun->startIndex(); | 675 const UChar* src = m_normalizedBuffer.get() + currentRun->startIndex(); |
| 675 std::wstring key(src, src + currentRun->numCharacters()); | 676 std::wstring key(src, src + currentRun->numCharacters()); |
| 676 | 677 |
| 677 CachedShapingResults* cachedResults = runCache.find(key); | 678 CachedShapingResults* cachedResults = m_forTextEmphasis ? 0 : runCache.f ind(key); |
| 678 if (cachedResults) { | 679 if (cachedResults) { |
| 679 if (cachedResults->dir == props.direction && cachedResults->font == *m_font) { | 680 if (cachedResults->dir == props.direction && cachedResults->font == *m_font) { |
| 680 currentRun->applyShapeResult(cachedResults->buffer); | 681 currentRun->applyShapeResult(cachedResults->buffer); |
| 681 setGlyphPositionsForHarfBuzzRun(currentRun, cachedResults->buffe r); | 682 setGlyphPositionsForHarfBuzzRun(currentRun, cachedResults->buffe r); |
| 682 | 683 |
| 683 hb_buffer_reset(harfBuzzBuffer.get()); | 684 hb_buffer_reset(harfBuzzBuffer.get()); |
| 684 | 685 |
| 685 runCache.moveToBack(cachedResults); | 686 runCache.moveToBack(cachedResults); |
| 686 | 687 |
| 687 continue; | 688 continue; |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 706 | 707 |
| 707 if (m_font->fontDescription().orientation() == Vertical) | 708 if (m_font->fontDescription().orientation() == Vertical) |
| 708 face->setScriptForVerticalGlyphSubstitution(harfBuzzBuffer.get()); | 709 face->setScriptForVerticalGlyphSubstitution(harfBuzzBuffer.get()); |
| 709 | 710 |
| 710 HarfBuzzScopedPtr<hb_font_t> harfBuzzFont(face->createFont(), hb_font_de stroy); | 711 HarfBuzzScopedPtr<hb_font_t> harfBuzzFont(face->createFont(), hb_font_de stroy); |
| 711 | 712 |
| 712 hb_shape(harfBuzzFont.get(), harfBuzzBuffer.get(), m_features.isEmpty() ? 0 : m_features.data(), m_features.size()); | 713 hb_shape(harfBuzzFont.get(), harfBuzzBuffer.get(), m_features.isEmpty() ? 0 : m_features.data(), m_features.size()); |
| 713 currentRun->applyShapeResult(harfBuzzBuffer.get()); | 714 currentRun->applyShapeResult(harfBuzzBuffer.get()); |
| 714 setGlyphPositionsForHarfBuzzRun(currentRun, harfBuzzBuffer.get()); | 715 setGlyphPositionsForHarfBuzzRun(currentRun, harfBuzzBuffer.get()); |
| 715 | 716 |
| 716 runCache.insert(key, new CachedShapingResults(harfBuzzBuffer.get(), m_fo nt, props.direction)); | 717 if (!m_forTextEmphasis) |
| 718 runCache.insert(key, new CachedShapingResults(harfBuzzBuffer.get(), m_font, props.direction)); | |
| 717 | 719 |
| 718 harfBuzzBuffer.set(hb_buffer_create()); | 720 harfBuzzBuffer.set(hb_buffer_create()); |
| 719 hb_buffer_set_unicode_funcs(harfBuzzBuffer.get(), hb_icu_get_unicode_fun cs()); | 721 hb_buffer_set_unicode_funcs(harfBuzzBuffer.get(), hb_icu_get_unicode_fun cs()); |
| 720 } | 722 } |
| 721 | 723 |
| 722 return true; | 724 return true; |
| 723 } | 725 } |
| 724 | 726 |
| 725 void HarfBuzzShaper::setGlyphPositionsForHarfBuzzRun(HarfBuzzRun* currentRun, hb _buffer_t* harfBuzzBuffer) | 727 void HarfBuzzShaper::setGlyphPositionsForHarfBuzzRun(HarfBuzzRun* currentRun, hb _buffer_t* harfBuzzBuffer) |
| 726 { | 728 { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 780 float* advances = currentRun->advances(); | 782 float* advances = currentRun->advances(); |
| 781 unsigned numGlyphs = currentRun->numGlyphs(); | 783 unsigned numGlyphs = currentRun->numGlyphs(); |
| 782 uint16_t* glyphToCharacterIndexes = currentRun->glyphToCharacterIndexes(); | 784 uint16_t* glyphToCharacterIndexes = currentRun->glyphToCharacterIndexes(); |
| 783 | 785 |
| 784 for (unsigned i = 0; i < numGlyphs; ++i) { | 786 for (unsigned i = 0; i < numGlyphs; ++i) { |
| 785 uint16_t currentCharacterIndex = currentRun->startIndex() + glyphToChara cterIndexes[i]; | 787 uint16_t currentCharacterIndex = currentRun->startIndex() + glyphToChara cterIndexes[i]; |
| 786 FloatPoint& currentOffset = offsets[i]; | 788 FloatPoint& currentOffset = offsets[i]; |
| 787 FloatPoint& nextOffset = (i == numGlyphs - 1) ? firstOffsetOfNextRun : o ffsets[i + 1]; | 789 FloatPoint& nextOffset = (i == numGlyphs - 1) ? firstOffsetOfNextRun : o ffsets[i + 1]; |
| 788 float glyphAdvanceX = advances[i] + nextOffset.x() - currentOffset.x(); | 790 float glyphAdvanceX = advances[i] + nextOffset.x() - currentOffset.x(); |
| 789 float glyphAdvanceY = nextOffset.y() - currentOffset.y(); | 791 float glyphAdvanceY = nextOffset.y() - currentOffset.y(); |
| 792 | |
| 793 Glyph glyphToAdd = glyphs[i]; | |
| 794 UChar ch = m_run[currentCharacterIndex]; | |
| 795 if (m_forTextEmphasis) | |
| 796 printf("Glyph: 0x%x, Character: 0x%x\n", glyphToAdd, ch); | |
|
Dominik Röttsches
2014/01/16 16:37:32
When running this against:
http://roettsch.es/emph
| |
| 797 | |
| 798 // FIXME: Combining marks should receive a text emphasis mark if they ar e combine with a space. | |
| 799 if (m_forTextEmphasis && (!Font::canReceiveTextEmphasis(ch) || (U_GET_GC _MASK(ch) & U_GC_M_MASK))) | |
| 800 glyphToAdd = 0; | |
| 801 | |
| 790 if (m_run.rtl()) { | 802 if (m_run.rtl()) { |
| 791 if (currentCharacterIndex >= m_toIndex) | 803 if (currentCharacterIndex >= m_toIndex) |
| 792 m_startOffset.move(glyphAdvanceX, glyphAdvanceY); | 804 m_startOffset.move(glyphAdvanceX, glyphAdvanceY); |
| 793 else if (currentCharacterIndex >= m_fromIndex) | 805 else if (currentCharacterIndex >= m_fromIndex) |
| 794 glyphBuffer->add(glyphs[i], currentRun->fontData(), createGlyphB ufferAdvance(glyphAdvanceX, glyphAdvanceY)); | 806 glyphBuffer->add(glyphToAdd, currentRun->fontData(), createGlyph BufferAdvance(glyphAdvanceX, glyphAdvanceY)); |
| 795 } else { | 807 } else { |
| 796 if (currentCharacterIndex < m_fromIndex) | 808 if (currentCharacterIndex < m_fromIndex) |
| 797 m_startOffset.move(glyphAdvanceX, glyphAdvanceY); | 809 m_startOffset.move(glyphAdvanceX, glyphAdvanceY); |
| 798 else if (currentCharacterIndex < m_toIndex) | 810 else if (currentCharacterIndex < m_toIndex) |
| 799 glyphBuffer->add(glyphs[i], currentRun->fontData(), createGlyphB ufferAdvance(glyphAdvanceX, glyphAdvanceY)); | 811 glyphBuffer->add(glyphToAdd, currentRun->fontData(), createGlyph BufferAdvance(glyphAdvanceX, glyphAdvanceY)); |
| 800 } | 812 } |
| 801 } | 813 } |
| 802 } | 814 } |
| 803 | 815 |
| 804 bool HarfBuzzShaper::fillGlyphBuffer(GlyphBuffer* glyphBuffer) | 816 bool HarfBuzzShaper::fillGlyphBuffer(GlyphBuffer* glyphBuffer) |
| 805 { | 817 { |
| 806 unsigned numRuns = m_harfBuzzRuns.size(); | 818 unsigned numRuns = m_harfBuzzRuns.size(); |
| 807 if (m_run.rtl()) { | 819 if (m_run.rtl()) { |
| 808 m_startOffset = m_harfBuzzRuns.last()->offsets()[0]; | 820 m_startOffset = m_harfBuzzRuns.last()->offsets()[0]; |
| 809 for (int runIndex = numRuns - 1; runIndex >= 0; --runIndex) { | 821 for (int runIndex = numRuns - 1; runIndex >= 0; --runIndex) { |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 894 if (!foundToX) | 906 if (!foundToX) |
| 895 toX = m_run.rtl() ? 0 : m_totalWidth; | 907 toX = m_run.rtl() ? 0 : m_totalWidth; |
| 896 | 908 |
| 897 // Using floorf() and roundf() as the same as mac port. | 909 // Using floorf() and roundf() as the same as mac port. |
| 898 if (fromX < toX) | 910 if (fromX < toX) |
| 899 return FloatRect(floorf(point.x() + fromX), point.y(), roundf(toX - from X), height); | 911 return FloatRect(floorf(point.x() + fromX), point.y(), roundf(toX - from X), height); |
| 900 return FloatRect(floorf(point.x() + toX), point.y(), roundf(fromX - toX), he ight); | 912 return FloatRect(floorf(point.x() + toX), point.y(), roundf(fromX - toX), he ight); |
| 901 } | 913 } |
| 902 | 914 |
| 903 } // namespace WebCore | 915 } // namespace WebCore |
| OLD | NEW |