1/* 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. 3 * Copyright (C) 2006 James G. Speth (speth@end.com) 4 * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com) 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28#import "config.h" 29#import "DOMInternal.h" // import first to make the private/public trick work 30#import "DOM.h" 31 32#import "CachedImage.h" 33#import "DOMElementInternal.h" 34#import "DOMHTMLCanvasElement.h" 35#import "DOMHTMLTableCellElementInternal.h" 36#import "DOMNodeInternal.h" 37#import "DOMPrivate.h" 38#import "DOMRangeInternal.h" 39#import "DragImage.h" 40#import "Font.h" 41#import "Frame.h" 42#import "HTMLElement.h" 43#import "HTMLNames.h" 44#import "HTMLParserIdioms.h" 45#import "HTMLTableCellElement.h" 46#import "Image.h" 47#import "JSNode.h" 48#import "NodeFilter.h" 49#import "Page.h" 50#import "Range.h" 51#import "RenderImage.h" 52#import "ScriptController.h" 53#import "WebScriptObjectPrivate.h" 54#import <JavaScriptCore/APICast.h> 55#import <wtf/HashMap.h> 56 57#if PLATFORM(IOS) 58#import "FocusController.h" 59#import "HTMLLinkElement.h" 60#import "KeyboardEvent.h" 61#import "URL.h" 62#import "MediaList.h" 63#import "MediaQueryEvaluator.h" 64#import "NodeRenderStyle.h" 65#import "Page.h" 66#import "RenderView.h" 67#import "Touch.h" 68#import "WAKAppKitStubs.h" 69#import "WAKWindow.h" 70#import "WebCoreThreadMessage.h" 71#endif 72 73using namespace JSC; 74using namespace WebCore; 75 76// FIXME: Would be nice to break this up into separate files to match how other WebKit 77// code is organized. 78 79//------------------------------------------------------------------------------------------ 80// DOMNode 81 82namespace WebCore { 83 84typedef HashMap<const QualifiedName::QualifiedNameImpl*, Class> ObjCClassMap; 85static ObjCClassMap* elementClassMap; 86 87static void addElementClass(const QualifiedName& tag, Class objCClass) 88{ 89 elementClassMap->set(tag.impl(), objCClass); 90} 91 92static void createElementClassMap() 93{ 94 // Create the table. 95 elementClassMap = new ObjCClassMap; 96 97 // FIXME: Reflect marquee once the API has been determined. 98 99 // Populate it with HTML and SVG element classes. 100 addElementClass(HTMLNames::aTag, [DOMHTMLAnchorElement class]); 101 addElementClass(HTMLNames::appletTag, [DOMHTMLAppletElement class]); 102 addElementClass(HTMLNames::areaTag, [DOMHTMLAreaElement class]); 103 addElementClass(HTMLNames::baseTag, [DOMHTMLBaseElement class]); 104 addElementClass(HTMLNames::basefontTag, [DOMHTMLBaseFontElement class]); 105 addElementClass(HTMLNames::bodyTag, [DOMHTMLBodyElement class]); 106 addElementClass(HTMLNames::brTag, [DOMHTMLBRElement class]); 107 addElementClass(HTMLNames::buttonTag, [DOMHTMLButtonElement class]); 108 addElementClass(HTMLNames::canvasTag, [DOMHTMLCanvasElement class]); 109 addElementClass(HTMLNames::captionTag, [DOMHTMLTableCaptionElement class]); 110 addElementClass(HTMLNames::colTag, [DOMHTMLTableColElement class]); 111 addElementClass(HTMLNames::colgroupTag, [DOMHTMLTableColElement class]); 112 addElementClass(HTMLNames::delTag, [DOMHTMLModElement class]); 113 addElementClass(HTMLNames::dirTag, [DOMHTMLDirectoryElement class]); 114 addElementClass(HTMLNames::divTag, [DOMHTMLDivElement class]); 115 addElementClass(HTMLNames::dlTag, [DOMHTMLDListElement class]); 116 addElementClass(HTMLNames::embedTag, [DOMHTMLEmbedElement class]); 117 addElementClass(HTMLNames::fieldsetTag, [DOMHTMLFieldSetElement class]); 118 addElementClass(HTMLNames::fontTag, [DOMHTMLFontElement class]); 119 addElementClass(HTMLNames::formTag, [DOMHTMLFormElement class]); 120 addElementClass(HTMLNames::frameTag, [DOMHTMLFrameElement class]); 121 addElementClass(HTMLNames::framesetTag, [DOMHTMLFrameSetElement class]); 122 addElementClass(HTMLNames::h1Tag, [DOMHTMLHeadingElement class]); 123 addElementClass(HTMLNames::h2Tag, [DOMHTMLHeadingElement class]); 124 addElementClass(HTMLNames::h3Tag, [DOMHTMLHeadingElement class]); 125 addElementClass(HTMLNames::h4Tag, [DOMHTMLHeadingElement class]); 126 addElementClass(HTMLNames::h5Tag, [DOMHTMLHeadingElement class]); 127 addElementClass(HTMLNames::h6Tag, [DOMHTMLHeadingElement class]); 128 addElementClass(HTMLNames::headTag, [DOMHTMLHeadElement class]); 129 addElementClass(HTMLNames::hrTag, [DOMHTMLHRElement class]); 130 addElementClass(HTMLNames::htmlTag, [DOMHTMLHtmlElement class]); 131 addElementClass(HTMLNames::iframeTag, [DOMHTMLIFrameElement class]); 132 addElementClass(HTMLNames::imgTag, [DOMHTMLImageElement class]); 133 addElementClass(HTMLNames::inputTag, [DOMHTMLInputElement class]); 134 addElementClass(HTMLNames::insTag, [DOMHTMLModElement class]); 135 addElementClass(HTMLNames::labelTag, [DOMHTMLLabelElement class]); 136 addElementClass(HTMLNames::legendTag, [DOMHTMLLegendElement class]); 137 addElementClass(HTMLNames::liTag, [DOMHTMLLIElement class]); 138 addElementClass(HTMLNames::linkTag, [DOMHTMLLinkElement class]); 139 addElementClass(HTMLNames::listingTag, [DOMHTMLPreElement class]); 140 addElementClass(HTMLNames::mapTag, [DOMHTMLMapElement class]); 141 addElementClass(HTMLNames::marqueeTag, [DOMHTMLMarqueeElement class]); 142 addElementClass(HTMLNames::menuTag, [DOMHTMLMenuElement class]); 143 addElementClass(HTMLNames::metaTag, [DOMHTMLMetaElement class]); 144 addElementClass(HTMLNames::objectTag, [DOMHTMLObjectElement class]); 145 addElementClass(HTMLNames::olTag, [DOMHTMLOListElement class]); 146 addElementClass(HTMLNames::optgroupTag, [DOMHTMLOptGroupElement class]); 147 addElementClass(HTMLNames::optionTag, [DOMHTMLOptionElement class]); 148 addElementClass(HTMLNames::pTag, [DOMHTMLParagraphElement class]); 149 addElementClass(HTMLNames::paramTag, [DOMHTMLParamElement class]); 150 addElementClass(HTMLNames::preTag, [DOMHTMLPreElement class]); 151 addElementClass(HTMLNames::qTag, [DOMHTMLQuoteElement class]); 152 addElementClass(HTMLNames::scriptTag, [DOMHTMLScriptElement class]); 153 addElementClass(HTMLNames::selectTag, [DOMHTMLSelectElement class]); 154 addElementClass(HTMLNames::styleTag, [DOMHTMLStyleElement class]); 155 addElementClass(HTMLNames::tableTag, [DOMHTMLTableElement class]); 156 addElementClass(HTMLNames::tbodyTag, [DOMHTMLTableSectionElement class]); 157 addElementClass(HTMLNames::tdTag, [DOMHTMLTableCellElement class]); 158 addElementClass(HTMLNames::textareaTag, [DOMHTMLTextAreaElement class]); 159 addElementClass(HTMLNames::tfootTag, [DOMHTMLTableSectionElement class]); 160 addElementClass(HTMLNames::thTag, [DOMHTMLTableCellElement class]); 161 addElementClass(HTMLNames::theadTag, [DOMHTMLTableSectionElement class]); 162 addElementClass(HTMLNames::titleTag, [DOMHTMLTitleElement class]); 163 addElementClass(HTMLNames::trTag, [DOMHTMLTableRowElement class]); 164 addElementClass(HTMLNames::ulTag, [DOMHTMLUListElement class]); 165 addElementClass(HTMLNames::xmpTag, [DOMHTMLPreElement class]); 166} 167 168static Class lookupElementClass(const QualifiedName& tag) 169{ 170 // Do a special lookup to ignore element prefixes 171 if (tag.hasPrefix()) 172 return elementClassMap->get(QualifiedName(nullAtom, tag.localName(), tag.namespaceURI()).impl()); 173 174 return elementClassMap->get(tag.impl()); 175} 176 177static Class elementClass(const QualifiedName& tag, Class defaultClass) 178{ 179 if (!elementClassMap) 180 createElementClassMap(); 181 Class objcClass = lookupElementClass(tag); 182 if (!objcClass) 183 objcClass = defaultClass; 184 return objcClass; 185} 186 187static NSArray *kit(const Vector<IntRect>& rects) 188{ 189 size_t size = rects.size(); 190 NSMutableArray *array = [NSMutableArray arrayWithCapacity:size]; 191 for (size_t i = 0; i < size; ++i) 192 [array addObject:[NSValue valueWithRect:rects[i]]]; 193 return array; 194} 195 196#if PLATFORM(IOS) 197static WKQuad wkQuadFromFloatQuad(const FloatQuad& inQuad) 198{ 199 WKQuad theQuad; 200 theQuad.p1 = inQuad.p1(); 201 theQuad.p2 = inQuad.p2(); 202 theQuad.p3 = inQuad.p3(); 203 theQuad.p4 = inQuad.p4(); 204 205 return theQuad; 206} 207 208static NSArray *kit(const Vector<FloatQuad>& quads) 209{ 210 size_t size = quads.size(); 211 NSMutableArray *array = [NSMutableArray arrayWithCapacity:size]; 212 for (size_t i = 0; i < size; ++i) { 213 WKQuadObject* quadObject = [[WKQuadObject alloc] initWithQuad:wkQuadFromFloatQuad(quads[i])]; 214 [array addObject:quadObject]; 215 [quadObject release]; 216 } 217 return array; 218} 219 220static inline float min4(float a, float b, float c, float d) 221{ 222 return std::min(std::min(a, b), std::min(c, d)); 223} 224 225static inline float max4(float a, float b, float c, float d) 226{ 227 return std::max(std::max(a, b), std::max(c, d)); 228} 229 230static inline WKQuad emptyQuad() 231{ 232 WKQuad zeroQuad = { CGPointZero, CGPointZero, CGPointZero, CGPointZero }; 233 return zeroQuad; 234} 235#endif 236 237} // namespace WebCore 238 239#if PLATFORM(IOS) 240@implementation WKQuadObject 241 242- (id)initWithQuad:(WKQuad)quad 243{ 244 if ((self = [super init])) 245 { 246 _quad = quad; 247 } 248 return self; 249} 250 251- (WKQuad)quad 252{ 253 return _quad; 254} 255 256- (CGRect)boundingBox 257{ 258 float left = WebCore::min4(_quad.p1.x, _quad.p2.x, _quad.p3.x, _quad.p4.x); 259 float top = WebCore::min4(_quad.p1.y, _quad.p2.y, _quad.p3.y, _quad.p4.y); 260 261 float right = WebCore::max4(_quad.p1.x, _quad.p2.x, _quad.p3.x, _quad.p4.x); 262 float bottom = WebCore::max4(_quad.p1.y, _quad.p2.y, _quad.p3.y, _quad.p4.y); 263 264 return CGRectMake(left, top, right - left, bottom - top); 265} 266 267@end 268#endif 269 270@implementation DOMNode (WebCoreInternal) 271 272#pragma clang diagnostic push 273#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation" 274 275- (NSString *)description 276{ 277 if (!_internal) 278 return [NSString stringWithFormat:@"<%@: null>", [[self class] description]]; 279 280 NSString *value = [self nodeValue]; 281 if (value) 282 return [NSString stringWithFormat:@"<%@ [%@]: %p '%@'>", 283 [[self class] description], [self nodeName], _internal, value]; 284 285 return [NSString stringWithFormat:@"<%@ [%@]: %p>", [[self class] description], [self nodeName], _internal]; 286} 287 288#pragma clang diagnostic pop 289 290- (JSC::Bindings::RootObject*)_rootObject 291{ 292 WebCore::Frame* frame = core(self)->document().frame(); 293 if (!frame) 294 return 0; 295 return frame->script().bindingRootObject(); 296} 297 298@end 299 300Class kitClass(WebCore::Node* impl) 301{ 302 switch (impl->nodeType()) { 303 case WebCore::Node::ELEMENT_NODE: 304 if (impl->isHTMLElement()) 305 return WebCore::elementClass(toHTMLElement(impl)->tagQName(), [DOMHTMLElement class]); 306 return [DOMElement class]; 307 case WebCore::Node::ATTRIBUTE_NODE: 308 return [DOMAttr class]; 309 case WebCore::Node::TEXT_NODE: 310 return [DOMText class]; 311 case WebCore::Node::CDATA_SECTION_NODE: 312 return [DOMCDATASection class]; 313 case WebCore::Node::ENTITY_REFERENCE_NODE: 314 return [DOMEntityReference class]; 315 case WebCore::Node::ENTITY_NODE: 316 return [DOMEntity class]; 317 case WebCore::Node::PROCESSING_INSTRUCTION_NODE: 318 return [DOMProcessingInstruction class]; 319 case WebCore::Node::COMMENT_NODE: 320 return [DOMComment class]; 321 case WebCore::Node::DOCUMENT_NODE: 322 if (static_cast<WebCore::Document*>(impl)->isHTMLDocument()) 323 return [DOMHTMLDocument class]; 324 return [DOMDocument class]; 325 case WebCore::Node::DOCUMENT_TYPE_NODE: 326 return [DOMDocumentType class]; 327 case WebCore::Node::DOCUMENT_FRAGMENT_NODE: 328 return [DOMDocumentFragment class]; 329 case WebCore::Node::NOTATION_NODE: 330 return [DOMNotation class]; 331 case WebCore::Node::XPATH_NAMESPACE_NODE: 332 // FIXME: Create an XPath objective C wrapper 333 // See http://bugs.webkit.org/show_bug.cgi?id=8755 334 return nil; 335 } 336 ASSERT_NOT_REACHED(); 337 return nil; 338} 339 340id <DOMEventTarget> kit(WebCore::EventTarget* eventTarget) 341{ 342 if (!eventTarget) 343 return nil; 344 345 if (WebCore::Node* node = eventTarget->toNode()) 346 return kit(node); 347 348 // We don't have an ObjC binding for XMLHttpRequest. 349 350 return nil; 351} 352 353@implementation DOMNode (DOMNodeExtensions) 354 355#if PLATFORM(IOS) 356- (CGRect)boundingBox 357#else 358- (NSRect)boundingBox 359#endif 360{ 361 // FIXME: Could we move this function to WebCore::Node and autogenerate? 362 core(self)->document().updateLayoutIgnorePendingStylesheets(); 363 WebCore::RenderObject* renderer = core(self)->renderer(); 364 if (!renderer) 365#if PLATFORM(IOS) 366 return CGRectZero; 367#else 368 return NSZeroRect; 369#endif 370 return renderer->absoluteBoundingBoxRect(); 371} 372 373- (NSArray *)lineBoxRects 374{ 375 return [self textRects]; 376} 377 378#if PLATFORM(IOS) 379// quad in page coordinates, taking transforms into account. c.f. - (NSRect)boundingBox; 380- (WKQuad)absoluteQuad 381{ 382 return [self absoluteQuadAndInsideFixedPosition:0]; 383} 384 385- (WKQuad)absoluteQuadAndInsideFixedPosition:(BOOL *)insideFixed 386{ 387 core(self)->document().updateLayoutIgnorePendingStylesheets(); 388 WebCore::RenderObject *renderer = core(self)->renderer(); 389 if (renderer) { 390 Vector<FloatQuad> quads; 391 bool wasFixed = false; 392 renderer->absoluteQuads(quads, &wasFixed); 393 if (insideFixed) 394 *insideFixed = wasFixed; 395 396 if (quads.size() == 0) 397 return WebCore::emptyQuad(); 398 399 if (quads.size() == 1) 400 return wkQuadFromFloatQuad(quads[0]); 401 402 FloatRect boundingRect = quads[0].boundingBox(); 403 for (size_t i = 1; i < quads.size(); ++i) 404 boundingRect.unite(quads[i].boundingBox()); 405 406 return wkQuadFromFloatQuad(boundingRect); 407 } 408 409 return WebCore::emptyQuad(); 410} 411 412// this method is like - (CGRect)boundingBox, but it accounts for for transforms 413- (CGRect)boundingBoxUsingTransforms 414{ 415 core(self)->document().updateLayoutIgnorePendingStylesheets(); 416 WebCore::RenderObject* renderer = core(self)->renderer(); 417 if (!renderer) 418 return CGRectZero; 419 return renderer->absoluteBoundingBoxRect(true); 420} 421 422// returns array of WKQuadObject 423- (NSArray *)lineBoxQuads 424{ 425 core(self)->document().updateLayoutIgnorePendingStylesheets(); 426 WebCore::RenderObject *renderer = core(self)->renderer(); 427 if (renderer) { 428 Vector<WebCore::FloatQuad> quads; 429 renderer->absoluteQuads(quads); 430 return kit(quads); 431 } 432 return nil; 433} 434 435- (Element *)_linkElement 436{ 437 WebCore::Node* node = core(self); 438 439 while (node) { 440 if (node->isLink()) 441 return static_cast<WebCore::Element*>(node); 442 node = node->parentNode(); 443 } 444 445 return 0; 446} 447 448- (NSURL *)hrefURL 449{ 450 Element *link= [self _linkElement]; 451 if (link) 452 return link->document().completeURL(stripLeadingAndTrailingHTMLSpaces(link->getAttribute(HTMLNames::hrefAttr))); 453 454 return nil; 455} 456 457- (NSString *)hrefTarget 458{ 459 Element *target = [self _linkElement]; 460 461 if(target) return target->getAttribute(HTMLNames::targetAttr); 462 463 return nil; 464} 465 466- (CGRect)hrefFrame 467{ 468 RenderObject *renderer = [self _linkElement]->renderer(); 469 if (renderer) 470 return renderer->absoluteBoundingBoxRect(); 471 return CGRectZero; 472} 473 474- (NSString *)hrefLabel 475{ 476 Element *link= [self _linkElement]; 477 478 if (!link) return nil; 479 480 return link->textContent(); 481} 482 483- (NSString *)hrefTitle 484{ 485 Element *link= [self _linkElement]; 486 487 if (!link) return nil; 488 489 return link->document().displayStringModifiedByEncoding(static_cast<HTMLElement *>(link)->title()); 490} 491 492- (CGRect)boundingFrame 493{ 494 return [self boundingBox]; 495} 496 497- (WKQuad)innerFrameQuad // takes transforms into account 498{ 499 core(self)->document().updateLayoutIgnorePendingStylesheets(); 500 RenderObject* renderer = core(self)->renderer(); 501 if (!renderer) 502 return emptyQuad(); 503 504 RenderStyle& style = renderer->style(); 505 IntRect boundingBox = renderer->absoluteBoundingBoxRect(true /* use transforms*/); 506 507 boundingBox.move(style.borderLeftWidth(), style.borderTopWidth()); 508 boundingBox.setWidth(boundingBox.width() - style.borderLeftWidth() - style.borderRightWidth()); 509 boundingBox.setHeight(boundingBox.height() - style.borderBottomWidth() - style.borderTopWidth()); 510 511 // FIXME: This function advertises returning a quad, but it actually returns a bounding box (so there is no rotation, for instance). 512 return wkQuadFromFloatQuad(FloatQuad(boundingBox)); 513} 514 515- (float)computedFontSize 516{ 517 WebCore::Node *node = core(self); 518 RenderStyle *style = node->renderStyle(); 519 if (!style) 520 return 0.0f; 521 return style->fontDescription().computedSize(); 522} 523 524- (DOMNode *)nextFocusNode 525{ 526 Page *page = core(self)->document().page(); 527 if (!page) 528 return nil; 529 530 RefPtr<KeyboardEvent> key = KeyboardEvent::create(); 531 return kit(page->focusController().nextFocusableElement(FocusNavigationScope::focusNavigationScopeOf(&core(self)->document()), core(self), key.get())); 532} 533 534- (DOMNode *)previousFocusNode 535{ 536 Page *page = core(self)->document().page(); 537 if (!page) 538 return nil; 539 540 RefPtr<KeyboardEvent> key = KeyboardEvent::create(); 541 return kit(page->focusController().previousFocusableElement(FocusNavigationScope::focusNavigationScopeOf(&core(self)->document()), core(self), key.get())); 542} 543 544#endif // PLATFORM(IOS) 545 546@end 547 548@implementation DOMNode (DOMNodeExtensionsPendingPublic) 549 550#if !PLATFORM(IOS) 551- (NSImage *)renderedImage 552{ 553 // FIXME: Could we move this function to WebCore::Node and autogenerate? 554 WebCore::Node* node = core(self); 555 WebCore::Frame* frame = node->document().frame(); 556 if (!frame) 557 return nil; 558 return createDragImageForNode(*frame, *node).autorelease(); 559} 560#endif 561 562- (NSArray *)textRects 563{ 564 core(self)->document().updateLayoutIgnorePendingStylesheets(); 565 if (!core(self)->renderer()) 566 return nil; 567 Vector<WebCore::IntRect> rects; 568 core(self)->textRects(rects); 569 return kit(rects); 570} 571 572@end 573 574@implementation DOMNode (WebPrivate) 575 576+ (id)_nodeFromJSWrapper:(JSObjectRef)jsWrapper 577{ 578 JSObject* object = toJS(jsWrapper); 579 580 if (!object->inherits(JSNode::info())) 581 return nil; 582 583 WebCore::Node& node = jsCast<JSNode*>(object)->impl(); 584 return kit(&node); 585} 586 587@end 588 589@implementation DOMRange (DOMRangeExtensions) 590 591#if PLATFORM(IOS) 592- (CGRect)boundingBox 593#else 594- (NSRect)boundingBox 595#endif 596{ 597 // FIXME: The call to updateLayoutIgnorePendingStylesheets should be moved into WebCore::Range. 598 core(self)->ownerDocument().updateLayoutIgnorePendingStylesheets(); 599 return core(self)->boundingBox(); 600} 601 602#if !PLATFORM(IOS) 603- (NSImage *)renderedImageForcingBlackText:(BOOL)forceBlackText 604#else 605- (CGImageRef)renderedImageForcingBlackText:(BOOL)forceBlackText 606#endif 607{ 608 WebCore::Range* range = core(self); 609 WebCore::Frame* frame = range->ownerDocument().frame(); 610 if (!frame) 611 return nil; 612 613 RetainPtr<NSImage> renderedImage = createDragImageForRange(*frame, *range, forceBlackText); 614 615 IntSize size([renderedImage size]); 616 size.scale(1 / frame->page()->deviceScaleFactor()); 617 [renderedImage setSize:size]; 618 619 return renderedImage.autorelease(); 620} 621 622- (NSArray *)textRects 623{ 624 // FIXME: The call to updateLayoutIgnorePendingStylesheets should be moved into WebCore::Range. 625 Vector<WebCore::IntRect> rects; 626 core(self)->ownerDocument().updateLayoutIgnorePendingStylesheets(); 627 core(self)->textRects(rects); 628 return kit(rects); 629} 630 631- (NSArray *)lineBoxRects 632{ 633 // FIXME: Remove this once all clients stop using it and we drop Leopard support. 634 return [self textRects]; 635} 636 637@end 638 639//------------------------------------------------------------------------------------------ 640// DOMElement 641 642@implementation DOMElement (DOMElementAppKitExtensions) 643 644#if !PLATFORM(IOS) 645- (NSImage*)image 646{ 647 // FIXME: Could we move this function to WebCore::Node and autogenerate? 648 WebCore::RenderObject* renderer = core(self)->renderer(); 649 if (!renderer || !renderer->isRenderImage()) 650 return nil; 651 WebCore::CachedImage* cachedImage = toRenderImage(renderer)->cachedImage(); 652 if (!cachedImage || cachedImage->errorOccurred()) 653 return nil; 654 return cachedImage->imageForRenderer(toRenderImage(renderer))->getNSImage(); 655} 656#endif 657 658@end 659 660@implementation DOMElement (WebPrivate) 661 662#if !PLATFORM(IOS) 663- (NSFont *)_font 664{ 665 // FIXME: Could we move this function to WebCore::Element and autogenerate? 666 auto renderer = core(self)->renderer(); 667 if (!renderer) 668 return nil; 669 return renderer->style().font().primaryFont()->getNSFont(); 670} 671#else 672- (CTFontRef)_font 673{ 674 RenderObject* renderer = core(self)->renderer(); 675 if (!renderer) 676 return nil; 677 return renderer->style().font().primaryFont()->getCTFont(); 678} 679#endif 680 681#if !PLATFORM(IOS) 682- (NSData *)_imageTIFFRepresentation 683{ 684 // FIXME: Could we move this function to WebCore::Element and autogenerate? 685 auto renderer = core(self)->renderer(); 686 if (!renderer || !renderer->isRenderImage()) 687 return nil; 688 WebCore::CachedImage* cachedImage = toRenderImage(renderer)->cachedImage(); 689 if (!cachedImage || cachedImage->errorOccurred()) 690 return nil; 691 return (NSData *)cachedImage->imageForRenderer(renderer)->getTIFFRepresentation(); 692} 693#endif 694 695- (NSURL *)_getURLAttribute:(NSString *)name 696{ 697 // FIXME: Could we move this function to WebCore::Element and autogenerate? 698 ASSERT(name); 699 WebCore::Element* element = core(self); 700 ASSERT(element); 701 return element->document().completeURL(stripLeadingAndTrailingHTMLSpaces(element->getAttribute(name))); 702} 703 704- (BOOL)isFocused 705{ 706 // FIXME: Could we move this function to WebCore::Element and autogenerate? 707 WebCore::Element* element = core(self); 708 return element->document().focusedElement() == element; 709} 710 711@end 712 713#if PLATFORM(IOS) 714@implementation DOMHTMLLinkElement (WebPrivate) 715- (BOOL)_mediaQueryMatchesForOrientation:(int)orientation 716{ 717 Document& document = static_cast<HTMLLinkElement*>(core(self))->document(); 718 FrameView* frameView = document.frame() ? document.frame()->view() : 0; 719 if (!frameView) 720 return false; 721 int layoutWidth = frameView->layoutWidth(); 722 int layoutHeight = frameView->layoutHeight(); 723 IntSize savedFixedLayoutSize = frameView->fixedLayoutSize(); 724 bool savedUseFixedLayout = frameView->useFixedLayout(); 725 if ((orientation == WebMediaQueryOrientationPortrait && layoutWidth > layoutHeight) || 726 (orientation == WebMediaQueryOrientationLandscape && layoutWidth < layoutHeight)) { 727 // temporarily swap the orientation for the evaluation 728 frameView->setFixedLayoutSize(IntSize(layoutHeight, layoutWidth)); 729 frameView->setUseFixedLayout(true); 730 } 731 732 bool result = [self _mediaQueryMatches]; 733 734 frameView->setFixedLayoutSize(savedFixedLayoutSize); 735 frameView->setUseFixedLayout(savedUseFixedLayout); 736 737 return result; 738} 739 740- (BOOL)_mediaQueryMatches 741{ 742 HTMLLinkElement* link = static_cast<HTMLLinkElement*>(core(self)); 743 String media = link->getAttribute(HTMLNames::mediaAttr); 744 if (media.isEmpty()) 745 return true; 746 Document& document = link->document(); 747 748 RefPtr<MediaQuerySet> mediaQuerySet = MediaQuerySet::createAllowingDescriptionSyntax(media); 749 MediaQueryEvaluator screenEval("screen", document.frame(), document.renderView() ? &document.renderView()->style() : 0); 750 751 return screenEval.eval(mediaQuerySet.get()); 752} 753@end 754#endif 755 756//------------------------------------------------------------------------------------------ 757// DOMRange 758 759@implementation DOMRange (WebPrivate) 760 761- (NSString *)description 762{ 763 if (!_internal) 764 return @"<DOMRange: null>"; 765 return [NSString stringWithFormat:@"<DOMRange: %@ %d %@ %d>", 766 [self startContainer], [self startOffset], [self endContainer], [self endOffset]]; 767} 768 769// FIXME: This should be removed as soon as all internal Apple uses of it have been replaced with 770// calls to the public method - (NSString *)text. 771- (NSString *)_text 772{ 773 return [self text]; 774} 775 776@end 777 778//------------------------------------------------------------------------------------------ 779// DOMRGBColor 780 781@implementation DOMRGBColor (WebPrivate) 782 783#if !PLATFORM(IOS) 784// FIXME: This should be removed as soon as all internal Apple uses of it have been replaced with 785// calls to the public method - (NSColor *)color. 786- (NSColor *)_color 787{ 788 return [self color]; 789} 790#endif 791 792@end 793 794 795@implementation DOMHTMLTableCellElement (WebPrivate) 796 797- (DOMHTMLTableCellElement *)_cellAbove 798{ 799 return kit(core(self)->cellAbove()); 800} 801 802@end 803 804//------------------------------------------------------------------------------------------ 805// DOMNodeFilter 806 807DOMNodeFilter *kit(WebCore::NodeFilter* impl) 808{ 809 if (!impl) 810 return nil; 811 812 if (DOMNodeFilter *wrapper = getDOMWrapper(impl)) 813 return [[wrapper retain] autorelease]; 814 815 DOMNodeFilter *wrapper = [[DOMNodeFilter alloc] _init]; 816 wrapper->_internal = reinterpret_cast<DOMObjectInternal*>(impl); 817 impl->ref(); 818 addDOMWrapper(wrapper, impl); 819 return [wrapper autorelease]; 820} 821 822WebCore::NodeFilter* core(DOMNodeFilter *wrapper) 823{ 824 return wrapper ? reinterpret_cast<WebCore::NodeFilter*>(wrapper->_internal) : 0; 825} 826 827@implementation DOMNodeFilter 828 829- (void)dealloc 830{ 831 if (_internal) 832 reinterpret_cast<WebCore::NodeFilter*>(_internal)->deref(); 833 [super dealloc]; 834} 835 836- (void)finalize 837{ 838 if (_internal) 839 reinterpret_cast<WebCore::NodeFilter*>(_internal)->deref(); 840 [super finalize]; 841} 842 843- (short)acceptNode:(DOMNode *)node 844{ 845 return core(self)->acceptNode(core(node)); 846} 847 848@end 849