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