Reviewed by Darin.
[WebKit-https.git] / WebCore / khtml / html / html_imageimpl.cpp
1 /**
2  * This file is part of the DOM implementation for KDE.
3  *
4  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
5  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
6  * Copyright (C) 2004 Apple Computer, Inc.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public License
19  * along with this library; see the file COPYING.LIB.  If not, write to
20  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 #include "html/html_imageimpl.h"
25 #include "html/html_formimpl.h"
26 #include "html/html_documentimpl.h"
27
28 #include "misc/htmlhashes.h"
29 #include "khtmlview.h"
30 #include "khtml_part.h"
31
32 #include <kstringhandler.h>
33 #include <kglobal.h>
34 #include <kdebug.h>
35
36 #include "rendering/render_image.h"
37 #include "rendering/render_flow.h"
38 #include "css/cssstyleselector.h"
39 #include "css/cssproperties.h"
40 #include "css/cssvalues.h"
41 #include "css/csshelper.h"
42 #include "xml/dom2_eventsimpl.h"
43
44 #include <qstring.h>
45 #include <qpoint.h>
46 #include <qregion.h>
47 #include <qptrstack.h>
48 #include <qimage.h>
49 #include <qpointarray.h>
50
51 using namespace DOM;
52 using namespace khtml;
53
54 //#define INSTRUMENT_LAYOUT_SCHEDULING 1
55
56 HTMLImageLoader::HTMLImageLoader(ElementImpl* elt)
57 :m_element(elt), m_image(0), m_firedLoad(true), m_imageComplete(true)
58 {
59 }
60
61 HTMLImageLoader::~HTMLImageLoader()
62 {
63     if (m_image)
64         m_image->deref(this);
65     if (m_element->getDocument())
66         m_element->getDocument()->removeImage(this);
67 }
68
69 void HTMLImageLoader::updateFromElement()
70 {
71     // If we're not making renderers for the page, then don't load images.  We don't want to slow
72     // down the raw HTML parsing case by loading images we don't intend to display.
73     DocumentImpl* document = element()->getDocument();
74     if (!document || !document->renderer())
75         return;
76
77     AtomicString attr;
78     if (element()->id() == ID_OBJECT)
79         attr = element()->getAttribute(ATTR_DATA);
80     else
81         attr = element()->getAttribute(ATTR_SRC);
82     
83     // Treat a lack of src or empty string for src as no image at all.
84     CachedImage* newImage = 0;
85     if (!attr.isEmpty())
86         newImage = element()->getDocument()->docLoader()->requestImage(khtml::parseURL(attr));
87
88     if (newImage != m_image) {
89         m_firedLoad = false;
90         m_imageComplete = false;
91         CachedImage* oldImage = m_image;
92         m_image = newImage;
93         if (m_image)
94             m_image->ref(this);
95         if (oldImage)
96             oldImage->deref(this);
97     }
98 #if APPLE_CHANGES
99     khtml::RenderImage *renderer = static_cast<khtml::RenderImage*>(element()->renderer());
100     if (renderer)
101         renderer->resetAnimation();
102 #endif
103 }
104
105 void HTMLImageLoader::dispatchLoadEvent()
106 {
107     if (!m_firedLoad) {
108         m_firedLoad = true;
109         if (m_image->isErrorImage())
110             element()->dispatchHTMLEvent(EventImpl::ERROR_EVENT, false, false);
111         else
112             element()->dispatchHTMLEvent(EventImpl::LOAD_EVENT, false, false);
113     }
114 }
115
116 void HTMLImageLoader::notifyFinished(CachedObject* image)
117 {
118     m_imageComplete = true;
119     DocumentImpl* document = element()->getDocument();
120     if (document) {
121         document->dispatchImageLoadEventSoon(this);
122 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
123         if (!document->ownerElement())
124             printf("Image loaded at %d\n", element()->getDocument()->elapsedTime());
125 #endif
126     }
127     if (element()->renderer()) {
128         RenderImage* imageObj = static_cast<RenderImage*>(element()->renderer());
129         imageObj->setImage(m_image);
130     }
131 }
132
133 // -------------------------------------------------------------------------
134
135 HTMLImageElementImpl::HTMLImageElementImpl(DocumentPtr *doc, HTMLFormElementImpl *f)
136     : HTMLElementImpl(doc), m_imageLoader(this), ismap(false), m_form(f)
137 {
138     if (m_form)
139         m_form->registerImgElement(this);
140 }
141
142 HTMLImageElementImpl::~HTMLImageElementImpl()
143 {
144     if (m_form)
145         m_form->removeImgElement(this);
146 }
147
148 NodeImpl::Id HTMLImageElementImpl::id() const
149 {
150     return ID_IMG;
151 }
152
153 bool HTMLImageElementImpl::mapToEntry(NodeImpl::Id attr, MappedAttributeEntry& result) const
154 {
155     switch(attr)
156     {
157         case ATTR_WIDTH:
158         case ATTR_HEIGHT:
159         case ATTR_VSPACE:
160         case ATTR_HSPACE:
161         case ATTR_VALIGN:
162             result = eUniversal;
163             return false;
164         case ATTR_BORDER:
165         case ATTR_ALIGN:
166             result = eReplaced; // Shared with embeds and iframes
167             return false;
168         default:
169             break;
170     }
171
172     return HTMLElementImpl::mapToEntry(attr, result);
173 }
174
175 void HTMLImageElementImpl::parseMappedAttribute(MappedAttributeImpl *attr)
176 {
177     switch (attr->id())
178     {
179     case ATTR_ALT:
180         if (m_render) static_cast<RenderImage*>(m_render)->updateAltText();
181         break;
182     case ATTR_SRC:
183         m_imageLoader.updateFromElement();
184         break;
185     case ATTR_WIDTH:
186         addCSSLength(attr, CSS_PROP_WIDTH, attr->value());
187         break;
188     case ATTR_HEIGHT:
189         addCSSLength(attr, CSS_PROP_HEIGHT, attr->value());
190         break;
191     case ATTR_BORDER:
192         // border="noborder" -> border="0"
193         if(attr->value().toInt()) {
194             addCSSLength(attr, CSS_PROP_BORDER_WIDTH, attr->value());
195             addCSSProperty(attr, CSS_PROP_BORDER_TOP_STYLE, CSS_VAL_SOLID);
196             addCSSProperty(attr, CSS_PROP_BORDER_RIGHT_STYLE, CSS_VAL_SOLID);
197             addCSSProperty(attr, CSS_PROP_BORDER_BOTTOM_STYLE, CSS_VAL_SOLID);
198             addCSSProperty(attr, CSS_PROP_BORDER_LEFT_STYLE, CSS_VAL_SOLID);
199         }
200         break;
201     case ATTR_VSPACE:
202         addCSSLength(attr, CSS_PROP_MARGIN_TOP, attr->value());
203         addCSSLength(attr, CSS_PROP_MARGIN_BOTTOM, attr->value());
204         break;
205     case ATTR_HSPACE:
206         addCSSLength(attr, CSS_PROP_MARGIN_LEFT, attr->value());
207         addCSSLength(attr, CSS_PROP_MARGIN_RIGHT, attr->value());
208         break;
209     case ATTR_ALIGN:
210         addHTMLAlignment(attr);
211         break;
212     case ATTR_VALIGN:
213         addCSSProperty(attr, CSS_PROP_VERTICAL_ALIGN, attr->value());
214         break;
215     case ATTR_USEMAP:
216         if ( attr->value().domString()[0] == '#' )
217             usemap = attr->value();
218         else {
219             QString url = getDocument()->completeURL( khtml::parseURL( attr->value() ).string() );
220             // ### we remove the part before the anchor and hope
221             // the map is on the same html page....
222             usemap = url;
223         }
224         m_isLink = !attr->isNull();
225     case ATTR_ISMAP:
226         ismap = true;
227         break;
228     case ATTR_ONABORT: // ### add support for this
229         setHTMLEventListener(EventImpl::ABORT_EVENT,
230             getDocument()->createHTMLEventListener(attr->value().string(), this));
231         break;
232     case ATTR_ONERROR:
233         setHTMLEventListener(EventImpl::ERROR_EVENT,
234             getDocument()->createHTMLEventListener(attr->value().string(), this));
235         break;
236     case ATTR_ONLOAD:
237         setHTMLEventListener(EventImpl::LOAD_EVENT,
238             getDocument()->createHTMLEventListener(attr->value().string(), this));
239         break;
240     case ATTR_NOSAVE:
241         break;
242 #if APPLE_CHANGES
243     case ATTR_COMPOSITE:
244         _compositeOperator = attr->value().string();
245         break;
246 #endif
247     case ATTR_NAME:
248         {
249             QString newNameAttr = attr->value().string();
250             if (attached() && getDocument()->isHTMLDocument()) {
251                 HTMLDocumentImpl *document = static_cast<HTMLDocumentImpl *>(getDocument());
252                 document->removeNamedImageOrForm(oldNameAttr);
253                 document->addNamedImageOrForm(newNameAttr);
254             }
255             oldNameAttr = newNameAttr;
256         }
257         break;
258     case ATTR_ID:
259         {
260             QString newIdAttr = attr->value().string();
261             if (attached() && getDocument()->isHTMLDocument()) {
262                 HTMLDocumentImpl *document = static_cast<HTMLDocumentImpl *>(getDocument());
263                 document->removeNamedImageOrForm(oldIdAttr);
264                 document->addNamedImageOrForm(newIdAttr);
265             }
266             oldIdAttr = newIdAttr;
267         }
268         // fall through
269     default:
270         HTMLElementImpl::parseMappedAttribute(attr);
271     }
272 }
273
274 DOMString HTMLImageElementImpl::altText() const
275 {
276     // lets figure out the alt text.. magic stuff
277     // http://www.w3.org/TR/1998/REC-html40-19980424/appendix/notes.html#altgen
278     // also heavily discussed by Hixie on bugzilla
279     DOMString alt( getAttribute( ATTR_ALT ) );
280     // fall back to title attribute
281     if ( alt.isNull() )
282         alt = getAttribute( ATTR_TITLE );
283 #if 0
284     if ( alt.isNull() ) {
285         QString p = KURL( getDocument()->completeURL( getAttribute(ATTR_SRC).string() ) ).prettyURL();
286         int pos;
287         if ( ( pos = p.findRev( '.' ) ) > 0 )
288             p.truncate( pos );
289         alt = DOMString( KStringHandler::csqueeze( p ) );
290     }
291 #endif
292
293     return alt;
294 }
295
296 RenderObject *HTMLImageElementImpl::createRenderer(RenderArena *arena, RenderStyle *style)
297 {
298      return new (arena) RenderImage(this);
299 }
300
301 void HTMLImageElementImpl::attach()
302 {
303     HTMLElementImpl::attach();
304
305     if (renderer()) {
306         RenderImage* imageObj = static_cast<RenderImage*>(renderer());
307         imageObj->setImage(m_imageLoader.image());
308     }
309
310     if (getDocument()->isHTMLDocument()) {
311         HTMLDocumentImpl *document = static_cast<HTMLDocumentImpl *>(getDocument());
312         document->addNamedImageOrForm(oldIdAttr);
313         document->addNamedImageOrForm(oldNameAttr);
314     }
315 }
316
317 void HTMLImageElementImpl::detach()
318 {
319     if (getDocument()->isHTMLDocument()) {
320         HTMLDocumentImpl *document = static_cast<HTMLDocumentImpl *>(getDocument());
321         document->removeNamedImageOrForm(oldIdAttr);
322         document->removeNamedImageOrForm(oldNameAttr);
323     }
324
325     HTMLElementImpl::detach();
326 }
327
328 long HTMLImageElementImpl::width(bool ignorePendingStylesheets) const
329 {
330     if (!m_render) {
331         // check the attribute first for an explicit pixel value
332         DOM::DOMString attrWidth = getAttribute(ATTR_WIDTH);
333         bool ok;
334         long width = attrWidth.string().toLong(&ok);
335         if (ok) {
336           return width;
337         }
338     }
339
340     DOM::DocumentImpl* docimpl = getDocument();
341     if (docimpl) {
342         if (ignorePendingStylesheets)
343             docimpl->updateLayoutIgnorePendingStylesheets();
344         else
345             docimpl->updateLayout();
346     }
347
348     if (!m_render) {
349         return 0;
350     }
351
352     return m_render->contentWidth();
353 }
354
355 long HTMLImageElementImpl::height(bool ignorePendingStylesheets) const
356 {
357     if (!m_render) {
358         // check the attribute first for an explicit pixel value
359         DOM::DOMString attrHeight = getAttribute(ATTR_HEIGHT);
360         bool ok;
361         long height = attrHeight.string().toLong(&ok);
362         if (ok) {
363           return height;
364         }
365     }
366
367     DOM::DocumentImpl* docimpl = getDocument();
368     if (docimpl) {
369         if (ignorePendingStylesheets)
370             docimpl->updateLayoutIgnorePendingStylesheets();
371         else
372             docimpl->updateLayout();
373     }
374
375     if (!m_render) {
376         return 0;
377     }
378
379     return m_render->contentHeight();
380 }
381
382 QImage HTMLImageElementImpl::currentImage() const
383 {
384     RenderImage *r = static_cast<RenderImage*>(renderer());
385     if (r)
386         return r->pixmap().convertToImage();
387     return QImage();
388 }
389
390 bool HTMLImageElementImpl::isURLAttribute(AttributeImpl *attr) const
391 {
392     return (attr->id() == ATTR_SRC || (attr->id() == ATTR_USEMAP && attr->value().domString()[0] != '#'));
393 }
394
395 DOMString HTMLImageElementImpl::name() const
396 {
397     return getAttribute(ATTR_NAME);
398 }
399
400 void HTMLImageElementImpl::setName(const DOMString &value)
401 {
402     setAttribute(ATTR_NAME, value);
403 }
404
405 DOMString HTMLImageElementImpl::align() const
406 {
407     return getAttribute(ATTR_ALIGN);
408 }
409
410 void HTMLImageElementImpl::setAlign(const DOMString &value)
411 {
412     setAttribute(ATTR_ALIGN, value);
413 }
414
415 DOMString HTMLImageElementImpl::alt() const
416 {
417     return getAttribute(ATTR_ALT);
418 }
419
420 void HTMLImageElementImpl::setAlt(const DOMString &value)
421 {
422     setAttribute(ATTR_ALT, value);
423 }
424
425 long HTMLImageElementImpl::border() const
426 {
427     // ### return value in pixels
428     return getAttribute(ATTR_BORDER).toInt();
429 }
430
431 void HTMLImageElementImpl::setBorder(long value)
432 {
433     setAttribute(ATTR_BORDER, QString::number(value));
434 }
435
436 void HTMLImageElementImpl::setHeight(long value)
437 {
438     setAttribute(ATTR_HEIGHT, QString::number(value));
439 }
440
441 long HTMLImageElementImpl::hspace() const
442 {
443     // ### return actual value
444     return getAttribute(ATTR_HSPACE).toInt();
445 }
446
447 void HTMLImageElementImpl::setHspace(long value)
448 {
449     setAttribute(ATTR_HSPACE, QString::number(value));
450 }
451
452 bool HTMLImageElementImpl::isMap() const
453 {
454     return !getAttribute(ATTR_ISMAP).isNull();
455 }
456
457 void HTMLImageElementImpl::setIsMap(bool isMap)
458 {
459     setAttribute(ATTR_ISMAP, isMap ? "" : 0);
460 }
461
462 DOMString HTMLImageElementImpl::longDesc() const
463 {
464     return getAttribute(ATTR_LONGDESC);
465 }
466
467 void HTMLImageElementImpl::setLongDesc(const DOMString &value)
468 {
469     setAttribute(ATTR_LONGDESC, value);
470 }
471
472 DOMString HTMLImageElementImpl::src() const
473 {
474     return getDocument()->completeURL(getAttribute(ATTR_SRC));
475 }
476
477 void HTMLImageElementImpl::setSrc(const DOMString &value)
478 {
479     setAttribute(ATTR_SRC, value);
480 }
481
482 DOMString HTMLImageElementImpl::useMap() const
483 {
484     return getAttribute(ATTR_USEMAP);
485 }
486
487 void HTMLImageElementImpl::setUseMap(const DOMString &value)
488 {
489     setAttribute(ATTR_USEMAP, value);
490 }
491
492 long HTMLImageElementImpl::vspace() const
493 {
494     // ### return actual vspace
495     return getAttribute(ATTR_VSPACE).toInt();
496 }
497
498 void HTMLImageElementImpl::setVspace(long value)
499 {
500     setAttribute(ATTR_VSPACE, QString::number(value));
501 }
502
503 void HTMLImageElementImpl::setWidth(long value)
504 {
505     setAttribute(ATTR_WIDTH, QString::number(value));
506 }
507
508 long HTMLImageElementImpl::x() const
509 {
510     RenderObject *r = renderer();
511     if (!r)
512         return 0;
513     int x, y;
514     r->absolutePosition(x, y);
515     return x;
516 }
517
518 long HTMLImageElementImpl::y() const
519 {
520     RenderObject *r = renderer();
521     if (!r)
522         return 0;
523     int x, y;
524     r->absolutePosition(x, y);
525     return y;
526 }
527
528 // -------------------------------------------------------------------------
529
530 HTMLMapElementImpl::HTMLMapElementImpl(DocumentPtr *doc)
531     : HTMLElementImpl(doc)
532 {
533 }
534
535 HTMLMapElementImpl::~HTMLMapElementImpl()
536 {
537     if (getDocument())
538         getDocument()->removeImageMap(this);
539 }
540
541 NodeImpl::Id HTMLMapElementImpl::id() const
542 {
543     return ID_MAP;
544 }
545
546 bool
547 HTMLMapElementImpl::mapMouseEvent(int x_, int y_, int width_, int height_,
548                                   RenderObject::NodeInfo& info)
549 {
550     //cout << "map:mapMouseEvent " << endl;
551     //cout << x_ << " " << y_ <<" "<< width_ <<" "<< height_ << endl;
552     QPtrStack<NodeImpl> nodeStack;
553
554     NodeImpl *current = firstChild();
555     while(1)
556     {
557         if(!current)
558         {
559             if(nodeStack.isEmpty()) break;
560             current = nodeStack.pop();
561             current = current->nextSibling();
562             continue;
563         }
564         if(current->id()==ID_AREA)
565         {
566             //cout << "area found " << endl;
567             HTMLAreaElementImpl* area=static_cast<HTMLAreaElementImpl*>(current);
568             if (area->mapMouseEvent(x_,y_,width_,height_, info))
569                 return true;
570         }
571         NodeImpl *child = current->firstChild();
572         if(child)
573         {
574             nodeStack.push(current);
575             current = child;
576         }
577         else
578         {
579             current = current->nextSibling();
580         }
581     }
582
583     return false;
584 }
585
586 void HTMLMapElementImpl::parseMappedAttribute(MappedAttributeImpl *attr)
587 {
588     switch (attr->id())
589     {
590     case ATTR_ID:
591         // Must call base class so that hasID bit gets set.
592         HTMLElementImpl::parseMappedAttribute(attr);
593         if (getDocument()->htmlMode() != DocumentImpl::XHtml) break;
594         // fall through
595     case ATTR_NAME:
596         getDocument()->removeImageMap(this);
597         m_name = attr->value();
598         if (m_name.length() != 0 && m_name[0] == '#')
599             m_name.remove(0, 1);
600         getDocument()->addImageMap(this);
601         break;
602     default:
603         HTMLElementImpl::parseMappedAttribute(attr);
604     }
605 }
606
607 SharedPtr<HTMLCollectionImpl> HTMLMapElementImpl::areas()
608 {
609     return SharedPtr<HTMLCollectionImpl>(new HTMLCollectionImpl(this, HTMLCollectionImpl::MAP_AREAS));
610 }
611
612 DOMString HTMLMapElementImpl::name() const
613 {
614     return getAttribute(ATTR_NAME);
615 }
616
617 void HTMLMapElementImpl::setName(const DOMString &value)
618 {
619     setAttribute(ATTR_NAME, value);
620 }
621
622 // -------------------------------------------------------------------------
623
624 HTMLAreaElementImpl::HTMLAreaElementImpl(DocumentPtr *doc)
625     : HTMLAnchorElementImpl(doc)
626 {
627     m_coords=0;
628     m_coordsLen = 0;
629     m_shape = Unknown;
630     lasth = lastw = -1;
631 }
632
633 HTMLAreaElementImpl::~HTMLAreaElementImpl()
634 {
635     if (m_coords) delete [] m_coords;
636 }
637
638 NodeImpl::Id HTMLAreaElementImpl::id() const
639 {
640     return ID_AREA;
641 }
642
643 void HTMLAreaElementImpl::parseMappedAttribute(MappedAttributeImpl *attr)
644 {
645     switch (attr->id())
646     {
647     case ATTR_SHAPE:
648         if ( strcasecmp( attr->value(), "default" ) == 0 )
649             m_shape = Default;
650         else if ( strcasecmp( attr->value(), "circle" ) == 0 )
651             m_shape = Circle;
652         else if ( strcasecmp( attr->value(), "poly" ) == 0 )
653             m_shape = Poly;
654         else if ( strcasecmp( attr->value(), "rect" ) == 0 )
655             m_shape = Rect;
656         break;
657     case ATTR_COORDS:
658         if (m_coords) delete [] m_coords;
659         m_coords = attr->value().toLengthArray(m_coordsLen);
660         break;
661     case ATTR_TARGET:
662         m_hasTarget = !attr->isNull();
663         break;
664     case ATTR_ALT:
665         break;
666     case ATTR_ACCESSKEY:
667         break;
668     default:
669         HTMLAnchorElementImpl::parseMappedAttribute(attr);
670     }
671 }
672
673 bool HTMLAreaElementImpl::mapMouseEvent(int x_, int y_, int width_, int height_,
674                                    RenderObject::NodeInfo& info)
675 {
676     bool inside = false;
677     if (width_ != lastw || height_ != lasth)
678     {
679         region=getRegion(width_, height_);
680         lastw=width_; lasth=height_;
681     }
682     if (region.contains(QPoint(x_,y_)))
683     {
684         inside = true;
685         info.setInnerNode(this);
686         info.setURLElement(this);
687     }
688
689     return inside;
690 }
691
692 QRect HTMLAreaElementImpl::getRect(RenderObject* obj) const
693 {
694     int dx, dy;
695     obj->absolutePosition(dx, dy);
696     QRegion region = getRegion(lastw,lasth);
697     region.translate(dx, dy);
698     return region.boundingRect();
699 }
700
701 QRegion HTMLAreaElementImpl::getRegion(int width_, int height_) const
702 {
703     QRegion region;
704     if (!m_coords)
705         return region;
706
707     // added broken HTML support (Dirk): some pages omit the SHAPE
708     // attribute, so we try to guess by looking at the coords count
709     // what the HTML author tried to tell us.
710
711     // a Poly needs at least 3 points (6 coords), so this is correct
712     if ((m_shape==Poly || m_shape==Unknown) && m_coordsLen > 5) {
713         // make sure its even
714         int len = m_coordsLen >> 1;
715         QPointArray points(len);
716         for (int i = 0; i < len; ++i)
717             points.setPoint(i, m_coords[(i<<1)].minWidth(width_),
718                             m_coords[(i<<1)+1].minWidth(height_));
719         region = QRegion(points);
720     }
721     else if (m_shape==Circle && m_coordsLen>=3 || m_shape==Unknown && m_coordsLen == 3) {
722         int r = kMin(m_coords[2].minWidth(width_), m_coords[2].minWidth(height_));
723         region = QRegion(m_coords[0].minWidth(width_)-r,
724                          m_coords[1].minWidth(height_)-r, 2*r, 2*r,QRegion::Ellipse);
725     }
726     else if (m_shape==Rect && m_coordsLen>=4 || m_shape==Unknown && m_coordsLen == 4) {
727         int x0 = m_coords[0].minWidth(width_);
728         int y0 = m_coords[1].minWidth(height_);
729         int x1 = m_coords[2].minWidth(width_);
730         int y1 = m_coords[3].minWidth(height_);
731         region = QRegion(x0,y0,x1-x0,y1-y0);
732     }
733     else if (m_shape==Default)
734         region = QRegion(0,0,width_,height_);
735     // else
736        // return null region
737
738     return region;
739 }
740
741 DOMString HTMLAreaElementImpl::accessKey() const
742 {
743     return getAttribute(ATTR_ACCESSKEY);
744 }
745
746 void HTMLAreaElementImpl::setAccessKey(const DOMString &value)
747 {
748     setAttribute(ATTR_ACCESSKEY, value);
749 }
750
751 DOMString HTMLAreaElementImpl::alt() const
752 {
753     return getAttribute(ATTR_ALT);
754 }
755
756 void HTMLAreaElementImpl::setAlt(const DOMString &value)
757 {
758     setAttribute(ATTR_ALT, value);
759 }
760
761 DOMString HTMLAreaElementImpl::coords() const
762 {
763     return getAttribute(ATTR_COORDS);
764 }
765
766 void HTMLAreaElementImpl::setCoords(const DOMString &value)
767 {
768     setAttribute(ATTR_COORDS, value);
769 }
770
771 DOMString HTMLAreaElementImpl::href() const
772 {
773     return getDocument()->completeURL(getAttribute(ATTR_HREF));
774 }
775
776 void HTMLAreaElementImpl::setHref(const DOMString &value)
777 {
778     setAttribute(ATTR_HREF, value);
779 }
780
781 bool HTMLAreaElementImpl::noHref() const
782 {
783     return !getAttribute(ATTR_NOHREF).isNull();
784 }
785
786 void HTMLAreaElementImpl::setNoHref(bool noHref)
787 {
788     setAttribute(ATTR_NOHREF, noHref ? "" : 0);
789 }
790
791 DOMString HTMLAreaElementImpl::shape() const
792 {
793     return getAttribute(ATTR_SHAPE);
794 }
795
796 void HTMLAreaElementImpl::setShape(const DOMString &value)
797 {
798     setAttribute(ATTR_SHAPE, value);
799 }
800
801 long HTMLAreaElementImpl::tabIndex() const
802 {
803     return getAttribute(ATTR_TABINDEX).toInt();
804 }
805
806 void HTMLAreaElementImpl::setTabIndex(long tabIndex)
807 {
808     setAttribute(ATTR_TABINDEX, QString::number(tabIndex));
809 }
810
811 DOMString HTMLAreaElementImpl::target() const
812 {
813     return getAttribute(ATTR_TARGET);
814 }
815
816 void HTMLAreaElementImpl::setTarget(const DOMString &value)
817 {
818     setAttribute(ATTR_TARGET, value);
819 }