Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(192)

Side by Side Diff: Source/core/rendering/RenderQuote.cpp

Issue 934853002: Move and rename RenderQuote and RenderWordBreak. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Source/core/rendering/RenderQuote.h ('k') | Source/core/rendering/RenderView.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /**
2 * Copyright (C) 2011 Nokia Inc. All rights reserved.
3 * Copyright (C) 2012 Google Inc. All rights reserved.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 *
20 */
21
22 #include "config.h"
23 #include "core/rendering/RenderQuote.h"
24
25 #include "core/rendering/RenderTextFragment.h"
26 #include "core/rendering/RenderView.h"
27 #include "wtf/StdLibExtras.h"
28 #include "wtf/text/AtomicString.h"
29
30 #include <algorithm>
31
32 namespace blink {
33
34 RenderQuote::RenderQuote(Document* node, QuoteType quote)
35 : RenderInline(0)
36 , m_type(quote)
37 , m_depth(0)
38 , m_next(nullptr)
39 , m_previous(nullptr)
40 , m_attached(false)
41 {
42 setDocumentForAnonymous(node);
43 }
44
45 RenderQuote::~RenderQuote()
46 {
47 ASSERT(!m_attached);
48 ASSERT(!m_next && !m_previous);
49 }
50
51 void RenderQuote::willBeDestroyed()
52 {
53 detachQuote();
54 RenderInline::willBeDestroyed();
55 }
56
57 void RenderQuote::willBeRemovedFromTree()
58 {
59 RenderInline::willBeRemovedFromTree();
60 detachQuote();
61 }
62
63 void RenderQuote::styleDidChange(StyleDifference diff, const LayoutStyle* oldSty le)
64 {
65 RenderInline::styleDidChange(diff, oldStyle);
66 updateText();
67 }
68
69 struct Language {
70 const char* lang;
71 UChar open1;
72 UChar close1;
73 UChar open2;
74 UChar close2;
75 QuotesData* data;
76
77 bool operator<(const Language& b) const { return strcmp(lang, b.lang) < 0; }
78 };
79
80 // Table of quotes from http://www.whatwg.org/specs/web-apps/current-work/multip age/rendering.html#quote
81 Language languages[] = {
82 { "af", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
83 { "agq", 0x201e, 0x201d, 0x201a, 0x2019, 0 },
84 { "ak", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
85 { "am", 0x00ab, 0x00bb, 0x2039, 0x203a, 0 },
86 { "ar", 0x201d, 0x201c, 0x2019, 0x2018, 0 },
87 { "asa", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
88 { "az-cyrl", 0x00ab, 0x00bb, 0x2039, 0x203a, 0 },
89 { "bas", 0x00ab, 0x00bb, 0x201e, 0x201c, 0 },
90 { "bem", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
91 { "bez", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
92 { "bg", 0x201e, 0x201c, 0x201a, 0x2018, 0 },
93 { "bm", 0x00ab, 0x00bb, 0x201c, 0x201d, 0 },
94 { "bn", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
95 { "br", 0x00ab, 0x00bb, 0x2039, 0x203a, 0 },
96 { "brx", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
97 { "bs-cyrl" , 0x201e, 0x201c, 0x201a, 0x2018, 0 },
98 { "ca", 0x201c, 0x201d, 0x00ab, 0x00bb, 0 },
99 { "cgg", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
100 { "chr", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
101 { "cs", 0x201e, 0x201c, 0x201a, 0x2018, 0 },
102 { "da", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
103 { "dav", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
104 { "de", 0x201e, 0x201c, 0x201a, 0x2018, 0 },
105 { "de-ch", 0x00ab, 0x00bb, 0x2039, 0x203a, 0 },
106 { "dje", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
107 { "dua", 0x00ab, 0x00bb, 0x2018, 0x2019, 0 },
108 { "dyo", 0x00ab, 0x00bb, 0x201c, 0x201d, 0 },
109 { "dz", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
110 { "ebu", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
111 { "ee", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
112 { "el", 0x00ab, 0x00bb, 0x201c, 0x201d, 0 },
113 { "en", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
114 { "en-gb", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
115 { "es", 0x201c, 0x201d, 0x00ab, 0x00bb, 0 },
116 { "et", 0x201e, 0x201c, 0x201a, 0x2018, 0 },
117 { "eu", 0x201c, 0x201d, 0x00ab, 0x00bb, 0 },
118 { "ewo", 0x00ab, 0x00bb, 0x201c, 0x201d, 0 },
119 { "fa", 0x00ab, 0x00bb, 0x2039, 0x203a, 0 },
120 { "ff", 0x201e, 0x201d, 0x201a, 0x2019, 0 },
121 { "fi", 0x201d, 0x201d, 0x2019, 0x2019, 0 },
122 { "fr", 0x00ab, 0x00bb, 0x00ab, 0x00bb, 0 },
123 { "fr-ca", 0x00ab, 0x00bb, 0x2039, 0x203a, 0 },
124 { "fr-ch", 0x00ab, 0x00bb, 0x2039, 0x203a, 0 },
125 { "gsw", 0x00ab, 0x00bb, 0x2039, 0x203a, 0 },
126 { "gu", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
127 { "guz", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
128 { "ha", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
129 { "he", 0x0022, 0x0022, 0x0027, 0x0027, 0 },
130 { "hi", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
131 { "hr", 0x201e, 0x201c, 0x201a, 0x2018, 0 },
132 { "hu", 0x201e, 0x201d, 0x00bb, 0x00ab, 0 },
133 { "id", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
134 { "ig", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
135 { "it", 0x00ab, 0x00bb, 0x201c, 0x201d, 0 },
136 { "ja", 0x300c, 0x300d, 0x300e, 0x300f, 0 },
137 { "jgo", 0x00ab, 0x00bb, 0x2039, 0x203a, 0 },
138 { "jmc", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
139 { "kab", 0x00ab, 0x00bb, 0x201c, 0x201d, 0 },
140 { "kam", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
141 { "kde", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
142 { "kea", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
143 { "khq", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
144 { "ki", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
145 { "kkj", 0x00ab, 0x00bb, 0x2039, 0x203a, 0 },
146 { "kln", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
147 { "km", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
148 { "kn", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
149 { "ko", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
150 { "ksb", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
151 { "ksf", 0x00ab, 0x00bb, 0x2018, 0x2019, 0 },
152 { "lag", 0x201d, 0x201d, 0x2019, 0x2019, 0 },
153 { "lg", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
154 { "ln", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
155 { "lo", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
156 { "lt", 0x201e, 0x201c, 0x201e, 0x201c, 0 },
157 { "lu", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
158 { "luo", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
159 { "luy", 0x201e, 0x201c, 0x201a, 0x2018, 0 },
160 { "lv", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
161 { "mas", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
162 { "mer", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
163 { "mfe", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
164 { "mg", 0x00ab, 0x00bb, 0x201c, 0x201d, 0 },
165 { "mgo", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
166 { "mk", 0x201e, 0x201c, 0x201a, 0x2018, 0 },
167 { "ml", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
168 { "mr", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
169 { "ms", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
170 { "mua", 0x00ab, 0x00bb, 0x201c, 0x201d, 0 },
171 { "my", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
172 { "naq", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
173 { "nb", 0x00ab, 0x00bb, 0x2018, 0x2019, 0 },
174 { "nd", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
175 { "nl", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
176 { "nmg", 0x201e, 0x201d, 0x00ab, 0x00bb, 0 },
177 { "nn", 0x00ab, 0x00bb, 0x2018, 0x2019, 0 },
178 { "nnh", 0x00ab, 0x00bb, 0x201c, 0x201d, 0 },
179 { "nus", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
180 { "nyn", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
181 { "pl", 0x201e, 0x201d, 0x00ab, 0x00bb, 0 },
182 { "pt", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
183 { "pt-pt", 0x00ab, 0x00bb, 0x201c, 0x201d, 0 },
184 { "rn", 0x201d, 0x201d, 0x2019, 0x2019, 0 },
185 { "ro", 0x201e, 0x201d, 0x00ab, 0x00bb, 0 },
186 { "rof", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
187 { "ru", 0x00ab, 0x00bb, 0x201e, 0x201c, 0 },
188 { "rw", 0x00ab, 0x00bb, 0x2018, 0x2019, 0 },
189 { "rwk", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
190 { "saq", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
191 { "sbp", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
192 { "seh", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
193 { "ses", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
194 { "sg", 0x00ab, 0x00bb, 0x201c, 0x201d, 0 },
195 { "shi", 0x00ab, 0x00bb, 0x201e, 0x201d, 0 },
196 { "shi-tfng", 0x00ab, 0x00bb, 0x201e, 0x201d, 0 },
197 { "si", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
198 { "sk", 0x201e, 0x201c, 0x201a, 0x2018, 0 },
199 { "sl", 0x201e, 0x201c, 0x201a, 0x2018, 0 },
200 { "sn", 0x201d, 0x201d, 0x2019, 0x2019, 0 },
201 { "so", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
202 { "sq", 0x201e, 0x201c, 0x201a, 0x2018, 0 },
203 { "sr", 0x201e, 0x201c, 0x201a, 0x2018, 0 },
204 { "sr-latn", 0x201e, 0x201c, 0x201a, 0x2018, 0 },
205 { "sv", 0x201d, 0x201d, 0x2019, 0x2019, 0 },
206 { "sw", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
207 { "swc", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
208 { "ta", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
209 { "te", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
210 { "teo", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
211 { "th", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
212 { "ti-er", 0x2018, 0x2019, 0x201c, 0x201d, 0 },
213 { "to", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
214 { "tr", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
215 { "twq", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
216 { "tzm", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
217 { "uk", 0x00ab, 0x00bb, 0x201e, 0x201c, 0 },
218 { "ur", 0x201d, 0x201c, 0x2019, 0x2018, 0 },
219 { "vai", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
220 { "vai-latn", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
221 { "vi", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
222 { "vun", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
223 { "xh", 0x2018, 0x2019, 0x201c, 0x201d, 0 },
224 { "xog", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
225 { "yav", 0x00ab, 0x00bb, 0x00ab, 0x00bb, 0 },
226 { "yo", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
227 { "zh", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
228 { "zh-hant", 0x300c, 0x300d, 0x300e, 0x300f, 0 },
229 { "zu", 0x201c, 0x201d, 0x2018, 0x2019, 0 },
230 };
231
232 const QuotesData* quotesDataForLanguage(const AtomicString& lang)
233 {
234 if (lang.isNull())
235 return 0;
236
237 // This could be just a hash table, but doing that adds 200k to RenderQuote. o
238 Language* languagesEnd = languages + WTF_ARRAY_LENGTH(languages);
239 CString lowercaseLang = lang.lower().utf8();
240 Language key = { lowercaseLang.data(), 0, 0, 0, 0, 0 };
241 Language* match = std::lower_bound(languages, languagesEnd, key);
242 if (match == languagesEnd || strcmp(match->lang, key.lang))
243 return 0;
244
245 if (!match->data)
246 match->data = QuotesData::create(match->open1, match->close1, match->ope n2, match->close2).leakRef();
247
248 return match->data;
249 }
250
251 static const QuotesData* basicQuotesData()
252 {
253 // FIXME: The default quotes should be the fancy quotes for "en".
254 DEFINE_STATIC_REF(QuotesData, staticBasicQuotes, (QuotesData::create('"', '" ', '\'', '\'')));
255 return staticBasicQuotes;
256 }
257
258 void RenderQuote::updateText()
259 {
260 String text = computeText();
261 if (m_text == text)
262 return;
263
264 m_text = text;
265
266 RenderTextFragment* fragment = findFragmentChild();
267 if (fragment) {
268 fragment->setStyle(style());
269 fragment->setContentString(m_text.impl());
270 } else {
271 fragment = new RenderTextFragment(&document(), m_text.impl());
272 fragment->setStyle(style());
273 addChild(fragment);
274 }
275 }
276
277 RenderTextFragment* RenderQuote::findFragmentChild() const
278 {
279 // We walk from the end of the child list because, if we've had a first-lett er
280 // renderer inserted then the remaining text will be at the end.
281 while (LayoutObject* child = lastChild()) {
282 if (child->isText() && toRenderText(child)->isTextFragment())
283 return toRenderTextFragment(child);
284 }
285
286 return nullptr;
287 }
288
289 String RenderQuote::computeText() const
290 {
291 switch (m_type) {
292 case NO_OPEN_QUOTE:
293 case NO_CLOSE_QUOTE:
294 return emptyString();
295 case CLOSE_QUOTE:
296 return quotesData()->getCloseQuote(m_depth - 1).impl();
297 case OPEN_QUOTE:
298 return quotesData()->getOpenQuote(m_depth).impl();
299 }
300 ASSERT_NOT_REACHED();
301 return emptyString();
302 }
303
304 const QuotesData* RenderQuote::quotesData() const
305 {
306 if (const QuotesData* customQuotes = style()->quotes())
307 return customQuotes;
308
309 if (const QuotesData* quotes = quotesDataForLanguage(style()->locale()))
310 return quotes;
311
312 return basicQuotesData();
313 }
314
315 void RenderQuote::attachQuote()
316 {
317 ASSERT(view());
318 ASSERT(!m_attached);
319 ASSERT(!m_next && !m_previous);
320 ASSERT(isRooted());
321
322 if (!view()->renderQuoteHead()) {
323 view()->setRenderQuoteHead(this);
324 m_attached = true;
325 return;
326 }
327
328 for (LayoutObject* predecessor = previousInPreOrder(); predecessor; predeces sor = predecessor->previousInPreOrder()) {
329 // Skip unattached predecessors to avoid having stale m_previous pointer s
330 // if the previous node is never attached and is then destroyed.
331 if (!predecessor->isQuote() || !toRenderQuote(predecessor)->isAttached() )
332 continue;
333 m_previous = toRenderQuote(predecessor);
334 m_next = m_previous->m_next;
335 m_previous->m_next = this;
336 if (m_next)
337 m_next->m_previous = this;
338 break;
339 }
340
341 if (!m_previous) {
342 m_next = view()->renderQuoteHead();
343 view()->setRenderQuoteHead(this);
344 if (m_next)
345 m_next->m_previous = this;
346 }
347 m_attached = true;
348
349 for (RenderQuote* quote = this; quote; quote = quote->m_next)
350 quote->updateDepth();
351
352 ASSERT(!m_next || m_next->m_attached);
353 ASSERT(!m_next || m_next->m_previous == this);
354 ASSERT(!m_previous || m_previous->m_attached);
355 ASSERT(!m_previous || m_previous->m_next == this);
356 }
357
358 void RenderQuote::detachQuote()
359 {
360 ASSERT(!m_next || m_next->m_attached);
361 ASSERT(!m_previous || m_previous->m_attached);
362 if (!m_attached)
363 return;
364
365 // Reset our attached status at this point because it's possible for
366 // updateDepth() to call into attachQuote(). Attach quote walks the render
367 // tree looking for quotes that are attached and does work on them.
368 m_attached = false;
369
370 if (m_previous)
371 m_previous->m_next = m_next;
372 else if (view())
373 view()->setRenderQuoteHead(m_next);
374 if (m_next)
375 m_next->m_previous = m_previous;
376 if (!documentBeingDestroyed()) {
377 for (RenderQuote* quote = m_next; quote; quote = quote->m_next)
378 quote->updateDepth();
379 }
380 m_next = nullptr;
381 m_previous = nullptr;
382 m_depth = 0;
383 }
384
385 void RenderQuote::updateDepth()
386 {
387 ASSERT(m_attached);
388 int oldDepth = m_depth;
389 m_depth = 0;
390 if (m_previous) {
391 m_depth = m_previous->m_depth;
392 switch (m_previous->m_type) {
393 case OPEN_QUOTE:
394 case NO_OPEN_QUOTE:
395 m_depth++;
396 break;
397 case CLOSE_QUOTE:
398 case NO_CLOSE_QUOTE:
399 if (m_depth)
400 m_depth--;
401 break;
402 }
403 }
404 if (oldDepth != m_depth)
405 updateText();
406 }
407
408 } // namespace blink
OLDNEW
« no previous file with comments | « Source/core/rendering/RenderQuote.h ('k') | Source/core/rendering/RenderView.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698