OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "SymbolsIterator.h" |
| 6 |
| 7 #include <unicode/uchar.h> |
| 8 #include <unicode/uniset.h> |
| 9 |
| 10 namespace blink { |
| 11 |
| 12 using namespace WTF::Unicode; |
| 13 |
| 14 SymbolsIterator::SymbolsIterator(const UChar* buffer, unsigned bufferSize) |
| 15 : m_utf16Iterator(adoptPtr(new UTF16TextIterator(buffer, bufferSize))) |
| 16 , m_bufferSize(bufferSize) |
| 17 , m_nextChar(0) |
| 18 , m_atEnd(bufferSize == 0) |
| 19 , m_currentFontFallbackPriority(FontFallbackPriority::Invalid) |
| 20 { |
| 21 } |
| 22 |
| 23 FontFallbackPriority SymbolsIterator::fontFallbackPriorityForCharacter(UChar32 c
odepoint) |
| 24 { |
| 25 |
| 26 // Those should only be Emoji presentation as combinations of two. |
| 27 if (Character::isEmojiKeycapBase(codepoint) |
| 28 || Character::isRegionalIndicator(codepoint)) |
| 29 return FontFallbackPriority::Text; |
| 30 |
| 31 if (codepoint == combiningEnclosingKeycapCharacter |
| 32 || codepoint == combiningEnclosingCircleBackslashCharacter) |
| 33 return FontFallbackPriority::EmojiEmoji; |
| 34 |
| 35 // There are overlaps between isEmojiTextpresentation and isEmojiEmojiPresen
tation. |
| 36 // We want to prioritize emoji presentation if the character has such a prop
erty. |
| 37 if (Character::isEmojiEmojiPresentation(codepoint) |
| 38 || Character::isEmojiModifierBase(codepoint) |
| 39 || Character::isModifier(codepoint)) |
| 40 return FontFallbackPriority::EmojiEmoji; |
| 41 |
| 42 if (Character::isEmojiTextPresentation(codepoint)) |
| 43 return FontFallbackPriority::EmojiText; |
| 44 |
| 45 UBlockCode block = ublock_getCode(codepoint); |
| 46 |
| 47 switch (block) { |
| 48 case UBLOCK_PLAYING_CARDS: |
| 49 case UBLOCK_MISCELLANEOUS_SYMBOLS: |
| 50 case UBLOCK_MISCELLANEOUS_SYMBOLS_AND_ARROWS: |
| 51 case UBLOCK_MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS: |
| 52 case UBLOCK_TRANSPORT_AND_MAP_SYMBOLS: |
| 53 case UBLOCK_ALCHEMICAL_SYMBOLS: |
| 54 case UBLOCK_RUNIC: |
| 55 case UBLOCK_DINGBATS: |
| 56 case UBLOCK_GOTHIC: |
| 57 return FontFallbackPriority::Symbols; |
| 58 case UBLOCK_ARROWS: |
| 59 case UBLOCK_MATHEMATICAL_OPERATORS: |
| 60 case UBLOCK_MISCELLANEOUS_TECHNICAL: |
| 61 case UBLOCK_GEOMETRIC_SHAPES: |
| 62 case UBLOCK_MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A: |
| 63 case UBLOCK_SUPPLEMENTAL_ARROWS_A: |
| 64 case UBLOCK_SUPPLEMENTAL_ARROWS_B: |
| 65 case UBLOCK_MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B: |
| 66 case UBLOCK_SUPPLEMENTAL_MATHEMATICAL_OPERATORS: |
| 67 case UBLOCK_MATHEMATICAL_ALPHANUMERIC_SYMBOLS: |
| 68 case UBLOCK_ARABIC_MATHEMATICAL_ALPHABETIC_SYMBOLS: |
| 69 case UBLOCK_GEOMETRIC_SHAPES_EXTENDED: |
| 70 return FontFallbackPriority::Math; |
| 71 default: |
| 72 return FontFallbackPriority::Text; |
| 73 } |
| 74 } |
| 75 |
| 76 bool SymbolsIterator::consume(unsigned *symbolsLimit, FontFallbackPriority* font
FallbackPriority) |
| 77 { |
| 78 if (m_atEnd) |
| 79 return false; |
| 80 |
| 81 while (m_utf16Iterator->consume(m_nextChar)) { |
| 82 m_previousFontFallbackPriority = m_currentFontFallbackPriority; |
| 83 unsigned iteratorOffset = m_utf16Iterator->offset(); |
| 84 m_utf16Iterator->advance(); |
| 85 |
| 86 // Except at the beginning, ZWJ just carries over the emoji or neutral |
| 87 // text type, VS15 & VS16 we just carry over as well, since we already |
| 88 // resolved those through lookahead. Also, the text presentation emoji |
| 89 // are upgraded to emoji presentation when combined through ZWJ in the |
| 90 // case of example U+1F441 U+200D U+1F5E8, eye + ZWJ + left speech |
| 91 // bubble, see below. |
| 92 if ((!(m_nextChar == zeroWidthJoinerCharacter |
| 93 && m_previousFontFallbackPriority == FontFallbackPriority::EmojiEmoj
i) |
| 94 && m_nextChar != variationSelector15Character |
| 95 && m_nextChar != variationSelector16Character |
| 96 && !Character::isRegionalIndicator(m_nextChar) |
| 97 && !(m_nextChar == leftSpeechBubbleCharacter |
| 98 && m_previousFontFallbackPriority == FontFallbackPriority::EmojiEmoj
i)) |
| 99 || m_currentFontFallbackPriority == FontFallbackPriority::Invalid) { |
| 100 m_currentFontFallbackPriority = fontFallbackPriorityForCharacter(m_n
extChar); |
| 101 } |
| 102 |
| 103 UChar32 peekChar = 0; |
| 104 if (m_utf16Iterator->consume(peekChar) |
| 105 && peekChar != 0) { |
| 106 |
| 107 // Variation Selectors |
| 108 if (m_currentFontFallbackPriority == FontFallbackPriority::EmojiEmoj
i |
| 109 && peekChar == variationSelector15Character) { |
| 110 m_currentFontFallbackPriority = FontFallbackPriority::EmojiText; |
| 111 } |
| 112 |
| 113 if (m_currentFontFallbackPriority == FontFallbackPriority::EmojiText |
| 114 && peekChar == variationSelector16Character) { |
| 115 m_currentFontFallbackPriority = FontFallbackPriority::EmojiEmoji
; |
| 116 } |
| 117 |
| 118 // Combining characters Keycap... |
| 119 if (Character::isEmojiKeycapBase(m_nextChar) |
| 120 && peekChar == combiningEnclosingKeycapCharacter) { |
| 121 m_currentFontFallbackPriority = FontFallbackPriority::EmojiEmoji
; |
| 122 }; |
| 123 |
| 124 // ...and Combining Enclosing Circle Backslash. |
| 125 if (m_currentFontFallbackPriority == FontFallbackPriority::EmojiText |
| 126 && peekChar == combiningEnclosingCircleBackslashCharacter) { |
| 127 m_currentFontFallbackPriority = FontFallbackPriority::EmojiEmoji
; |
| 128 } |
| 129 |
| 130 // Regional indicators |
| 131 if (Character::isRegionalIndicator(m_nextChar) |
| 132 && Character::isRegionalIndicator(peekChar)) { |
| 133 m_currentFontFallbackPriority = FontFallbackPriority::EmojiEmoji
; |
| 134 } |
| 135 |
| 136 // Upgrade text presentation emoji to emoji presentation when follow
ed by ZWJ, |
| 137 // Example U+1F441 U+200D U+1F5E8, eye + ZWJ + left speech bubble. |
| 138 if (m_nextChar == eyeCharacter && peekChar == zeroWidthJoinerCharact
er) { |
| 139 m_currentFontFallbackPriority = FontFallbackPriority::EmojiEmoji
; |
| 140 } |
| 141 } |
| 142 |
| 143 if (m_previousFontFallbackPriority != m_currentFontFallbackPriority |
| 144 && (m_previousFontFallbackPriority != FontFallbackPriority::Invalid)
) { |
| 145 *symbolsLimit = iteratorOffset; |
| 146 *fontFallbackPriority = m_previousFontFallbackPriority; |
| 147 return true; |
| 148 } |
| 149 } |
| 150 *symbolsLimit = m_bufferSize; |
| 151 *fontFallbackPriority = m_currentFontFallbackPriority; |
| 152 m_atEnd = true; |
| 153 return true; |
| 154 } |
| 155 |
| 156 } |
OLD | NEW |