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 534 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 545 stringFor8BitRun = String::make16BitFrom8BitSource(run.characters8(), ru n.length()); | 545 stringFor8BitRun = String::make16BitFrom8BitSource(run.characters8(), ru n.length()); |
| 546 source = stringFor8BitRun.characters16(); | 546 source = stringFor8BitRun.characters16(); |
| 547 } else { | 547 } else { |
| 548 source = run.characters16(); | 548 source = run.characters16(); |
| 549 } | 549 } |
| 550 | 550 |
| 551 *destinationLength = 0; | 551 *destinationLength = 0; |
| 552 while (position < length) { | 552 while (position < length) { |
| 553 UChar32 character; | 553 UChar32 character; |
| 554 U16_NEXT(source, position, length, character); | 554 U16_NEXT(source, position, length, character); |
| 555 // Don't normalize tabs as they are not treated as spaces for word-end. | 555 if (!(character == tabulationCharacter && run.allowTabs())) { |
| 556 if (run.normalizeSpace() && Character::isNormalizedCanvasSpaceCharacter( character)) | 556 // Don't normalize tabs as they are not treated as spaces for word-e nd. |
| 557 character = spaceCharacter; | 557 if (run.normalizeSpace() && Character::isNormalizedCanvasSpaceCharac ter(character)) |
| 558 else if (Character::treatAsSpace(character) && character != tabulationCh aracter) | 558 character = spaceCharacter; |
| 559 character = spaceCharacter; | 559 else if (Character::treatAsSpace(character) && character != tabulati onCharacter) |
| 560 else if (Character::treatAsZeroWidthSpaceInComplexScript(character)) | 560 character = spaceCharacter; |
| 561 character = zeroWidthSpaceCharacter; | 561 else if (Character::treatAsZeroWidthSpaceInComplexScript(character)) |
| 562 character = zeroWidthSpaceCharacter; | |
| 563 } | |
| 562 | 564 |
| 563 U16_APPEND(destination, *destinationLength, length, character, error); | 565 U16_APPEND(destination, *destinationLength, length, character, error); |
| 564 ASSERT_UNUSED(error, !error); | 566 ASSERT_UNUSED(error, !error); |
| 565 } | 567 } |
| 566 } | 568 } |
| 567 | 569 |
| 568 HarfBuzzShaper::HarfBuzzShaper(const Font* font, const TextRun& run, | 570 HarfBuzzShaper::HarfBuzzShaper(const Font* font, const TextRun& run, |
| 569 HashSet<const SimpleFontData*>* fallbackFonts) | 571 HashSet<const SimpleFontData*>* fallbackFonts) |
| 570 : Shaper(font, run, nullptr, fallbackFonts) | 572 : Shaper(font, run, nullptr, fallbackFonts) |
| 571 , m_normalizedBufferLength(0) | 573 , m_normalizedBufferLength(0) |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 725 } | 727 } |
| 726 | 728 |
| 727 struct CandidateRun { | 729 struct CandidateRun { |
| 728 UChar32 character; | 730 UChar32 character; |
| 729 unsigned start; | 731 unsigned start; |
| 730 unsigned end; | 732 unsigned end; |
| 731 const SimpleFontData* fontData; | 733 const SimpleFontData* fontData; |
| 732 UScriptCode script; | 734 UScriptCode script; |
| 733 }; | 735 }; |
| 734 | 736 |
| 737 static void collectCandidateRunsForTabulationCharacters(UTF16TextIterator& itera tor, | |
| 738 Vector<CandidateRun>* runs, unsigned& startIndexOfCurrentRun, | |
| 739 UChar32& character, const SimpleFontData* currentFontData) | |
| 740 { | |
| 741 ASSERT(character == tabulationCharacter); | |
| 742 for (iterator.advance(); iterator.consume(character); iterator.advance()) { | |
| 743 if (character != tabulationCharacter) | |
| 744 break; | |
| 745 } | |
| 746 CandidateRun run = { tabulationCharacter, startIndexOfCurrentRun, static_cas t<unsigned>(iterator.offset()), currentFontData, USCRIPT_COMMON }; | |
| 747 runs->append(run); | |
| 748 startIndexOfCurrentRun = iterator.offset(); | |
| 749 } | |
| 750 | |
| 751 static inline bool updateCharacterInfo(const Font* font, UChar32 character, cons t TextRun& textRun, | |
|
eae
2015/07/20 17:39:24
Update makes it sound like it has state, how about
kojii
2015/07/21 01:11:47
Glad you suggested this! I once did this but it ma
| |
| 752 const SimpleFontData*& fontData, UScriptCode& script) | |
| 753 { | |
| 754 fontData = font->glyphDataForCharacter(character, false, textRun.normalizeSp ace()).fontData; | |
| 755 UErrorCode errorCode = U_ZERO_ERROR; | |
| 756 script = uscript_getScript(character, &errorCode); | |
| 757 if (U_FAILURE(errorCode)) | |
| 758 return false; | |
| 759 return true; | |
| 760 } | |
| 761 | |
| 735 static inline bool collectCandidateRuns(const UChar* normalizedBuffer, | 762 static inline bool collectCandidateRuns(const UChar* normalizedBuffer, |
| 736 size_t bufferLength, const Font* font, Vector<CandidateRun>* runs, bool isSp aceNormalize) | 763 size_t bufferLength, const Font* font, Vector<CandidateRun>* runs, |
| 764 const TextRun& textRun) | |
| 737 { | 765 { |
| 738 UTF16TextIterator iterator(normalizedBuffer, bufferLength); | 766 UTF16TextIterator iterator(normalizedBuffer, bufferLength); |
| 739 UChar32 character; | 767 UChar32 character; |
| 740 unsigned startIndexOfCurrentRun = 0; | 768 unsigned startIndexOfCurrentRun = 0; |
| 741 | 769 |
| 742 if (!iterator.consume(character)) | 770 if (!iterator.consume(character)) |
| 743 return false; | 771 return false; |
| 744 | 772 |
| 745 const SimpleFontData* nextFontData = font->glyphDataForCharacter(character, false, isSpaceNormalize).fontData; | 773 const SimpleFontData* nextFontData; |
| 746 UErrorCode errorCode = U_ZERO_ERROR; | 774 UScriptCode nextScript; |
| 747 UScriptCode nextScript = uscript_getScript(character, &errorCode); | 775 if (!updateCharacterInfo(font, character, textRun, nextFontData, nextScript) ) |
| 748 if (U_FAILURE(errorCode)) | |
| 749 return false; | 776 return false; |
| 750 | 777 |
| 751 do { | 778 do { |
| 779 // Tab characters need to go to its own run because the run doesn't use Harfbuzz. | |
| 780 if (character == tabulationCharacter && textRun.allowTabs()) { | |
|
eae
2015/07/20 17:39:24
How about adding UNLIKELY macros around the tab ch
kojii
2015/07/21 01:11:47
Thought UNLIKELY() is the past. Thanks, learned on
| |
| 781 collectCandidateRunsForTabulationCharacters(iterator, runs, | |
| 782 startIndexOfCurrentRun, character, nextFontData); | |
| 783 if (iterator.atEnd()) | |
| 784 break; | |
| 785 if (!updateCharacterInfo(font, character, textRun, nextFontData, nex tScript)) | |
| 786 return false; | |
| 787 } | |
| 788 | |
| 752 const UChar* currentCharacterPosition = iterator.characters(); | 789 const UChar* currentCharacterPosition = iterator.characters(); |
| 753 const SimpleFontData* currentFontData = nextFontData; | 790 const SimpleFontData* currentFontData = nextFontData; |
| 754 UScriptCode currentScript = nextScript; | 791 UScriptCode currentScript = nextScript; |
| 755 | 792 |
| 756 UChar32 lastCharacter = character; | 793 UChar32 lastCharacter = character; |
| 757 for (iterator.advance(); iterator.consume(character); iterator.advance() ) { | 794 for (iterator.advance(); iterator.consume(character); iterator.advance() ) { |
| 758 if (Character::treatAsZeroWidthSpace(character)) | 795 if (Character::treatAsZeroWidthSpace(character)) { |
| 796 if (character == tabulationCharacter && textRun.allowTabs()) | |
|
eae
2015/07/20 17:39:24
I'd move this check out of the treatAsZeroWidthSpa
kojii
2015/07/21 01:11:47
That's better to read. treatAsZeroWidthSpace() che
| |
| 797 break; | |
| 759 continue; | 798 continue; |
| 799 } | |
| 760 if ((U_GET_GC_MASK(character) & U_GC_M_MASK) | 800 if ((U_GET_GC_MASK(character) & U_GC_M_MASK) |
| 761 && (Character::isUnicodeVariationSelector(character) | 801 && (Character::isUnicodeVariationSelector(character) |
| 762 || currentFontData->canRenderCombiningCharacterSequence( | 802 || currentFontData->canRenderCombiningCharacterSequence( |
| 763 currentCharacterPosition, | 803 currentCharacterPosition, |
| 764 iterator.glyphEnd() - currentCharacterPosition))) | 804 iterator.glyphEnd() - currentCharacterPosition))) |
| 765 continue; | 805 continue; |
| 766 | 806 |
| 767 nextFontData = font->glyphDataForCharacter(character, false, isSpace Normalize).fontData; | 807 if (!updateCharacterInfo(font, character, textRun, nextFontData, nex tScript)) |
| 768 nextScript = uscript_getScript(character, &errorCode); | |
| 769 if (U_FAILURE(errorCode)) | |
| 770 return false; | 808 return false; |
| 771 if (lastCharacter == zeroWidthJoinerCharacter) | 809 if (lastCharacter == zeroWidthJoinerCharacter) |
| 772 currentFontData = nextFontData; | 810 currentFontData = nextFontData; |
| 773 if ((nextFontData != currentFontData) || ((currentScript != nextScri pt) && (nextScript != USCRIPT_INHERITED) && (!uscript_hasScript(character, curre ntScript)))) | 811 if ((nextFontData != currentFontData) || ((currentScript != nextScri pt) && (nextScript != USCRIPT_INHERITED) && (!uscript_hasScript(character, curre ntScript)))) |
| 774 break; | 812 break; |
| 775 currentCharacterPosition = iterator.characters(); | 813 currentCharacterPosition = iterator.characters(); |
| 776 lastCharacter = character; | 814 lastCharacter = character; |
| 777 } | 815 } |
| 778 | 816 |
| 779 CandidateRun run = { lastCharacter, startIndexOfCurrentRun, static_cast< unsigned>(iterator.offset()), currentFontData, currentScript }; | 817 CandidateRun run = { lastCharacter, startIndexOfCurrentRun, static_cast< unsigned>(iterator.offset()), currentFontData, currentScript }; |
| 780 runs->append(run); | 818 runs->append(run); |
| 781 | 819 |
| 782 startIndexOfCurrentRun = iterator.offset(); | 820 startIndexOfCurrentRun = iterator.offset(); |
| 783 } while (iterator.consume(character)); | 821 } while (!iterator.atEnd()); |
| 784 | 822 |
| 785 return true; | 823 return true; |
| 786 } | 824 } |
| 787 | 825 |
| 788 static inline bool matchesAdjacentRun(UScriptCode* scriptExtensions, int length, | 826 static inline bool matchesAdjacentRun(UScriptCode* scriptExtensions, int length, |
| 789 CandidateRun& adjacentRun) | 827 CandidateRun& adjacentRun) |
| 790 { | 828 { |
| 791 for (int i = 0; i < length; i++) { | 829 for (int i = 0; i < length; i++) { |
| 792 if (scriptExtensions[i] == adjacentRun.script) | 830 if (scriptExtensions[i] == adjacentRun.script) |
| 793 return true; | 831 return true; |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 886 return true; | 924 return true; |
| 887 } | 925 } |
| 888 | 926 |
| 889 bool HarfBuzzShaper::createHarfBuzzRuns() | 927 bool HarfBuzzShaper::createHarfBuzzRuns() |
| 890 { | 928 { |
| 891 if (m_normalizedBufferLength == 1) | 929 if (m_normalizedBufferLength == 1) |
| 892 return createHarfBuzzRunsForSingleCharacter(); | 930 return createHarfBuzzRunsForSingleCharacter(); |
| 893 | 931 |
| 894 Vector<CandidateRun> candidateRuns; | 932 Vector<CandidateRun> candidateRuns; |
| 895 if (!collectCandidateRuns(m_normalizedBuffer.get(), | 933 if (!collectCandidateRuns(m_normalizedBuffer.get(), |
| 896 m_normalizedBufferLength, m_font, &candidateRuns, m_textRun.normalizeSpa ce())) | 934 m_normalizedBufferLength, m_font, &candidateRuns, m_textRun)) |
| 897 return false; | 935 return false; |
| 898 | 936 |
| 899 if (!resolveCandidateRuns(candidateRuns)) | 937 if (!resolveCandidateRuns(candidateRuns)) |
| 900 return false; | 938 return false; |
| 901 | 939 |
| 902 size_t length = candidateRuns.size(); | 940 size_t length = candidateRuns.size(); |
| 903 for (size_t i = 0; i < length; ) { | 941 for (size_t i = 0; i < length; ) { |
| 904 CandidateRun& run = candidateRuns[i]; | 942 CandidateRun& run = candidateRuns[i]; |
| 943 if (run.character == tabulationCharacter && m_textRun.allowTabs()) { | |
|
eae
2015/07/20 17:39:24
Is this really needed? Isn't the extra condition i
kojii
2015/07/21 01:11:47
Yeah, this check is needed if the first run is tab
| |
| 944 addHarfBuzzRun(run.start, run.end, run.fontData, run.script); | |
| 945 ++i; | |
| 946 continue; | |
| 947 } | |
| 905 CandidateRun lastMatchingRun = run; | 948 CandidateRun lastMatchingRun = run; |
| 906 for (i++; i < length; i++) { | 949 for (i++; i < length; i++) { |
| 907 if (candidateRuns[i].script != run.script | 950 if (candidateRuns[i].script != run.script |
| 908 || candidateRuns[i].fontData != run.fontData) | 951 || candidateRuns[i].fontData != run.fontData |
| 952 || candidateRuns[i].character == tabulationCharacter) | |
| 909 break; | 953 break; |
| 910 lastMatchingRun = candidateRuns[i]; | 954 lastMatchingRun = candidateRuns[i]; |
| 911 } | 955 } |
| 912 addHarfBuzzRun(run.start, lastMatchingRun.end, run.fontData, run.script) ; | 956 addHarfBuzzRun(run.start, lastMatchingRun.end, run.fontData, run.script) ; |
| 913 } | 957 } |
| 914 return !m_harfBuzzRuns.isEmpty(); | 958 return !m_harfBuzzRuns.isEmpty(); |
| 915 } | 959 } |
| 916 | 960 |
| 917 // A port of hb_icu_script_to_script because harfbuzz on CrOS is built | 961 // A port of hb_icu_script_to_script because harfbuzz on CrOS is built |
| 918 // without hb-icu. See http://crbug.com/356929 | 962 // without hb-icu. See http://crbug.com/356929 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 951 static const uint16_t* toUint16(const UChar* src) | 995 static const uint16_t* toUint16(const UChar* src) |
| 952 { | 996 { |
| 953 // FIXME: This relies on undefined behavior however it works on the | 997 // FIXME: This relies on undefined behavior however it works on the |
| 954 // current versions of all compilers we care about and avoids making | 998 // current versions of all compilers we care about and avoids making |
| 955 // a copy of the string. | 999 // a copy of the string. |
| 956 static_assert(sizeof(UChar) == sizeof(uint16_t), "UChar should be the same s ize as uint16_t"); | 1000 static_assert(sizeof(UChar) == sizeof(uint16_t), "UChar should be the same s ize as uint16_t"); |
| 957 return reinterpret_cast<const uint16_t*>(src); | 1001 return reinterpret_cast<const uint16_t*>(src); |
| 958 } | 1002 } |
| 959 | 1003 |
| 960 static inline void addToHarfBuzzBufferInternal(hb_buffer_t* buffer, | 1004 static inline void addToHarfBuzzBufferInternal(hb_buffer_t* buffer, |
| 961 const FontDescription& fontDescription, const UChar* normalizedBuffer, | 1005 const FontDescription& fontDescription, const UChar* characters, |
| 962 unsigned startIndex, unsigned numCharacters) | 1006 unsigned numCharacters) |
| 963 { | 1007 { |
| 964 if (fontDescription.variant() == FontVariantSmallCaps | 1008 if (fontDescription.variant() == FontVariantSmallCaps |
| 965 && u_islower(normalizedBuffer[startIndex])) { | 1009 && u_islower(characters[0])) { |
| 966 String upperText = String(normalizedBuffer + startIndex, numCharacters) | 1010 String upperText = String(characters, numCharacters) |
| 967 .upper(); | 1011 .upper(); |
| 968 // TextRun is 16 bit, therefore upperText is 16 bit, even after we call | 1012 // TextRun is 16 bit, therefore upperText is 16 bit, even after we call |
| 969 // makeUpper(). | 1013 // makeUpper(). |
| 970 ASSERT(!upperText.is8Bit()); | 1014 ASSERT(!upperText.is8Bit()); |
| 971 hb_buffer_add_utf16(buffer, toUint16(upperText.characters16()), | 1015 hb_buffer_add_utf16(buffer, toUint16(upperText.characters16()), |
| 972 numCharacters, 0, numCharacters); | 1016 numCharacters, 0, numCharacters); |
| 973 } else { | 1017 } else { |
| 974 hb_buffer_add_utf16(buffer, toUint16(normalizedBuffer + startIndex), | 1018 hb_buffer_add_utf16(buffer, toUint16(characters), |
| 975 numCharacters, 0, numCharacters); | 1019 numCharacters, 0, numCharacters); |
| 976 } | 1020 } |
| 977 } | 1021 } |
| 978 | 1022 |
| 979 PassRefPtr<ShapeResult> HarfBuzzShaper::shapeHarfBuzzRuns() | 1023 PassRefPtr<ShapeResult> HarfBuzzShaper::shapeHarfBuzzRuns() |
| 980 { | 1024 { |
| 981 RefPtr<ShapeResult> result = ShapeResult::create( | 1025 RefPtr<ShapeResult> result = ShapeResult::create( |
| 982 m_normalizedBufferLength, m_textRun.direction()); | 1026 m_normalizedBufferLength, m_textRun.direction()); |
| 983 HarfBuzzScopedPtr<hb_buffer_t> harfBuzzBuffer(hb_buffer_create(), hb_buffer_ destroy); | 1027 HarfBuzzScopedPtr<hb_buffer_t> harfBuzzBuffer(hb_buffer_create(), hb_buffer_ destroy); |
| 984 | 1028 |
| 985 const FontDescription& fontDescription = m_font->fontDescription(); | 1029 const FontDescription& fontDescription = m_font->fontDescription(); |
| 986 const String& localeString = fontDescription.locale(); | 1030 const String& localeString = fontDescription.locale(); |
| 987 CString locale = localeString.latin1(); | 1031 CString locale = localeString.latin1(); |
| 988 const hb_language_t language = hb_language_from_string(locale.data(), locale .length()); | 1032 const hb_language_t language = hb_language_from_string(locale.data(), locale .length()); |
| 989 | 1033 |
| 990 result->m_runs.resize(m_harfBuzzRuns.size()); | 1034 result->m_runs.resize(m_harfBuzzRuns.size()); |
| 991 for (unsigned i = 0; i < m_harfBuzzRuns.size(); ++i) { | 1035 for (unsigned i = 0; i < m_harfBuzzRuns.size(); ++i) { |
| 992 unsigned runIndex = m_textRun.rtl() ? m_harfBuzzRuns.size() - i - 1 : i; | 1036 unsigned runIndex = m_textRun.rtl() ? m_harfBuzzRuns.size() - i - 1 : i; |
| 993 const HarfBuzzRun* currentRun = &m_harfBuzzRuns[runIndex]; | 1037 const HarfBuzzRun* currentRun = &m_harfBuzzRuns[runIndex]; |
| 1038 ASSERT(m_normalizedBufferLength >= currentRun->m_startIndex + currentRun ->m_numCharacters); | |
| 1039 const UChar* characters = m_normalizedBuffer.get() + currentRun->m_start Index; | |
| 1040 | |
| 1041 if (characters[0] == tabulationCharacter && m_textRun.allowTabs()) { | |
| 1042 shapeResultForTabulationCharacters(result.get(), i, currentRun); | |
| 1043 continue; | |
| 1044 } | |
| 994 | 1045 |
| 995 const SimpleFontData* currentFontData = currentRun->m_fontData; | 1046 const SimpleFontData* currentFontData = currentRun->m_fontData; |
| 996 FontPlatformData* platformData = const_cast<FontPlatformData*>(¤tF ontData->platformData()); | 1047 FontPlatformData* platformData = const_cast<FontPlatformData*>(¤tF ontData->platformData()); |
| 997 HarfBuzzFace* face = platformData->harfBuzzFace(); | 1048 HarfBuzzFace* face = platformData->harfBuzzFace(); |
| 998 if (!face) | 1049 if (!face) |
| 999 return nullptr; | 1050 return nullptr; |
| 1000 | 1051 |
| 1001 hb_buffer_set_language(harfBuzzBuffer.get(), language); | 1052 hb_buffer_set_language(harfBuzzBuffer.get(), language); |
| 1002 hb_buffer_set_script(harfBuzzBuffer.get(), currentRun->m_script); | 1053 hb_buffer_set_script(harfBuzzBuffer.get(), currentRun->m_script); |
| 1003 hb_buffer_set_direction(harfBuzzBuffer.get(), currentRun->m_direction); | 1054 hb_buffer_set_direction(harfBuzzBuffer.get(), currentRun->m_direction); |
| 1004 | 1055 |
| 1005 // Add a space as pre-context to the buffer. This prevents showing dotte d-circle | 1056 // Add a space as pre-context to the buffer. This prevents showing dotte d-circle |
| 1006 // for combining marks at the beginning of runs. | 1057 // for combining marks at the beginning of runs. |
| 1007 static const uint16_t preContext = spaceCharacter; | 1058 static const uint16_t preContext = spaceCharacter; |
| 1008 hb_buffer_add_utf16(harfBuzzBuffer.get(), &preContext, 1, 1, 0); | 1059 hb_buffer_add_utf16(harfBuzzBuffer.get(), &preContext, 1, 1, 0); |
| 1009 | 1060 |
| 1010 addToHarfBuzzBufferInternal(harfBuzzBuffer.get(), | 1061 addToHarfBuzzBufferInternal(harfBuzzBuffer.get(), |
| 1011 fontDescription, m_normalizedBuffer.get(), currentRun->m_startIndex, | 1062 fontDescription, characters, currentRun->m_numCharacters); |
| 1012 currentRun->m_numCharacters); | |
| 1013 | 1063 |
| 1014 if (fontDescription.isVerticalAnyUpright()) | 1064 if (fontDescription.isVerticalAnyUpright()) |
| 1015 face->setScriptForVerticalGlyphSubstitution(harfBuzzBuffer.get()); | 1065 face->setScriptForVerticalGlyphSubstitution(harfBuzzBuffer.get()); |
| 1016 | 1066 |
| 1017 HarfBuzzScopedPtr<hb_font_t> harfBuzzFont(face->createFont(), hb_font_de stroy); | 1067 HarfBuzzScopedPtr<hb_font_t> harfBuzzFont(face->createFont(), hb_font_de stroy); |
| 1018 hb_shape(harfBuzzFont.get(), harfBuzzBuffer.get(), m_features.isEmpty() ? 0 : m_features.data(), m_features.size()); | 1068 hb_shape(harfBuzzFont.get(), harfBuzzBuffer.get(), m_features.isEmpty() ? 0 : m_features.data(), m_features.size()); |
| 1019 shapeResult(result.get(), i, currentRun, harfBuzzBuffer.get()); | 1069 shapeResult(result.get(), i, currentRun, harfBuzzBuffer.get()); |
| 1020 | 1070 |
| 1021 hb_buffer_reset(harfBuzzBuffer.get()); | 1071 hb_buffer_reset(harfBuzzBuffer.get()); |
| 1022 } | 1072 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1060 bool runEnd = i + 1 == numGlyphs; | 1110 bool runEnd = i + 1 == numGlyphs; |
| 1061 uint16_t glyph = glyphInfos[i].codepoint; | 1111 uint16_t glyph = glyphInfos[i].codepoint; |
| 1062 offsetX = harfBuzzPositionToFloat(glyphPositions[i].x_offset); | 1112 offsetX = harfBuzzPositionToFloat(glyphPositions[i].x_offset); |
| 1063 offsetY = -harfBuzzPositionToFloat(glyphPositions[i].y_offset); | 1113 offsetY = -harfBuzzPositionToFloat(glyphPositions[i].y_offset); |
| 1064 | 1114 |
| 1065 // One out of x_advance and y_advance is zero, depending on | 1115 // One out of x_advance and y_advance is zero, depending on |
| 1066 // whether the buffer direction is horizontal or vertical. | 1116 // whether the buffer direction is horizontal or vertical. |
| 1067 float advance = harfBuzzPositionToFloat(glyphPositions[i].x_advance - gl yphPositions[i].y_advance); | 1117 float advance = harfBuzzPositionToFloat(glyphPositions[i].x_advance - gl yphPositions[i].y_advance); |
| 1068 unsigned currentCharacterIndex = currentRun->m_startIndex + glyphInfos[i ].cluster; | 1118 unsigned currentCharacterIndex = currentRun->m_startIndex + glyphInfos[i ].cluster; |
| 1069 RELEASE_ASSERT(m_normalizedBufferLength > currentCharacterIndex); | 1119 RELEASE_ASSERT(m_normalizedBufferLength > currentCharacterIndex); |
| 1120 ASSERT(m_normalizedBuffer[currentCharacterIndex] != tabulationCharacter || !m_textRun.allowTabs()); | |
| 1070 bool isClusterEnd = runEnd || glyphInfos[i].cluster != glyphInfos[i + 1] .cluster; | 1121 bool isClusterEnd = runEnd || glyphInfos[i].cluster != glyphInfos[i + 1] .cluster; |
| 1071 float spacing = 0; | 1122 float spacing = 0; |
| 1072 | 1123 |
| 1073 run->m_glyphData[i].characterIndex = glyphInfos[i].cluster; | 1124 run->m_glyphData[i].characterIndex = glyphInfos[i].cluster; |
| 1074 | 1125 |
| 1075 if (isClusterEnd) | 1126 if (isClusterEnd) |
| 1076 spacing += adjustSpacing(run, i, currentCharacterIndex, *directionOf fset, totalAdvance); | 1127 spacing += adjustSpacing(run, i, currentCharacterIndex, *directionOf fset, totalAdvance); |
| 1077 | 1128 |
| 1078 if (currentFontData->isZeroWidthSpaceGlyph(glyph)) { | 1129 if (currentFontData->isZeroWidthSpaceGlyph(glyph)) { |
| 1079 run->setGlyphAndPositions(i, glyph, 0, 0, 0); | 1130 run->setGlyphAndPositions(i, glyph, 0, 0, 0); |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 1096 result->m_glyphBoundingBox.unite(glyphBounds); | 1147 result->m_glyphBoundingBox.unite(glyphBounds); |
| 1097 glyphOrigin += FloatSize(advance + offsetX, offsetY); | 1148 glyphOrigin += FloatSize(advance + offsetX, offsetY); |
| 1098 } | 1149 } |
| 1099 | 1150 |
| 1100 run->m_width = totalAdvance > 0.0 ? totalAdvance : 0.0; | 1151 run->m_width = totalAdvance > 0.0 ? totalAdvance : 0.0; |
| 1101 result->m_width += run->m_width; | 1152 result->m_width += run->m_width; |
| 1102 for (auto& fallbackFont : *m_fallbackFonts) | 1153 for (auto& fallbackFont : *m_fallbackFonts) |
| 1103 result->m_fallbackFonts.add(const_cast<SimpleFontData*>(fallbackFont)); | 1154 result->m_fallbackFonts.add(const_cast<SimpleFontData*>(fallbackFont)); |
| 1104 } | 1155 } |
| 1105 | 1156 |
| 1157 void HarfBuzzShaper::shapeResultForTabulationCharacters(ShapeResult* result, uns igned index, const HarfBuzzRun* currentRun) | |
| 1158 { | |
| 1159 const SimpleFontData& fontData = *currentRun->m_fontData; | |
| 1160 ShapeResult::RunInfo* run = new ShapeResult::RunInfo(currentRun->m_fontData, | |
| 1161 currentRun->m_direction, currentRun->m_script, currentRun->m_startIndex, | |
| 1162 currentRun->m_numCharacters, currentRun->m_numCharacters); | |
| 1163 result->m_runs[index] = run; | |
| 1164 result->m_numGlyphs += currentRun->m_numCharacters; | |
| 1165 float position = m_textRun.xPos() + result->m_width; | |
| 1166 float positionStart = position; | |
| 1167 for (size_t i = 0; i < currentRun->m_numCharacters; ++i) { | |
| 1168 ASSERT(m_normalizedBuffer[currentRun->m_startIndex + i] == tabulationCha racter); | |
| 1169 float advance = m_font->tabWidth(fontData, m_textRun.tabSize(), position ); | |
| 1170 run->m_glyphData[i].characterIndex = i; | |
| 1171 run->setGlyphAndPositions(i, fontData.spaceGlyph(), advance, 0, 0); | |
| 1172 position += advance; | |
| 1173 } | |
| 1174 run->m_width = position - positionStart; | |
| 1175 result->m_width += run->m_width; | |
| 1176 } | |
| 1177 | |
| 1106 float HarfBuzzShaper::adjustSpacing(ShapeResult::RunInfo* run, size_t glyphIndex , unsigned currentCharacterIndex, float& offset, float& totalAdvance) | 1178 float HarfBuzzShaper::adjustSpacing(ShapeResult::RunInfo* run, size_t glyphIndex , unsigned currentCharacterIndex, float& offset, float& totalAdvance) |
| 1107 { | 1179 { |
| 1108 float spacing = 0; | 1180 float spacing = 0; |
| 1109 UChar32 character = m_normalizedBuffer[currentCharacterIndex]; | 1181 UChar32 character = m_normalizedBuffer[currentCharacterIndex]; |
| 1110 if (m_letterSpacing && !Character::treatAsZeroWidthSpace(character)) | 1182 if (m_letterSpacing && !Character::treatAsZeroWidthSpace(character)) |
| 1111 spacing += m_letterSpacing; | 1183 spacing += m_letterSpacing; |
| 1112 | 1184 |
| 1113 bool treatAsSpace = Character::treatAsSpace(character); | 1185 bool treatAsSpace = Character::treatAsSpace(character); |
| 1114 if (treatAsSpace && currentCharacterIndex && (character != '\t' || !m_textRu n.allowTabs())) | 1186 if (treatAsSpace && currentCharacterIndex && (character != '\t' || !m_textRu n.allowTabs())) |
| 1115 spacing += m_wordSpacingAdjustment; | 1187 spacing += m_wordSpacingAdjustment; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1153 return spacing; | 1225 return spacing; |
| 1154 } | 1226 } |
| 1155 | 1227 |
| 1156 // Don't need to check m_textRun.allowsTrailingExpansion() since it's covere d by !m_expansionOpportunityCount above | 1228 // Don't need to check m_textRun.allowsTrailingExpansion() since it's covere d by !m_expansionOpportunityCount above |
| 1157 spacing += nextExpansionPerOpportunity(); | 1229 spacing += nextExpansionPerOpportunity(); |
| 1158 m_isAfterExpansion = true; | 1230 m_isAfterExpansion = true; |
| 1159 return spacing; | 1231 return spacing; |
| 1160 } | 1232 } |
| 1161 | 1233 |
| 1162 } // namespace blink | 1234 } // namespace blink |
| OLD | NEW |