Build fix for iOS
[WebKit-https.git] / Source / WebCore / bindings / objc / DOM.mm
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
73 using namespace JSC;
74 using 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
82 namespace WebCore {
83
84 typedef HashMap<const QualifiedName::QualifiedNameImpl*, Class> ObjCClassMap;
85 static ObjCClassMap* elementClassMap;
86
87 static void addElementClass(const QualifiedName& tag, Class objCClass)
88 {
89     elementClassMap->set(tag.impl(), objCClass);
90 }
91
92 static 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
168 static 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
177 static 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
187 static 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)
197 static 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
208 static 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
220 static 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
225 static 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
230 static 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
300 Class 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
340 id <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     // iOS uses CGImageRef for drag images, which doesn't support separate logical/physical sizes.
614 #if PLATFORM(MAC)
615     RetainPtr<NSImage> renderedImage = createDragImageForRange(*frame, *range, forceBlackText);
616
617     IntSize size([renderedImage size]);
618     size.scale(1 / frame->page()->deviceScaleFactor());
619     [renderedImage setSize:size];
620
621     return renderedImage.autorelease();
622 #else
623     return createDragImageForRange(*frame, *range, forceBlackText).autorelease();
624 #endif
625 }
626
627 - (NSArray *)textRects
628 {
629     // FIXME: The call to updateLayoutIgnorePendingStylesheets should be moved into WebCore::Range.
630     Vector<WebCore::IntRect> rects;
631     core(self)->ownerDocument().updateLayoutIgnorePendingStylesheets();
632     core(self)->textRects(rects);
633     return kit(rects);
634 }
635
636 - (NSArray *)lineBoxRects
637 {
638     // FIXME: Remove this once all clients stop using it and we drop Leopard support.
639     return [self textRects];
640 }
641
642 @end
643
644 //------------------------------------------------------------------------------------------
645 // DOMElement
646
647 @implementation DOMElement (DOMElementAppKitExtensions)
648
649 #if !PLATFORM(IOS)
650 - (NSImage*)image
651 {
652     // FIXME: Could we move this function to WebCore::Node and autogenerate?
653     WebCore::RenderObject* renderer = core(self)->renderer();
654     if (!renderer || !renderer->isRenderImage())
655         return nil;
656     WebCore::CachedImage* cachedImage = toRenderImage(renderer)->cachedImage();
657     if (!cachedImage || cachedImage->errorOccurred())
658         return nil;
659     return cachedImage->imageForRenderer(toRenderImage(renderer))->getNSImage();
660 }
661 #endif
662
663 @end
664
665 @implementation DOMElement (WebPrivate)
666
667 #if !PLATFORM(IOS)
668 - (NSFont *)_font
669 {
670     // FIXME: Could we move this function to WebCore::Element and autogenerate?
671     auto renderer = core(self)->renderer();
672     if (!renderer)
673         return nil;
674     return renderer->style().font().primaryFont()->getNSFont();
675 }
676 #else
677 - (CTFontRef)_font
678 {
679     RenderObject* renderer = core(self)->renderer();
680     if (!renderer)
681         return nil;
682     return renderer->style().font().primaryFont()->getCTFont();
683 }
684 #endif
685
686 #if !PLATFORM(IOS)
687 - (NSData *)_imageTIFFRepresentation
688 {
689     // FIXME: Could we move this function to WebCore::Element and autogenerate?
690     auto renderer = core(self)->renderer();
691     if (!renderer || !renderer->isRenderImage())
692         return nil;
693     WebCore::CachedImage* cachedImage = toRenderImage(renderer)->cachedImage();
694     if (!cachedImage || cachedImage->errorOccurred())
695         return nil;
696     return (NSData *)cachedImage->imageForRenderer(renderer)->getTIFFRepresentation();
697 }
698 #endif
699
700 - (NSURL *)_getURLAttribute:(NSString *)name
701 {
702     // FIXME: Could we move this function to WebCore::Element and autogenerate?
703     ASSERT(name);
704     WebCore::Element* element = core(self);
705     ASSERT(element);
706     return element->document().completeURL(stripLeadingAndTrailingHTMLSpaces(element->getAttribute(name)));
707 }
708
709 - (BOOL)isFocused
710 {
711     // FIXME: Could we move this function to WebCore::Element and autogenerate?
712     WebCore::Element* element = core(self);
713     return element->document().focusedElement() == element;
714 }
715
716 @end
717
718 #if PLATFORM(IOS)
719 @implementation DOMHTMLLinkElement (WebPrivate)
720 - (BOOL)_mediaQueryMatchesForOrientation:(int)orientation
721 {
722     Document& document = static_cast<HTMLLinkElement*>(core(self))->document();
723     FrameView* frameView = document.frame() ? document.frame()->view() : 0;
724     if (!frameView)
725         return false;
726     int layoutWidth = frameView->layoutWidth();
727     int layoutHeight = frameView->layoutHeight();
728     IntSize savedFixedLayoutSize = frameView->fixedLayoutSize();
729     bool savedUseFixedLayout = frameView->useFixedLayout();
730     if ((orientation == WebMediaQueryOrientationPortrait && layoutWidth > layoutHeight) ||
731         (orientation == WebMediaQueryOrientationLandscape && layoutWidth < layoutHeight)) {
732         // temporarily swap the orientation for the evaluation
733         frameView->setFixedLayoutSize(IntSize(layoutHeight, layoutWidth));
734         frameView->setUseFixedLayout(true);
735     }
736         
737     bool result = [self _mediaQueryMatches];
738
739     frameView->setFixedLayoutSize(savedFixedLayoutSize);
740     frameView->setUseFixedLayout(savedUseFixedLayout);
741
742     return result;
743 }
744
745 - (BOOL)_mediaQueryMatches
746 {
747     HTMLLinkElement* link = static_cast<HTMLLinkElement*>(core(self));
748     String media = link->getAttribute(HTMLNames::mediaAttr);
749     if (media.isEmpty())
750         return true;
751     Document& document = link->document();
752
753     RefPtr<MediaQuerySet> mediaQuerySet = MediaQuerySet::createAllowingDescriptionSyntax(media);
754     MediaQueryEvaluator screenEval("screen", document.frame(), document.renderView() ? &document.renderView()->style() : 0);
755
756     return screenEval.eval(mediaQuerySet.get());
757 }
758 @end
759 #endif
760
761 //------------------------------------------------------------------------------------------
762 // DOMRange
763
764 @implementation DOMRange (WebPrivate)
765
766 - (NSString *)description
767 {
768     if (!_internal)
769         return @"<DOMRange: null>";
770     return [NSString stringWithFormat:@"<DOMRange: %@ %d %@ %d>",
771                [self startContainer], [self startOffset], [self endContainer], [self endOffset]];
772 }
773
774 // FIXME: This should be removed as soon as all internal Apple uses of it have been replaced with
775 // calls to the public method - (NSString *)text.
776 - (NSString *)_text
777 {
778     return [self text];
779 }
780
781 @end
782
783 //------------------------------------------------------------------------------------------
784 // DOMRGBColor
785
786 @implementation DOMRGBColor (WebPrivate)
787
788 #if !PLATFORM(IOS)
789 // FIXME: This should be removed as soon as all internal Apple uses of it have been replaced with
790 // calls to the public method - (NSColor *)color.
791 - (NSColor *)_color
792 {
793     return [self color];
794 }
795 #endif
796
797 @end
798
799
800 @implementation DOMHTMLTableCellElement (WebPrivate)
801
802 - (DOMHTMLTableCellElement *)_cellAbove
803 {
804     return kit(core(self)->cellAbove());
805 }
806
807 @end
808
809 //------------------------------------------------------------------------------------------
810 // DOMNodeFilter
811
812 DOMNodeFilter *kit(WebCore::NodeFilter* impl)
813 {
814     if (!impl)
815         return nil;
816     
817     if (DOMNodeFilter *wrapper = getDOMWrapper(impl))
818         return [[wrapper retain] autorelease];
819     
820     DOMNodeFilter *wrapper = [[DOMNodeFilter alloc] _init];
821     wrapper->_internal = reinterpret_cast<DOMObjectInternal*>(impl);
822     impl->ref();
823     addDOMWrapper(wrapper, impl);
824     return [wrapper autorelease];
825 }
826
827 WebCore::NodeFilter* core(DOMNodeFilter *wrapper)
828 {
829     return wrapper ? reinterpret_cast<WebCore::NodeFilter*>(wrapper->_internal) : 0;
830 }
831
832 @implementation DOMNodeFilter
833
834 - (void)dealloc
835 {
836     if (_internal)
837         reinterpret_cast<WebCore::NodeFilter*>(_internal)->deref();
838     [super dealloc];
839 }
840
841 - (void)finalize
842 {
843     if (_internal)
844         reinterpret_cast<WebCore::NodeFilter*>(_internal)->deref();
845     [super finalize];
846 }
847
848 - (short)acceptNode:(DOMNode *)node
849 {
850     return core(self)->acceptNode(core(node));
851 }
852
853 @end