| 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 |