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 |