summaryrefslogtreecommitdiff
path: root/Source/WebCore/rendering/RenderQuote.cpp
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@digia.com>2013-09-13 12:51:20 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-09-19 20:50:05 +0200
commitd441d6f39bb846989d95bcf5caf387b42414718d (patch)
treee367e64a75991c554930278175d403c072de6bb8 /Source/WebCore/rendering/RenderQuote.cpp
parent0060b2994c07842f4c59de64b5e3e430525c4b90 (diff)
downloadqtwebkit-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.cpp577
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