| Index: Source/core/rendering/RenderQuote.cpp
|
| diff --git a/Source/core/rendering/RenderQuote.cpp b/Source/core/rendering/RenderQuote.cpp
|
| index 6586d0438fdf42c6b2622caf4761d93daa271ae2..9cd2c702e74563752cfe3f45dc53c0175e3eda43 100644
|
| --- a/Source/core/rendering/RenderQuote.cpp
|
| +++ b/Source/core/rendering/RenderQuote.cpp
|
| @@ -22,10 +22,9 @@
|
| #include "config.h"
|
| #include "core/rendering/RenderQuote.h"
|
|
|
| -#include "core/rendering/RenderView.h"
|
| -#include <wtf/text/AtomicString.h>
|
| +#include "core/rendering/style/QuotesData.h"
|
|
|
| -#define U(x) ((const UChar*)L##x)
|
| +using namespace WTF::Unicode;
|
|
|
| namespace WebCore {
|
|
|
| @@ -35,14 +34,15 @@ RenderQuote::RenderQuote(Document* node, QuoteType quote)
|
| , m_depth(0)
|
| , m_next(0)
|
| , m_previous(0)
|
| - , m_attached(false)
|
| + , m_isAttached(false)
|
| {
|
| }
|
|
|
| RenderQuote::~RenderQuote()
|
| {
|
| - ASSERT(!m_attached);
|
| - ASSERT(!m_next && !m_previous);
|
| + ASSERT(!m_isAttached);
|
| + ASSERT(!m_next);
|
| + ASSERT(!m_previous);
|
| }
|
|
|
| void RenderQuote::willBeDestroyed()
|
| @@ -63,229 +63,323 @@ void RenderQuote::styleDidChange(StyleDifference diff, const RenderStyle* oldSty
|
| setText(originalText());
|
| }
|
|
|
| -typedef HashMap<AtomicString, const QuotesData*, CaseFoldingHash> QuotesMap;
|
| +const unsigned maxDistinctQuoteCharacters = 16;
|
|
|
| -static const QuotesMap& quotesDataLanguageMap()
|
| +#if !ASSERT_DISABLED
|
| +
|
| +static void checkNumberOfDistinctQuoteCharacters(UChar character)
|
| {
|
| - DEFINE_STATIC_LOCAL(QuotesMap, staticQuotesMap, ());
|
| - if (staticQuotesMap.size())
|
| - return staticQuotesMap;
|
| + ASSERT(character);
|
| + static UChar distinctQuoteCharacters[maxDistinctQuoteCharacters];
|
| + for (unsigned i = 0; i < maxDistinctQuoteCharacters; ++i) {
|
| + if (distinctQuoteCharacters[i] == character)
|
| + return;
|
| + if (!distinctQuoteCharacters[i]) {
|
| + distinctQuoteCharacters[i] = character;
|
| + return;
|
| + }
|
| + }
|
| + ASSERT_NOT_REACHED();
|
| +}
|
| +
|
| +#endif
|
| +
|
| +struct QuotesForLanguage {
|
| + const char* language;
|
| + UChar open1;
|
| + UChar close1;
|
| + UChar open2;
|
| + UChar close2;
|
| +};
|
|
|
| +static int quoteTableLanguageComparisonFunction(const void* a, const void* b)
|
| +{
|
| + return strcmp(static_cast<const QuotesForLanguage*>(a)->language,
|
| + static_cast<const QuotesForLanguage*>(b)->language);
|
| +}
|
| +
|
| +static const QuotesForLanguage* quotesForLanguage(const String& language)
|
| +{
|
| // Table of quotes from http://www.whatwg.org/specs/web-apps/current-work/multipage/rendering.html#quotes
|
| - #define QUOTES_LANG(lang, o1, c1, o2, c2) staticQuotesMap.set(lang, QuotesData::create(U(o1), U(c1), U(o2), U(c2)).leakRef())
|
| - QUOTES_LANG("af", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("agq", "\x201e", "\x201d", "\x201a", "\x2019");
|
| - QUOTES_LANG("ak", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("am", "\x00ab", "\x00bb", "\x2039", "\x203a");
|
| - QUOTES_LANG("ar", "\x201d", "\x201c", "\x2019", "\x2018");
|
| - QUOTES_LANG("asa", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("az-Cyrl", "\x00ab", "\x00bb", "\x2039", "\x203a");
|
| - QUOTES_LANG("bas", "\x00ab", "\x00bb", "\x201e", "\x201c");
|
| - QUOTES_LANG("bem", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("bez", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("bg", "\x201e", "\x201c", "\x201a", "\x2018");
|
| - QUOTES_LANG("bm", "\x00ab", "\x00bb", "\x201c", "\x201d");
|
| - QUOTES_LANG("bn", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("br", "\x00ab", "\x00bb", "\x2039", "\x203a");
|
| - QUOTES_LANG("brx", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("bs-Cyrl", "\x201e", "\x201c", "\x201a", "\x2018");
|
| - QUOTES_LANG("ca", "\x201c", "\x201d", "\x00ab", "\x00bb");
|
| - QUOTES_LANG("cgg", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("chr", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("cs", "\x201e", "\x201c", "\x201a", "\x2018");
|
| - QUOTES_LANG("da", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("dav", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("de", "\x201e", "\x201c", "\x201a", "\x2018");
|
| - QUOTES_LANG("de-CH", "\x00ab", "\x00bb", "\x2039", "\x203a");
|
| - QUOTES_LANG("dje", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("dua", "\x00ab", "\x00bb", "\x2018", "\x2019");
|
| - QUOTES_LANG("dyo", "\x00ab", "\x00bb", "\x201c", "\x201d");
|
| - QUOTES_LANG("dz", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("ebu", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("ee", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("el", "\x00ab", "\x00bb", "\x201c", "\x201d");
|
| - QUOTES_LANG("en", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("en-GB", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("es", "\x201c", "\x201d", "\x00ab", "\x00bb");
|
| - QUOTES_LANG("et", "\x201e", "\x201c", "\x201a", "\x2018");
|
| - QUOTES_LANG("eu", "\x201c", "\x201d", "\x00ab", "\x00bb");
|
| - QUOTES_LANG("ewo", "\x00ab", "\x00bb", "\x201c", "\x201d");
|
| - QUOTES_LANG("fa", "\x00ab", "\x00bb", "\x2039", "\x203a");
|
| - QUOTES_LANG("ff", "\x201e", "\x201d", "\x201a", "\x2019");
|
| - QUOTES_LANG("fi", "\x201d", "\x201d", "\x2019", "\x2019");
|
| - QUOTES_LANG("fr", "\x00ab", "\x00bb", "\x00ab", "\x00bb");
|
| - QUOTES_LANG("fr-CA", "\x00ab", "\x00bb", "\x2039", "\x203a");
|
| - QUOTES_LANG("fr-CH", "\x00ab", "\x00bb", "\x2039", "\x203a");
|
| - QUOTES_LANG("gsw", "\x00ab", "\x00bb", "\x2039", "\x203a");
|
| - QUOTES_LANG("gu", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("guz", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("ha", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("he", "\x0022", "\x0022", "\x0027", "\x0027");
|
| - QUOTES_LANG("hi", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("hr", "\x201e", "\x201c", "\x201a", "\x2018");
|
| - QUOTES_LANG("hu", "\x201e", "\x201d", "\x00bb", "\x00ab");
|
| - QUOTES_LANG("id", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("ig", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("it", "\x00ab", "\x00bb", "\x201c", "\x201d");
|
| - QUOTES_LANG("ja", "\x300c", "\x300d", "\x300e", "\x300f");
|
| - QUOTES_LANG("jgo", "\x00ab", "\x00bb", "\x2039", "\x203a");
|
| - QUOTES_LANG("jmc", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("kab", "\x00ab", "\x00bb", "\x201c", "\x201d");
|
| - QUOTES_LANG("kam", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("kde", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("kea", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("khq", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("ki", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("kkj", "\x00ab", "\x00bb", "\x2039", "\x203a");
|
| - QUOTES_LANG("kln", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("km", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("kn", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("ko", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("ksb", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("ksf", "\x00ab", "\x00bb", "\x2018", "\x2019");
|
| - QUOTES_LANG("lag", "\x201d", "\x201d", "\x2019", "\x2019");
|
| - QUOTES_LANG("lg", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("ln", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("lo", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("lt", "\x201e", "\x201c", "\x201e", "\x201c");
|
| - QUOTES_LANG("lu", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("luo", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("luy", "\x201e", "\x201c", "\x201a", "\x2018");
|
| - QUOTES_LANG("lv", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("mas", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("mer", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("mfe", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("mg", "\x00ab", "\x00bb", "\x201c", "\x201d");
|
| - QUOTES_LANG("mgo", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("mk", "\x201e", "\x201c", "\x201a", "\x2018");
|
| - QUOTES_LANG("ml", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("mr", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("ms", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("mua", "\x00ab", "\x00bb", "\x201c", "\x201d");
|
| - QUOTES_LANG("my", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("naq", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("nb", "\x00ab", "\x00bb", "\x2018", "\x2019");
|
| - QUOTES_LANG("nd", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("nl", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("nmg", "\x201e", "\x201d", "\x00ab", "\x00bb");
|
| - QUOTES_LANG("nn", "\x00ab", "\x00bb", "\x2018", "\x2019");
|
| - QUOTES_LANG("nnh", "\x00ab", "\x00bb", "\x201c", "\x201d");
|
| - QUOTES_LANG("nus", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("nyn", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("pl", "\x201e", "\x201d", "\x00ab", "\x00bb");
|
| - QUOTES_LANG("pt", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("pt-PT", "\x00ab", "\x00bb", "\x201c", "\x201d");
|
| - QUOTES_LANG("rn", "\x201d", "\x201d", "\x2019", "\x2019");
|
| - QUOTES_LANG("ro", "\x201e", "\x201d", "\x00ab", "\x00bb");
|
| - QUOTES_LANG("rof", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("ru", "\x00ab", "\x00bb", "\x201e", "\x201c");
|
| - QUOTES_LANG("rw", "\x00ab", "\x00bb", "\x2018", "\x2019");
|
| - QUOTES_LANG("rwk", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("saq", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("sbp", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("seh", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("ses", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("sg", "\x00ab", "\x00bb", "\x201c", "\x201d");
|
| - QUOTES_LANG("shi", "\x00ab", "\x00bb", "\x201e", "\x201d");
|
| - QUOTES_LANG("shi-Tfng", "\x00ab", "\x00bb", "\x201e", "\x201d");
|
| - QUOTES_LANG("si", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("sk", "\x201e", "\x201c", "\x201a", "\x2018");
|
| - QUOTES_LANG("sl", "\x201e", "\x201c", "\x201a", "\x2018");
|
| - QUOTES_LANG("sn", "\x201d", "\x201d", "\x2019", "\x2019");
|
| - QUOTES_LANG("so", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("sq", "\x201e", "\x201c", "\x201a", "\x2018");
|
| - QUOTES_LANG("sr", "\x201e", "\x201c", "\x201a", "\x2018");
|
| - QUOTES_LANG("sr-Latn", "\x201e", "\x201c", "\x201a", "\x2018");
|
| - QUOTES_LANG("sv", "\x201d", "\x201d", "\x2019", "\x2019");
|
| - QUOTES_LANG("sw", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("swc", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("ta", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("te", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("teo", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("th", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("ti-ER", "\x2018", "\x2019", "\x201c", "\x201d");
|
| - QUOTES_LANG("to", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("tr", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("twq", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("tzm", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("uk", "\x00ab", "\x00bb", "\x201e", "\x201c");
|
| - QUOTES_LANG("ur", "\x201d", "\x201c", "\x2019", "\x2018");
|
| - QUOTES_LANG("vai", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("vai-Latn", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("vi", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("vun", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("xh", "\x2018", "\x2019", "\x201c", "\x201d");
|
| - QUOTES_LANG("xog", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("yav", "\x00ab", "\x00bb", "\x00ab", "\x00bb");
|
| - QUOTES_LANG("yo", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("zh", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - QUOTES_LANG("zh-Hant", "\x300c", "\x300d", "\x300e", "\x300f");
|
| - QUOTES_LANG("zu", "\x201c", "\x201d", "\x2018", "\x2019");
|
| - #undef QUOTES_LANG
|
| -
|
| - return staticQuotesMap;
|
| + static const QuotesForLanguage quoteTable[] = {
|
| + { "af", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "agq", 0x201e, 0x201d, 0x201a, 0x2019 },
|
| + { "ak", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "am", 0x00ab, 0x00bb, 0x2039, 0x203a },
|
| + { "ar", 0x201d, 0x201c, 0x2019, 0x2018 },
|
| + { "asa", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "az-cyrl", 0x00ab, 0x00bb, 0x2039, 0x203a },
|
| + { "bas", 0x00ab, 0x00bb, 0x201e, 0x201c },
|
| + { "bem", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "bez", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "bg", 0x201e, 0x201c, 0x201a, 0x2018 },
|
| + { "bm", 0x00ab, 0x00bb, 0x201c, 0x201d },
|
| + { "bn", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "br", 0x00ab, 0x00bb, 0x2039, 0x203a },
|
| + { "brx", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "bs-cyrl", 0x201e, 0x201c, 0x201a, 0x2018 },
|
| + { "ca", 0x201c, 0x201d, 0x00ab, 0x00bb },
|
| + { "cgg", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "chr", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "cs", 0x201e, 0x201c, 0x201a, 0x2018 },
|
| + { "da", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "dav", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "de", 0x201e, 0x201c, 0x201a, 0x2018 },
|
| + { "de-ch", 0x00ab, 0x00bb, 0x2039, 0x203a },
|
| + { "dje", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "dua", 0x00ab, 0x00bb, 0x2018, 0x2019 },
|
| + { "dyo", 0x00ab, 0x00bb, 0x201c, 0x201d },
|
| + { "dz", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "ebu", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "ee", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "el", 0x00ab, 0x00bb, 0x201c, 0x201d },
|
| + { "en", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "en-gb", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "es", 0x201c, 0x201d, 0x00ab, 0x00bb },
|
| + { "et", 0x201e, 0x201c, 0x201a, 0x2018 },
|
| + { "eu", 0x201c, 0x201d, 0x00ab, 0x00bb },
|
| + { "ewo", 0x00ab, 0x00bb, 0x201c, 0x201d },
|
| + { "fa", 0x00ab, 0x00bb, 0x2039, 0x203a },
|
| + { "ff", 0x201e, 0x201d, 0x201a, 0x2019 },
|
| + { "fi", 0x201d, 0x201d, 0x2019, 0x2019 },
|
| + { "fr", 0x00ab, 0x00bb, 0x00ab, 0x00bb },
|
| + { "fr-ca", 0x00ab, 0x00bb, 0x2039, 0x203a },
|
| + { "fr-ch", 0x00ab, 0x00bb, 0x2039, 0x203a },
|
| + { "gsw", 0x00ab, 0x00bb, 0x2039, 0x203a },
|
| + { "gu", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "guz", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "ha", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "he", 0x0022, 0x0022, 0x0027, 0x0027 },
|
| + { "hi", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "hr", 0x201e, 0x201c, 0x201a, 0x2018 },
|
| + { "hu", 0x201e, 0x201d, 0x00bb, 0x00ab },
|
| + { "id", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "ig", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "it", 0x00ab, 0x00bb, 0x201c, 0x201d },
|
| + { "ja", 0x300c, 0x300d, 0x300e, 0x300f },
|
| + { "jgo", 0x00ab, 0x00bb, 0x2039, 0x203a },
|
| + { "jmc", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "kab", 0x00ab, 0x00bb, 0x201c, 0x201d },
|
| + { "kam", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "kde", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "kea", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "khq", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "ki", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "kkj", 0x00ab, 0x00bb, 0x2039, 0x203a },
|
| + { "kln", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "km", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "kn", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "ko", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "ksb", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "ksf", 0x00ab, 0x00bb, 0x2018, 0x2019 },
|
| + { "lag", 0x201d, 0x201d, 0x2019, 0x2019 },
|
| + { "lg", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "ln", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "lo", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "lt", 0x201e, 0x201c, 0x201e, 0x201c },
|
| + { "lu", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "luo", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "luy", 0x201e, 0x201c, 0x201a, 0x2018 },
|
| + { "lv", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "mas", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "mer", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "mfe", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "mg", 0x00ab, 0x00bb, 0x201c, 0x201d },
|
| + { "mgo", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "mk", 0x201e, 0x201c, 0x201a, 0x2018 },
|
| + { "ml", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "mr", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "ms", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "mua", 0x00ab, 0x00bb, 0x201c, 0x201d },
|
| + { "my", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "naq", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "nb", 0x00ab, 0x00bb, 0x2018, 0x2019 },
|
| + { "nd", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "nl", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "nmg", 0x201e, 0x201d, 0x00ab, 0x00bb },
|
| + { "nn", 0x00ab, 0x00bb, 0x2018, 0x2019 },
|
| + { "nnh", 0x00ab, 0x00bb, 0x201c, 0x201d },
|
| + { "nus", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "nyn", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "pl", 0x201e, 0x201d, 0x00ab, 0x00bb },
|
| + { "pt", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "pt-pt", 0x00ab, 0x00bb, 0x201c, 0x201d },
|
| + { "rn", 0x201d, 0x201d, 0x2019, 0x2019 },
|
| + { "ro", 0x201e, 0x201d, 0x00ab, 0x00bb },
|
| + { "rof", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "ru", 0x00ab, 0x00bb, 0x201e, 0x201c },
|
| + { "rw", 0x00ab, 0x00bb, 0x2018, 0x2019 },
|
| + { "rwk", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "saq", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "sbp", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "seh", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "ses", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "sg", 0x00ab, 0x00bb, 0x201c, 0x201d },
|
| + { "shi", 0x00ab, 0x00bb, 0x201e, 0x201d },
|
| + { "shi-tfng", 0x00ab, 0x00bb, 0x201e, 0x201d },
|
| + { "si", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "sk", 0x201e, 0x201c, 0x201a, 0x2018 },
|
| + { "sl", 0x201e, 0x201c, 0x201a, 0x2018 },
|
| + { "sn", 0x201d, 0x201d, 0x2019, 0x2019 },
|
| + { "so", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "sq", 0x201e, 0x201c, 0x201a, 0x2018 },
|
| + { "sr", 0x201e, 0x201c, 0x201a, 0x2018 },
|
| + { "sr-latn", 0x201e, 0x201c, 0x201a, 0x2018 },
|
| + { "sv", 0x201d, 0x201d, 0x2019, 0x2019 },
|
| + { "sw", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "swc", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "ta", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "te", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "teo", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "th", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "ti-er", 0x2018, 0x2019, 0x201c, 0x201d },
|
| + { "to", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "tr", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "twq", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "tzm", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "uk", 0x00ab, 0x00bb, 0x201e, 0x201c },
|
| + { "ur", 0x201d, 0x201c, 0x2019, 0x2018 },
|
| + { "vai", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "vai-latn", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "vi", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "vun", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "xh", 0x2018, 0x2019, 0x201c, 0x201d },
|
| + { "xog", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "yav", 0x00ab, 0x00bb, 0x00ab, 0x00bb },
|
| + { "yo", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "zh", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + { "zh-hant", 0x300c, 0x300d, 0x300e, 0x300f },
|
| + { "zu", 0x201c, 0x201d, 0x2018, 0x2019 },
|
| + };
|
| +
|
| + const unsigned maxLanguageLength = 8;
|
| +
|
| +#if !ASSERT_DISABLED
|
| + // One time check that the table meets the constraints that the code below relies on.
|
| +
|
| + static bool didOneTimeCheck = false;
|
| + if (!didOneTimeCheck) {
|
| + didOneTimeCheck = true;
|
| +
|
| + checkNumberOfDistinctQuoteCharacters(quotationMark);
|
| + checkNumberOfDistinctQuoteCharacters(apostrophe);
|
| +
|
| + for (unsigned i = 0; i < WTF_ARRAY_LENGTH(quoteTable); ++i) {
|
| + ASSERT(strlen(quoteTable[i].language) <= maxLanguageLength);
|
| +
|
| + if (i)
|
| + ASSERT(strcmp(quoteTable[i - 1].language, quoteTable[i].language) < 0);
|
| +
|
| + for (unsigned j = 0; UChar character = quoteTable[i].language[j]; ++j)
|
| + ASSERT(isASCIILower(character) || character == '-');
|
| +
|
| + checkNumberOfDistinctQuoteCharacters(quoteTable[i].open1);
|
| + checkNumberOfDistinctQuoteCharacters(quoteTable[i].close1);
|
| + checkNumberOfDistinctQuoteCharacters(quoteTable[i].open2);
|
| + checkNumberOfDistinctQuoteCharacters(quoteTable[i].close2);
|
| + }
|
| + }
|
| +#endif
|
| +
|
| + unsigned length = language.length();
|
| + if (!length || length > maxLanguageLength)
|
| + return 0;
|
| +
|
| + char languageKeyBuffer[maxLanguageLength + 1];
|
| + for (unsigned i = 0; i < length; ++i) {
|
| + UChar character = toASCIILower(language[i]);
|
| + if (!(isASCIILower(character) || character == '-'))
|
| + return 0;
|
| + languageKeyBuffer[i] = static_cast<char>(character);
|
| + }
|
| + languageKeyBuffer[length] = 0;
|
| +
|
| + QuotesForLanguage languageKey = { languageKeyBuffer, 0, 0, 0, 0 };
|
| +
|
| + return static_cast<const QuotesForLanguage*>(bsearch(&languageKey,
|
| + quoteTable, WTF_ARRAY_LENGTH(quoteTable), sizeof(quoteTable[0]), quoteTableLanguageComparisonFunction));
|
| }
|
|
|
| -static const QuotesData* basicQuotesData()
|
| +static StringImpl* stringForQuoteCharacter(UChar character)
|
| {
|
| - // FIXME: The default quotes should be the fancy quotes for "en".
|
| - static const QuotesData* staticBasicQuotes = QuotesData::create(U("\""), U("\""), U("'"), U("'")).leakRef();
|
| - return staticBasicQuotes;
|
| + // Use linear search because there is a small number of distinct characters, thus binary search is unneeded.
|
| + ASSERT(character);
|
| + struct StringForCharacter {
|
| + UChar character;
|
| + StringImpl* string;
|
| + };
|
| + static StringForCharacter strings[maxDistinctQuoteCharacters];
|
| + for (unsigned i = 0; i < maxDistinctQuoteCharacters; ++i) {
|
| + if (strings[i].character == character)
|
| + return strings[i].string;
|
| + if (!strings[i].character) {
|
| + strings[i].character = character;
|
| + strings[i].string = StringImpl::create8BitIfPossible(&character, 1).leakRef();
|
| + return strings[i].string;
|
| + }
|
| + }
|
| + ASSERT_NOT_REACHED();
|
| + return StringImpl::empty();
|
| +}
|
| +
|
| +static inline StringImpl* quotationMarkString()
|
| +{
|
| + static StringImpl* quotationMarkString = stringForQuoteCharacter(quotationMark);
|
| + return quotationMarkString;
|
| +}
|
| +
|
| +static inline StringImpl* apostropheString()
|
| +{
|
| + static StringImpl* apostropheString = stringForQuoteCharacter(apostrophe);
|
| + return apostropheString;
|
| }
|
|
|
| PassRefPtr<StringImpl> RenderQuote::originalText() const
|
| {
|
| + if (m_depth < 0)
|
| + return StringImpl::empty();
|
| + bool isOpenQuote = false;
|
| switch (m_type) {
|
| case NO_OPEN_QUOTE:
|
| case NO_CLOSE_QUOTE:
|
| return StringImpl::empty();
|
| - case CLOSE_QUOTE:
|
| - return quotesData()->getCloseQuote(m_depth - 1).impl();
|
| case OPEN_QUOTE:
|
| - return quotesData()->getOpenQuote(m_depth).impl();
|
| + isOpenQuote = true;
|
| + // fall through
|
| + case CLOSE_QUOTE:
|
| + if (const QuotesData* quotes = style()->quotes())
|
| + return isOpenQuote ? quotes->openQuote(m_depth).impl() : quotes->closeQuote(m_depth).impl();
|
| + if (const QuotesForLanguage* quotes = quotesForLanguage(style()->locale()))
|
| + return stringForQuoteCharacter(isOpenQuote ? (m_depth ? quotes->open2 : quotes->open1) : (m_depth ? quotes->close2 : quotes->close1));
|
| + // FIXME: Should the default be the quotes for "en" rather than straight quotes?
|
| + return m_depth ? apostropheString() : quotationMarkString();
|
| }
|
| ASSERT_NOT_REACHED();
|
| return StringImpl::empty();
|
| }
|
|
|
| -const QuotesData* RenderQuote::quotesData() const
|
| -{
|
| - if (QuotesData* customQuotes = style()->quotes())
|
| - return customQuotes;
|
| -
|
| - AtomicString language = style()->locale();
|
| - if (language.isNull())
|
| - return basicQuotesData();
|
| - const QuotesData* quotes = quotesDataLanguageMap().get(language);
|
| - if (!quotes)
|
| - return basicQuotesData();
|
| - return quotes;
|
| -}
|
| -
|
| void RenderQuote::attachQuote()
|
| {
|
| ASSERT(view());
|
| - ASSERT(!m_attached);
|
| - ASSERT(!m_next && !m_previous);
|
| + ASSERT(!m_isAttached);
|
| + ASSERT(!m_next);
|
| + ASSERT(!m_previous);
|
| ASSERT(isRooted());
|
|
|
| - if (!view()->renderQuoteHead()) {
|
| - view()->setRenderQuoteHead(this);
|
| - m_attached = true;
|
| - return;
|
| - }
|
| -
|
| - for (RenderObject* predecessor = previousInPreOrder(); predecessor; predecessor = predecessor->previousInPreOrder()) {
|
| - // Skip unattached predecessors to avoid having stale m_previous pointers
|
| - // if the previous node is never attached and is then destroyed.
|
| - if (!predecessor->isQuote() || !toRenderQuote(predecessor)->isAttached())
|
| - continue;
|
| - m_previous = toRenderQuote(predecessor);
|
| - m_next = m_previous->m_next;
|
| - m_previous->m_next = this;
|
| - if (m_next)
|
| - m_next->m_previous = this;
|
| - break;
|
| + // Optimize case where this is the first quote in a RenderView by not searching for predecessors in that case.
|
| + if (view()->renderQuoteHead()) {
|
| + for (RenderObject* predecessor = previousInPreOrder(); predecessor; predecessor = predecessor->previousInPreOrder()) {
|
| + // Skip unattached predecessors to avoid having stale m_previous pointers
|
| + // if the previous node is never attached and is then destroyed.
|
| + if (!predecessor->isQuote() || !toRenderQuote(predecessor)->m_isAttached)
|
| + continue;
|
| + m_previous = toRenderQuote(predecessor);
|
| + m_next = m_previous->m_next;
|
| + m_previous->m_next = this;
|
| + if (m_next)
|
| + m_next->m_previous = this;
|
| + break;
|
| + }
|
| }
|
|
|
| if (!m_previous) {
|
| @@ -294,22 +388,22 @@ void RenderQuote::attachQuote()
|
| if (m_next)
|
| m_next->m_previous = this;
|
| }
|
| - m_attached = true;
|
| + m_isAttached = true;
|
|
|
| for (RenderQuote* quote = this; quote; quote = quote->m_next)
|
| quote->updateDepth();
|
|
|
| - ASSERT(!m_next || m_next->m_attached);
|
| + ASSERT(!m_next || m_next->m_isAttached);
|
| ASSERT(!m_next || m_next->m_previous == this);
|
| - ASSERT(!m_previous || m_previous->m_attached);
|
| + ASSERT(!m_previous || m_previous->m_isAttached);
|
| ASSERT(!m_previous || m_previous->m_next == this);
|
| }
|
|
|
| void RenderQuote::detachQuote()
|
| {
|
| - ASSERT(!m_next || m_next->m_attached);
|
| - ASSERT(!m_previous || m_previous->m_attached);
|
| - if (!m_attached)
|
| + ASSERT(!m_next || m_next->m_isAttached);
|
| + ASSERT(!m_previous || m_previous->m_isAttached);
|
| + if (!m_isAttached)
|
| return;
|
| if (m_previous)
|
| m_previous->m_next = m_next;
|
| @@ -321,7 +415,7 @@ void RenderQuote::detachQuote()
|
| for (RenderQuote* quote = m_next; quote; quote = quote->m_next)
|
| quote->updateDepth();
|
| }
|
| - m_attached = false;
|
| + m_isAttached = false;
|
| m_next = 0;
|
| m_previous = 0;
|
| m_depth = 0;
|
| @@ -329,7 +423,7 @@ void RenderQuote::detachQuote()
|
|
|
| void RenderQuote::updateDepth()
|
| {
|
| - ASSERT(m_attached);
|
| + ASSERT(m_isAttached);
|
| int oldDepth = m_depth;
|
| m_depth = 0;
|
| if (m_previous) {
|
|
|