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

Side by Side Diff: Source/core/editing/StyledMarkupSerializer.cpp

Issue 1165833002: Refactoring: Move StyledMarkupSerializer::m_reversedPrecedingMarkup to StyledMarkupAccumulator (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: rebase Created 5 years, 6 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 | Annotate | Revision Log
« no previous file with comments | « Source/core/editing/StyledMarkupSerializer.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserv ed. 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserv ed.
3 * Copyright (C) 2008, 2009, 2010, 2011 Google Inc. All rights reserved. 3 * Copyright (C) 2008, 2009, 2010, 2011 Google Inc. All rights reserved.
4 * Copyright (C) 2011 Igalia S.L. 4 * Copyright (C) 2011 Igalia S.L.
5 * Copyright (C) 2011 Motorola Mobility. All rights reserved. 5 * Copyright (C) 2011 Motorola Mobility. All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
(...skipping 29 matching lines...) Expand all
40 #include "core/editing/iterators/TextIterator.h" 40 #include "core/editing/iterators/TextIterator.h"
41 #include "core/editing/markup.h" 41 #include "core/editing/markup.h"
42 #include "core/html/HTMLBodyElement.h" 42 #include "core/html/HTMLBodyElement.h"
43 #include "core/html/HTMLElement.h" 43 #include "core/html/HTMLElement.h"
44 #include "wtf/text/StringBuilder.h" 44 #include "wtf/text/StringBuilder.h"
45 45
46 namespace blink { 46 namespace blink {
47 47
48 namespace { 48 namespace {
49 49
50 const String& styleNodeCloseTag(bool isBlock)
51 {
52 DEFINE_STATIC_LOCAL(const String, divClose, ("</div>"));
53 DEFINE_STATIC_LOCAL(const String, styleSpanClose, ("</span>"));
54 return isBlock ? divClose : styleSpanClose;
55 }
56
57 template<typename PositionType> 50 template<typename PositionType>
58 TextOffset toTextOffset(const PositionType& position) 51 TextOffset toTextOffset(const PositionType& position)
59 { 52 {
60 if (position.isNull()) 53 if (position.isNull())
61 return TextOffset(); 54 return TextOffset();
62 55
63 if (!position.containerNode()->isTextNode()) 56 if (!position.containerNode()->isTextNode())
64 return TextOffset(); 57 return TextOffset();
65 58
66 return TextOffset(toText(position.containerNode()), position.offsetInContain erNode()); 59 return TextOffset(toText(position.containerNode()), position.offsetInContain erNode());
67 } 60 }
68 61
69 } // namespace 62 } // namespace
70 63
71 using namespace HTMLNames; 64 using namespace HTMLNames;
72 65
73 static Position toPositionInDOMTree(const Position& position) 66 static Position toPositionInDOMTree(const Position& position)
74 { 67 {
75 return position; 68 return position;
76 } 69 }
77 70
78 template<typename Strategy> 71 template<typename Strategy>
79 StyledMarkupSerializer<Strategy>::StyledMarkupSerializer(EAbsoluteURLs shouldRes olveURLs, EAnnotateForInterchange shouldAnnotate, const PositionType& start, con st PositionType& end, Node* highestNodeToBeSerialized, ConvertBlocksToInlines co nvertBlocksToInlines) 72 StyledMarkupSerializer<Strategy>::StyledMarkupSerializer(EAbsoluteURLs shouldRes olveURLs, EAnnotateForInterchange shouldAnnotate, const PositionType& start, con st PositionType& end, Node* highestNodeToBeSerialized, ConvertBlocksToInlines co nvertBlocksToInlines)
80 : m_markupAccumulator(shouldResolveURLs, toTextOffset(start.parentAnchoredEq uivalent()), toTextOffset(end.parentAnchoredEquivalent()), start.document(), sho uldAnnotate, highestNodeToBeSerialized) 73 : m_markupAccumulator(shouldResolveURLs, toTextOffset(start.parentAnchoredEq uivalent()), toTextOffset(end.parentAnchoredEquivalent()), start.document(), sho uldAnnotate, highestNodeToBeSerialized, convertBlocksToInlines)
81 , m_start(start) 74 , m_start(start)
82 , m_end(end) 75 , m_end(end)
83 , m_shouldAnnotate(shouldAnnotate) 76 , m_shouldAnnotate(shouldAnnotate)
84 , m_highestNodeToBeSerialized(highestNodeToBeSerialized) 77 , m_highestNodeToBeSerialized(highestNodeToBeSerialized)
85 , m_convertBlocksToInlines(convertBlocksToInlines)
86 { 78 {
87 } 79 }
88 80
89 static bool needInterchangeNewlineAfter(const VisiblePosition& v) 81 static bool needInterchangeNewlineAfter(const VisiblePosition& v)
90 { 82 {
91 VisiblePosition next = v.next(); 83 VisiblePosition next = v.next();
92 Node* upstreamNode = next.deepEquivalent().upstream().deprecatedNode(); 84 Node* upstreamNode = next.deepEquivalent().upstream().deprecatedNode();
93 Node* downstreamNode = v.deepEquivalent().downstream().deprecatedNode(); 85 Node* downstreamNode = v.deepEquivalent().downstream().deprecatedNode();
94 // Add an interchange newline if a paragraph break is selected and a br won' t already be added to the markup to represent it. 86 // Add an interchange newline if a paragraph break is selected and a br won' t already be added to the markup to represent it.
95 return isEndOfParagraph(v) && isStartOfParagraph(next) && !(isHTMLBRElement( *upstreamNode) && upstreamNode == downstreamNode); 87 return isEndOfParagraph(v) && isStartOfParagraph(next) && !(isHTMLBRElement( *upstreamNode) && upstreamNode == downstreamNode);
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
152 ASSERT(commonAncestor); 144 ASSERT(commonAncestor);
153 HTMLBodyElement* body = toHTMLBodyElement(enclosingElementWithTag(firstP ositionInNode(commonAncestor), bodyTag)); 145 HTMLBodyElement* body = toHTMLBodyElement(enclosingElementWithTag(firstP ositionInNode(commonAncestor), bodyTag));
154 HTMLBodyElement* fullySelectedRoot = nullptr; 146 HTMLBodyElement* fullySelectedRoot = nullptr;
155 // FIXME: Do this for all fully selected blocks, not just the body. 147 // FIXME: Do this for all fully selected blocks, not just the body.
156 if (body && areSameRanges(body, m_start, m_end)) 148 if (body && areSameRanges(body, m_start, m_end))
157 fullySelectedRoot = body; 149 fullySelectedRoot = body;
158 150
159 // Also include all of the ancestors of lastClosed up to this special an cestor. 151 // Also include all of the ancestors of lastClosed up to this special an cestor.
160 // FIXME: What is ancestor? 152 // FIXME: What is ancestor?
161 for (ContainerNode* ancestor = Strategy::parent(*lastClosed); ancestor; ancestor = Strategy::parent(*ancestor)) { 153 for (ContainerNode* ancestor = Strategy::parent(*lastClosed); ancestor; ancestor = Strategy::parent(*ancestor)) {
162 if (ancestor == fullySelectedRoot && !convertBlocksToInlines()) { 154 if (ancestor == fullySelectedRoot && !m_markupAccumulator.convertBlo cksToInlines()) {
163 RefPtrWillBeRawPtr<EditingStyle> fullySelectedRootStyle = styleF romMatchedRulesAndInlineDecl(fullySelectedRoot); 155 RefPtrWillBeRawPtr<EditingStyle> fullySelectedRootStyle = styleF romMatchedRulesAndInlineDecl(fullySelectedRoot);
164 156
165 // Bring the background attribute over, but not as an attribute because a background attribute on a div 157 // Bring the background attribute over, but not as an attribute because a background attribute on a div
166 // appears to have no effect. 158 // appears to have no effect.
167 if ((!fullySelectedRootStyle || !fullySelectedRootStyle->style() || !fullySelectedRootStyle->style()->getPropertyCSSValue(CSSPropertyBackgroundI mage)) 159 if ((!fullySelectedRootStyle || !fullySelectedRootStyle->style() || !fullySelectedRootStyle->style()->getPropertyCSSValue(CSSPropertyBackgroundI mage))
168 && fullySelectedRoot->hasAttribute(backgroundAttr)) 160 && fullySelectedRoot->hasAttribute(backgroundAttr))
169 fullySelectedRootStyle->style()->setProperty(CSSPropertyBack groundImage, "url('" + fullySelectedRoot->getAttribute(backgroundAttr) + "')"); 161 fullySelectedRootStyle->style()->setProperty(CSSPropertyBack groundImage, "url('" + fullySelectedRoot->getAttribute(backgroundAttr) + "')");
170 162
171 if (fullySelectedRootStyle->style()) { 163 if (fullySelectedRootStyle->style()) {
172 // Reset the CSS properties to avoid an assertion error in a ddStyleMarkup(). 164 // Reset the CSS properties to avoid an assertion error in a ddStyleMarkup().
173 // This assertion is caused at least when we select all text of a <body> element whose 165 // This assertion is caused at least when we select all text of a <body> element whose
174 // 'text-decoration' property is "inherit", and copy it. 166 // 'text-decoration' property is "inherit", and copy it.
175 if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->st yle(), CSSPropertyTextDecoration)) 167 if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->st yle(), CSSPropertyTextDecoration))
176 fullySelectedRootStyle->style()->setProperty(CSSProperty TextDecoration, CSSValueNone); 168 fullySelectedRootStyle->style()->setProperty(CSSProperty TextDecoration, CSSValueNone);
177 if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->st yle(), CSSPropertyWebkitTextDecorationsInEffect)) 169 if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->st yle(), CSSPropertyWebkitTextDecorationsInEffect))
178 fullySelectedRootStyle->style()->setProperty(CSSProperty WebkitTextDecorationsInEffect, CSSValueNone); 170 fullySelectedRootStyle->style()->setProperty(CSSProperty WebkitTextDecorationsInEffect, CSSValueNone);
179 wrapWithStyleNode(fullySelectedRootStyle->style(), true); 171 m_markupAccumulator.wrapWithStyleNode(fullySelectedRootStyle ->style(), true);
180 } 172 }
181 } else { 173 } else {
182 // Since this node and all the other ancestors are not in the se lection we want to set RangeFullySelectsNode to DoesNotFullySelectNode 174 // Since this node and all the other ancestors are not in the se lection we want to set RangeFullySelectsNode to DoesNotFullySelectNode
183 // so that styles that affect the exterior of the node are not i ncluded. 175 // so that styles that affect the exterior of the node are not i ncluded.
184 wrapWithNode(*ancestor, StyledMarkupAccumulator::DoesNotFullySel ectNode); 176 m_markupAccumulator.wrapWithNode(*ancestor, StyledMarkupAccumula tor::DoesNotFullySelectNode);
185 } 177 }
186 178
187 if (ancestor == m_highestNodeToBeSerialized) 179 if (ancestor == m_highestNodeToBeSerialized)
188 break; 180 break;
189 } 181 }
190 } 182 }
191 183
192 // FIXME: The interchange newline should be placed in the block that it's in , not after all of the content, unconditionally. 184 // FIXME: The interchange newline should be placed in the block that it's in , not after all of the content, unconditionally.
193 if (m_shouldAnnotate == AnnotateForInterchange && needInterchangeNewlineAt(v isibleEnd)) 185 if (m_shouldAnnotate == AnnotateForInterchange && needInterchangeNewlineAt(v isibleEnd))
194 m_markupAccumulator.appendString(interchangeNewlineString); 186 m_markupAccumulator.appendString(interchangeNewlineString);
195 187
196 return takeResults(); 188 return m_markupAccumulator.takeResults();
197 } 189 }
198 190
199 template<typename Strategy> 191 template<typename Strategy>
200 void StyledMarkupSerializer<Strategy>::wrapWithNode(ContainerNode& node, typenam e StyledMarkupAccumulator::RangeFullySelectsNode rangeFullySelectsNode)
201 {
202 StringBuilder markup;
203 if (node.isElementNode())
204 m_markupAccumulator.appendElement(markup, toElement(node), convertBlocks ToInlines() && isBlock(&node), rangeFullySelectsNode);
205 else
206 m_markupAccumulator.appendStartMarkup(markup, node);
207 m_reversedPrecedingMarkup.append(markup.toString());
208 if (node.isElementNode())
209 m_markupAccumulator.appendEndTag(toElement(node));
210 }
211
212 template<typename Strategy>
213 void StyledMarkupSerializer<Strategy>::wrapWithStyleNode(StylePropertySet* style , bool isBlock)
214 {
215 StringBuilder openTag;
216 m_markupAccumulator.appendStyleNodeOpenTag(openTag, style, isBlock);
217 m_reversedPrecedingMarkup.append(openTag.toString());
218 m_markupAccumulator.appendString(styleNodeCloseTag(isBlock));
219 }
220
221 template<typename Strategy>
222 String StyledMarkupSerializer<Strategy>::takeResults()
223 {
224 StringBuilder result;
225 result.reserveCapacity(MarkupAccumulator::totalLength(m_reversedPrecedingMar kup) + m_markupAccumulator.length());
226
227 for (size_t i = m_reversedPrecedingMarkup.size(); i > 0; --i)
228 result.append(m_reversedPrecedingMarkup[i - 1]);
229
230 m_markupAccumulator.concatenateMarkup(result);
231
232 // We remove '\0' characters because they are not visibly rendered to the us er.
233 return result.toString().replace(0, "");
234 }
235
236 template<typename Strategy>
237 Node* StyledMarkupSerializer<Strategy>::serializeNodes(Node* startNode, Node* pa stEnd) 192 Node* StyledMarkupSerializer<Strategy>::serializeNodes(Node* startNode, Node* pa stEnd)
238 { 193 {
239 if (!m_markupAccumulator.highestNodeToBeSerialized()) { 194 if (!m_markupAccumulator.highestNodeToBeSerialized()) {
240 Node* lastClosed = traverseNodesForSerialization(startNode, pastEnd, Nod eTraversalMode::DoNotEmitString); 195 Node* lastClosed = traverseNodesForSerialization(startNode, pastEnd, Nod eTraversalMode::DoNotEmitString);
241 m_markupAccumulator.setHighestNodeToBeSerialized(lastClosed); 196 m_markupAccumulator.setHighestNodeToBeSerialized(lastClosed);
242 } 197 }
243 198
244 Node* highestNodeToBeSerialized = m_markupAccumulator.highestNodeToBeSeriali zed(); 199 Node* highestNodeToBeSerialized = m_markupAccumulator.highestNodeToBeSeriali zed();
245 if (highestNodeToBeSerialized && Strategy::parent(*highestNodeToBeSerialized )) { 200 if (highestNodeToBeSerialized && Strategy::parent(*highestNodeToBeSerialized )) {
246 bool shouldAnnotate = m_shouldAnnotate == AnnotateForInterchange; 201 bool shouldAnnotate = m_shouldAnnotate == AnnotateForInterchange;
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
319 ASSERT(n); 274 ASSERT(n);
320 Node* lastAncestorClosedOrSelf = Strategy::isDescendantOf(*n, *lastClose d) ? lastClosed : n; 275 Node* lastAncestorClosedOrSelf = Strategy::isDescendantOf(*n, *lastClose d) ? lastClosed : n;
321 for (ContainerNode* parent = Strategy::parent(*lastAncestorClosedOrSelf) ; parent && parent != nextParent; parent = Strategy::parent(*parent)) { 276 for (ContainerNode* parent = Strategy::parent(*lastAncestorClosedOrSelf) ; parent && parent != nextParent; parent = Strategy::parent(*parent)) {
322 // All ancestors that aren't in the ancestorsToClose list should eit her be a) unrendered: 277 // All ancestors that aren't in the ancestorsToClose list should eit her be a) unrendered:
323 if (!parent->layoutObject()) 278 if (!parent->layoutObject())
324 continue; 279 continue;
325 // or b) ancestors that we never encountered during a pre-order trav ersal starting at startNode: 280 // or b) ancestors that we never encountered during a pre-order trav ersal starting at startNode:
326 ASSERT(startNode); 281 ASSERT(startNode);
327 ASSERT(Strategy::isDescendantOf(*startNode, *parent)); 282 ASSERT(Strategy::isDescendantOf(*startNode, *parent));
328 if (shouldEmit) 283 if (shouldEmit)
329 wrapWithNode(*parent); 284 m_markupAccumulator.wrapWithNode(*parent);
330 lastClosed = parent; 285 lastClosed = parent;
331 } 286 }
332 } 287 }
333 288
334 return lastClosed; 289 return lastClosed;
335 } 290 }
336 291
337 template class StyledMarkupSerializer<EditingStrategy>; 292 template class StyledMarkupSerializer<EditingStrategy>;
338 293
339 } // namespace blink 294 } // namespace blink
OLDNEW
« no previous file with comments | « Source/core/editing/StyledMarkupSerializer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698