diff options
| author | Allan Sandfeld Jensen <allan.jensen@digia.com> | 2013-09-13 12:51:20 +0200 |
|---|---|---|
| committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-19 20:50:05 +0200 |
| commit | d441d6f39bb846989d95bcf5caf387b42414718d (patch) | |
| tree | e367e64a75991c554930278175d403c072de6bb8 /Source/WebCore/rendering/RenderQuote.cpp | |
| parent | 0060b2994c07842f4c59de64b5e3e430525c4b90 (diff) | |
| download | qtwebkit-d441d6f39bb846989d95bcf5caf387b42414718d.tar.gz | |
Import Qt5x2 branch of QtWebkit for Qt 5.2
Importing a new snapshot of webkit.
Change-Id: I2d01ad12cdc8af8cb015387641120a9d7ea5f10c
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@digia.com>
Diffstat (limited to 'Source/WebCore/rendering/RenderQuote.cpp')
| -rw-r--r-- | Source/WebCore/rendering/RenderQuote.cpp | 577 |
1 files changed, 332 insertions, 245 deletions
diff --git a/Source/WebCore/rendering/RenderQuote.cpp b/Source/WebCore/rendering/RenderQuote.cpp index da16df5aa..48f1f097e 100644 --- a/Source/WebCore/rendering/RenderQuote.cpp +++ b/Source/WebCore/rendering/RenderQuote.cpp @@ -1,6 +1,7 @@ -/** +/* * Copyright (C) 2011 Nokia Inc. All rights reserved. * Copyright (C) 2012 Google Inc. All rights reserved. + * Copyright (C) 2013 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -22,27 +23,27 @@ #include "config.h" #include "RenderQuote.h" -#include "RenderView.h" -#include <wtf/text/AtomicString.h> +#include "QuotesData.h" -#define U(x) ((const UChar*)L##x) +using namespace WTF::Unicode; namespace WebCore { RenderQuote::RenderQuote(Document* node, QuoteType quote) : RenderText(node, StringImpl::empty()) , m_type(quote) - , m_depth(0) + , m_depth(-1) , 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() @@ -54,252 +55,332 @@ void RenderQuote::willBeDestroyed() void RenderQuote::willBeRemovedFromTree() { RenderText::willBeRemovedFromTree(); - detachQuote(); } -typedef HashMap<AtomicString, const QuotesData*, CaseFoldingHash> QuotesMap; +void RenderQuote::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) +{ + RenderText::styleDidChange(diff, oldStyle); + setText(originalText()); +} + +const unsigned maxDistinctQuoteCharacters = 16; + +#if !ASSERT_DISABLED -static const QuotesMap& quotesDataLanguageMap() +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(); +} - // 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; +#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 QuotesData* basicQuotesData() +static const QuotesForLanguage* quotesForLanguage(const String& language) { - // FIXME: The default quotes should be the fancy quotes for "en". - static const QuotesData* staticBasicQuotes = QuotesData::create(U("\""), U("\""), U("'"), U("'")).leakRef(); - return staticBasicQuotes; + // Table of quotes from http://www.whatwg.org/specs/web-apps/current-work/multipage/rendering.html#quotes + 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)); } -PassRefPtr<StringImpl> RenderQuote::originalText() const +static StringImpl* stringForQuoteCharacter(UChar character) { - 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(); + // 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(); } -void RenderQuote::updateText() +static inline StringImpl* quotationMarkString() { - computePreferredLogicalWidths(0); + static StringImpl* quotationMarkString = stringForQuoteCharacter(quotationMark); + return quotationMarkString; } -void RenderQuote::computePreferredLogicalWidths(float lead) +static inline StringImpl* apostropheString() { - if (!m_attached) - attachQuote(); - setTextInternal(originalText()); - RenderText::computePreferredLogicalWidths(lead); + static StringImpl* apostropheString = stringForQuoteCharacter(apostrophe); + return apostropheString; } -const QuotesData* RenderQuote::quotesData() const +PassRefPtr<StringImpl> RenderQuote::originalText() 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; + 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 OPEN_QUOTE: + 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(); } void RenderQuote::attachQuote() { ASSERT(view()); - ASSERT(!m_attached); - ASSERT(!m_next && !m_previous); + ASSERT(!m_isAttached); + ASSERT(!m_next); + ASSERT(!m_previous); + ASSERT(isRooted()); - // FIXME: Don't set pref widths dirty during layout. See updateDepth() for - // more detail. - if (!isRooted()) { - setNeedsLayoutAndPrefWidthsRecalc(); - return; - } - - 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) { @@ -308,22 +389,23 @@ 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; @@ -335,37 +417,42 @@ 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; } void RenderQuote::updateDepth() { - ASSERT(m_attached); - int oldDepth = m_depth; - m_depth = 0; + ASSERT(m_isAttached); + int depth = 0; if (m_previous) { - m_depth = m_previous->m_depth; + depth = m_previous->m_depth; + if (depth < 0) + depth = 0; switch (m_previous->m_type) { case OPEN_QUOTE: case NO_OPEN_QUOTE: - m_depth++; + depth++; break; case CLOSE_QUOTE: case NO_CLOSE_QUOTE: - if (m_depth) - m_depth--; break; } } - // FIXME: Don't call setNeedsLayout or dirty our preferred widths during layout. - // This is likely to fail anyway as one of our ancestor will call setNeedsLayout(false), - // preventing the future layout to occur on |this|. The solution is to move that to a - // pre-layout phase. - if (oldDepth != m_depth) - setNeedsLayoutAndPrefWidthsRecalc(); + switch (m_type) { + case OPEN_QUOTE: + case NO_OPEN_QUOTE: + break; + case CLOSE_QUOTE: + case NO_CLOSE_QUOTE: + depth--; + break; + } + if (m_depth == depth) + return; + m_depth = depth; + setText(originalText()); } } // namespace WebCore |
