OLD | NEW |
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 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 if (!style) | 163 if (!style) |
164 return false; | 164 return false; |
165 RefPtrWillBeRawPtr<CSSValue> value = style->getPropertyCSSValue(propertyID); | 165 RefPtrWillBeRawPtr<CSSValue> value = style->getPropertyCSSValue(propertyID); |
166 if (!value) | 166 if (!value) |
167 return true; | 167 return true; |
168 if (!value->isPrimitiveValue()) | 168 if (!value->isPrimitiveValue()) |
169 return false; | 169 return false; |
170 return toCSSPrimitiveValue(value.get())->getValueID() == CSSValueNone; | 170 return toCSSPrimitiveValue(value.get())->getValueID() == CSSValueNone; |
171 } | 171 } |
172 | 172 |
173 static bool needInterchangeNewlineAfter(const VisiblePosition& v) | |
174 { | |
175 VisiblePosition next = v.next(); | |
176 Node* upstreamNode = next.deepEquivalent().upstream().deprecatedNode(); | |
177 Node* downstreamNode = v.deepEquivalent().downstream().deprecatedNode(); | |
178 // Add an interchange newline if a paragraph break is selected and a br won'
t already be added to the markup to represent it. | |
179 return isEndOfParagraph(v) && isStartOfParagraph(next) && !(isHTMLBRElement(
*upstreamNode) && upstreamNode == downstreamNode); | |
180 } | |
181 | |
182 static PassRefPtrWillBeRawPtr<EditingStyle> styleFromMatchedRulesAndInlineDecl(c
onst HTMLElement* element) | |
183 { | |
184 RefPtrWillBeRawPtr<EditingStyle> style = EditingStyle::create(element->inlin
eStyle()); | |
185 // FIXME: Having to const_cast here is ugly, but it is quite a bit of work t
o untangle | |
186 // the non-const-ness of styleFromMatchedRulesForElement. | |
187 style->mergeStyleFromRules(const_cast<HTMLElement*>(element)); | |
188 return style.release(); | |
189 } | |
190 | |
191 static bool isPresentationalHTMLElement(const Node* node) | 173 static bool isPresentationalHTMLElement(const Node* node) |
192 { | 174 { |
193 if (!node->isHTMLElement()) | 175 if (!node->isHTMLElement()) |
194 return false; | 176 return false; |
195 | 177 |
196 const HTMLElement& element = toHTMLElement(*node); | 178 const HTMLElement& element = toHTMLElement(*node); |
197 return element.hasTagName(uTag) || element.hasTagName(sTag) || element.hasTa
gName(strikeTag) | 179 return element.hasTagName(uTag) || element.hasTagName(sTag) || element.hasTa
gName(strikeTag) |
198 || element.hasTagName(iTag) || element.hasTagName(emTag) || element.hasT
agName(bTag) || element.hasTagName(strongTag); | 180 || element.hasTagName(iTag) || element.hasTagName(emTag) || element.hasT
agName(bTag) || element.hasTagName(strongTag); |
199 } | 181 } |
200 | 182 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
256 } | 238 } |
257 | 239 |
258 // FIXME: Shouldn't we omit style info when annotate == DoNotAnnotateForIntercha
nge? | 240 // FIXME: Shouldn't we omit style info when annotate == DoNotAnnotateForIntercha
nge? |
259 // FIXME: At least, annotation and style info should probably not be included in
range.markupString() | 241 // FIXME: At least, annotation and style info should probably not be included in
range.markupString() |
260 static String createMarkupInternal(const Position& startPosition, const Position
& endPosition, | 242 static String createMarkupInternal(const Position& startPosition, const Position
& endPosition, |
261 EAnnotateForInterchange shouldAnnotate, bool convertBlocksToInlines, EAbsolu
teURLs shouldResolveURLs, Node* constrainingAncestor) | 243 EAnnotateForInterchange shouldAnnotate, bool convertBlocksToInlines, EAbsolu
teURLs shouldResolveURLs, Node* constrainingAncestor) |
262 { | 244 { |
263 ASSERT(startPosition.isNotNull()); | 245 ASSERT(startPosition.isNotNull()); |
264 ASSERT(endPosition.isNotNull()); | 246 ASSERT(endPosition.isNotNull()); |
265 ASSERT(startPosition.compareTo(endPosition) <= 0); | 247 ASSERT(startPosition.compareTo(endPosition) <= 0); |
266 DEFINE_STATIC_LOCAL(const String, interchangeNewlineString, ("<br class=\""
AppleInterchangeNewline "\">")); | |
267 | 248 |
268 bool collapsed = startPosition == endPosition; | 249 bool collapsed = startPosition == endPosition; |
269 if (collapsed) | 250 if (collapsed) |
270 return emptyString(); | 251 return emptyString(); |
271 Node* commonAncestor = NodeTraversal::commonAncestor(*startPosition.containe
rNode(), *endPosition.containerNode()); | 252 Node* commonAncestor = NodeTraversal::commonAncestor(*startPosition.containe
rNode(), *endPosition.containerNode()); |
272 if (!commonAncestor) | 253 if (!commonAncestor) |
273 return emptyString(); | 254 return emptyString(); |
274 | 255 |
275 Document* document = startPosition.document(); | 256 Document* document = startPosition.document(); |
276 document->updateLayoutIgnorePendingStylesheets(); | 257 document->updateLayoutIgnorePendingStylesheets(); |
277 | 258 |
278 HTMLBodyElement* body = toHTMLBodyElement(enclosingElementWithTag(firstPosit
ionInNode(commonAncestor), bodyTag)); | |
279 HTMLBodyElement* fullySelectedRoot = nullptr; | |
280 // FIXME: Do this for all fully selected blocks, not just the body. | |
281 if (body && areSameRanges(body, startPosition, endPosition)) | |
282 fullySelectedRoot = body; | |
283 HTMLElement* specialCommonAncestor = highestAncestorToWrapMarkup(startPositi
on, endPosition, shouldAnnotate, constrainingAncestor); | 259 HTMLElement* specialCommonAncestor = highestAncestorToWrapMarkup(startPositi
on, endPosition, shouldAnnotate, constrainingAncestor); |
284 StyledMarkupSerializer accumulator(shouldResolveURLs, shouldAnnotate, startP
osition, endPosition, specialCommonAncestor); | 260 StyledMarkupSerializer serializer(shouldResolveURLs, shouldAnnotate, startPo
sition, endPosition, specialCommonAncestor); |
285 Node* pastEnd = endPosition.nodeAsRangePastLastNode(); | 261 return serializer.createMarkup(convertBlocksToInlines, specialCommonAncestor
); |
286 | |
287 Node* startNode = startPosition.nodeAsRangeFirstNode(); | |
288 VisiblePosition visibleStart(startPosition, VP_DEFAULT_AFFINITY); | |
289 VisiblePosition visibleEnd(endPosition, VP_DEFAULT_AFFINITY); | |
290 if (shouldAnnotate == AnnotateForInterchange && needInterchangeNewlineAfter(
visibleStart)) { | |
291 if (visibleStart == visibleEnd.previous()) | |
292 return interchangeNewlineString; | |
293 | |
294 accumulator.appendString(interchangeNewlineString); | |
295 startNode = visibleStart.next().deepEquivalent().deprecatedNode(); | |
296 | |
297 if (pastEnd && Range::compareBoundaryPoints(startNode, 0, pastEnd, 0, AS
SERT_NO_EXCEPTION) >= 0) | |
298 return interchangeNewlineString; | |
299 } | |
300 | |
301 Node* lastClosed = accumulator.serializeNodes<EditingStrategy>(startNode, pa
stEnd); | |
302 | |
303 if (specialCommonAncestor && lastClosed) { | |
304 // Also include all of the ancestors of lastClosed up to this special an
cestor. | |
305 for (ContainerNode* ancestor = lastClosed->parentNode(); ancestor; ances
tor = ancestor->parentNode()) { | |
306 if (ancestor == fullySelectedRoot && !convertBlocksToInlines) { | |
307 RefPtrWillBeRawPtr<EditingStyle> fullySelectedRootStyle = styleF
romMatchedRulesAndInlineDecl(fullySelectedRoot); | |
308 | |
309 // Bring the background attribute over, but not as an attribute
because a background attribute on a div | |
310 // appears to have no effect. | |
311 if ((!fullySelectedRootStyle || !fullySelectedRootStyle->style()
|| !fullySelectedRootStyle->style()->getPropertyCSSValue(CSSPropertyBackgroundI
mage)) | |
312 && fullySelectedRoot->hasAttribute(backgroundAttr)) | |
313 fullySelectedRootStyle->style()->setProperty(CSSPropertyBack
groundImage, "url('" + fullySelectedRoot->getAttribute(backgroundAttr) + "')"); | |
314 | |
315 if (fullySelectedRootStyle->style()) { | |
316 // Reset the CSS properties to avoid an assertion error in a
ddStyleMarkup(). | |
317 // This assertion is caused at least when we select all text
of a <body> element whose | |
318 // 'text-decoration' property is "inherit", and copy it. | |
319 if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->st
yle(), CSSPropertyTextDecoration)) | |
320 fullySelectedRootStyle->style()->setProperty(CSSProperty
TextDecoration, CSSValueNone); | |
321 if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->st
yle(), CSSPropertyWebkitTextDecorationsInEffect)) | |
322 fullySelectedRootStyle->style()->setProperty(CSSProperty
WebkitTextDecorationsInEffect, CSSValueNone); | |
323 accumulator.wrapWithStyleNode(fullySelectedRootStyle->style(
), true); | |
324 } | |
325 } else { | |
326 // Since this node and all the other ancestors are not in the se
lection we want to set RangeFullySelectsNode to DoesNotFullySelectNode | |
327 // so that styles that affect the exterior of the node are not i
ncluded. | |
328 accumulator.wrapWithNode(*ancestor, convertBlocksToInlines, Styl
edMarkupAccumulator::DoesNotFullySelectNode); | |
329 } | |
330 | |
331 if (ancestor == specialCommonAncestor) | |
332 break; | |
333 } | |
334 } | |
335 | |
336 // FIXME: The interchange newline should be placed in the block that it's in
, not after all of the content, unconditionally. | |
337 if (shouldAnnotate == AnnotateForInterchange && needInterchangeNewlineAfter(
visibleEnd.previous())) | |
338 accumulator.appendString(interchangeNewlineString); | |
339 | |
340 return accumulator.takeResults(); | |
341 } | 262 } |
342 | 263 |
343 String createMarkup(const Range* range, EAnnotateForInterchange shouldAnnotate,
bool convertBlocksToInlines, EAbsoluteURLs shouldResolveURLs, Node* constraining
Ancestor) | 264 String createMarkup(const Range* range, EAnnotateForInterchange shouldAnnotate,
bool convertBlocksToInlines, EAbsoluteURLs shouldResolveURLs, Node* constraining
Ancestor) |
344 { | 265 { |
345 if (!range) | 266 if (!range) |
346 return emptyString(); | 267 return emptyString(); |
347 | 268 |
348 return createMarkupInternal(range->startPosition(), range->endPosition(), sh
ouldAnnotate, convertBlocksToInlines, shouldResolveURLs, constrainingAncestor); | 269 return createMarkupInternal(range->startPosition(), range->endPosition(), sh
ouldAnnotate, convertBlocksToInlines, shouldResolveURLs, constrainingAncestor); |
349 } | 270 } |
350 | 271 |
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
781 node->document().updateLayoutIgnorePendingStylesheets(); | 702 node->document().updateLayoutIgnorePendingStylesheets(); |
782 | 703 |
783 StyledMarkupSerializer serializer(ResolveAllURLs, AnnotateForNavigationTrans
ition, Position(), Position(), 0); | 704 StyledMarkupSerializer serializer(ResolveAllURLs, AnnotateForNavigationTrans
ition, Position(), Position(), 0); |
784 serializer.serializeNodes<EditingStrategy>(node, NodeTraversal::nextSkipping
Children(*node)); | 705 serializer.serializeNodes<EditingStrategy>(node, NodeTraversal::nextSkipping
Children(*node)); |
785 | 706 |
786 static const char* documentMarkup = "<!DOCTYPE html><meta name=\"viewport\"
content=\"width=device-width, user-scalable=0\">"; | 707 static const char* documentMarkup = "<!DOCTYPE html><meta name=\"viewport\"
content=\"width=device-width, user-scalable=0\">"; |
787 return documentMarkup + serializer.takeResults(); | 708 return documentMarkup + serializer.takeResults(); |
788 } | 709 } |
789 | 710 |
790 } | 711 } |
OLD | NEW |