html_imageimpl.cpp Source File (khtml Library)

| # khtml Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Source Files

# html_imageimpl.cpp

    00001
    00023 #include "html/html_imageimpl.h"
    00024 #include "html/html_formimpl.h"
    00025 #include "html/html_documentimpl.h"
    00026
    00027 #include "misc/htmlhashes.h"
    00028 #include "khtmlview.h"
    00029 #include "khtml_part.h"
    00030
    00031 #include <kstringhandler.h>
    00032 #include <kglobal.h>
    00033 #include <kdebug.h>
    00034
    00035 #include "rendering/render_image.h"
    00036 #include "rendering/render_flow.h"
    00037 #include "css/cssstyleselector.h"
    00038 #include "css/cssproperties.h"
    00039 #include "css/cssvalues.h"
    00040 #include "css/csshelper.h"
    00041 #include "xml/dom2_eventsimpl.h"
    00042
    00043 #include <qstring.h>
    00044 #include <qpoint.h>
    00045 #include <qregion.h>
    00046 #include <qptrstack.h>
    00047 #include <qimage.h>
    00048 #include <qpointarray.h>
    00049
    00050 using namespace DOM;
    00051 using namespace khtml;
    00052
    00053 // -------------------------------------------------------------------------
    00054
    00055 HTMLImageElementImpl::HTMLImageElementImpl(DocumentPtr *doc, HTMLFormElementImpl *f)
    00056     : HTMLElementImpl(doc), ismap(false), m_form(f)
    00057 {
    00058     if (m_form)
    00059         m_form->registerImgElement(this);
    00060 }
    00061
    00062 HTMLImageElementImpl::~HTMLImageElementImpl()
    00063 {
    00064     if (m_form)
    00065         m_form->removeImgElement(this);
    00066 }
    00067
    00068 NodeImpl::Id HTMLImageElementImpl::id() const
    00069 {
    00070     return ID_IMG;
    00071 }
    00072
    00073 void HTMLImageElementImpl::parseAttribute(AttributeImpl *attr)
    00074 {
    00075     switch (attr->id())
    00076     {
    00077     case ATTR_ALT:
    00078     case ATTR_SRC:
    00079         setChanged();
    00080         break;
    00081     case ATTR_WIDTH:
    00082         addCSSLength(CSS_PROP_WIDTH, attr->value());
    00083         break;
    00084     case ATTR_HEIGHT:
    00085         addCSSLength(CSS_PROP_HEIGHT, attr->value());
    00086         break;
    00087     case ATTR_BORDER:
    00088         // border="noborder" -> border="0"
    00089         if(attr->value().toInt()) {
    00090             addCSSLength(CSS_PROP_BORDER_WIDTH, attr->value());
    00091             addCSSProperty( CSS_PROP_BORDER_TOP_STYLE, CSS_VAL_SOLID );
    00092             addCSSProperty( CSS_PROP_BORDER_RIGHT_STYLE, CSS_VAL_SOLID );
    00093             addCSSProperty( CSS_PROP_BORDER_BOTTOM_STYLE, CSS_VAL_SOLID );
    00094             addCSSProperty( CSS_PROP_BORDER_LEFT_STYLE, CSS_VAL_SOLID );
    00095         }
    00096         break;
    00097     case ATTR_VSPACE:
    00098         addCSSLength(CSS_PROP_MARGIN_TOP, attr->value());
    00099         addCSSLength(CSS_PROP_MARGIN_BOTTOM, attr->value());
    00100         break;
    00101     case ATTR_HSPACE:
    00102         addCSSLength(CSS_PROP_MARGIN_LEFT, attr->value());
    00103         addCSSLength(CSS_PROP_MARGIN_RIGHT, attr->value());
    00104         break;
    00105     case ATTR_ALIGN:
    00106         addHTMLAlignment( attr->value() );
    00107         break;
    00108     case ATTR_VALIGN:
    00109         addCSSProperty(CSS_PROP_VERTICAL_ALIGN, attr->value());
    00110         break;
    00111     case ATTR_USEMAP:
    00112         if ( attr->value()[0] == '#' )
    00113             usemap = attr->value();
    00114         else {
    00115             QString url = getDocument()->completeURL( khtml::parseURL( attr->value() ).string() );
    00116             // ### we remove the part before the anchor and hope
    00117             // the map is on the same html page....
    00118             usemap = url;
    00119         }
    00120         m_hasAnchor = attr->val() != 0;
    00121     case ATTR_ISMAP:
    00122         ismap = true;
    00123         break;
    00124     case ATTR_ONABORT: // ### add support for this
    00125         setHTMLEventListener(EventImpl::ABORT_EVENT,
    00126             getDocument()->createHTMLEventListener(attr->value().string()));
    00127         break;
    00128     case ATTR_ONERROR: // ### add support for this
    00129         setHTMLEventListener(EventImpl::ERROR_EVENT,
    00130             getDocument()->createHTMLEventListener(attr->value().string()));
    00131         break;
    00132     case ATTR_ONLOAD:
    00133         setHTMLEventListener(EventImpl::LOAD_EVENT,
    00134             getDocument()->createHTMLEventListener(attr->value().string()));
    00135         break;
    00136     case ATTR_NAME:
    00137     case ATTR_NOSAVE:
    00138         break;
    00139     default:
    00140         HTMLElementImpl::parseAttribute(attr);
    00141     }
    00142 }
    00143
    00144 DOMString HTMLImageElementImpl::altText() const
    00145 {
    00146     // lets figure out the alt text.. magic stuff
    00147     // http://www.w3.org/TR/1998/REC-html40-19980424/appendix/notes.html#altgen
    00148     // also heavily discussed by Hixie on bugzilla
    00149     DOMString alt( getAttribute( ATTR_ALT ) );
    00150     // fall back to title attribute
    00151     if ( alt.isNull() )
    00152         alt = getAttribute( ATTR_TITLE );
    00153 #if 0
    00154     if ( alt.isNull() ) {
    00155         QString p = KURL( getDocument()->completeURL( getAttribute(ATTR_SRC).string() ) ).prettyURL();
    00156         int pos;
    00157         if ( ( pos = p.findRev( '.' ) ) > 0 )
    00158             p.truncate( pos );
    00159         alt = DOMString( KStringHandler::csqueeze( p ) );
    00160     }
    00161 #endif
    00162
    00163     return alt;
    00164 }
    00165
    00166 void HTMLImageElementImpl::attach()
    00167 {
    00168     assert(!attached());
    00169     assert(!m_render);
    00170     assert(parentNode());
    00171
    00172     RenderStyle* _style = getDocument()->styleSelector()->styleForElement(this);
    00173     _style->ref();
    00174     if (parentNode()->renderer() && _style->display() != NONE) {
    00175         m_render = new RenderImage(this);
    00176         m_render->setStyle(getDocument()->styleSelector()->styleForElement(this));
    00177         parentNode()->renderer()->addChild(m_render, nextRenderer());
    00178         m_render->updateFromElement();
    00179     }
    00180     _style->deref();
    00181
    00182     NodeBaseImpl::attach();
    00183 }
    00184
    00185 long HTMLImageElementImpl::width() const
    00186 {
    00187     if (!m_render) return getAttribute(ATTR_WIDTH).toInt();
    00188
    00189     // ### make a unified call for this
    00190     if (changed()) {
    00191         getDocument()->updateRendering();
    00192         if (getDocument()->view())
    00193             getDocument()->view()->layout();
    00194     }
    00195
    00196     return m_render->contentWidth();
    00197 }
    00198
    00199 long HTMLImageElementImpl::height() const
    00200 {
    00201     if (!m_render) return getAttribute(ATTR_HEIGHT).toInt();
    00202
    00203     // ### make a unified call for this
    00204     if (changed()) {
    00205         getDocument()->updateRendering();
    00206         if (getDocument()->view())
    00207             getDocument()->view()->layout();
    00208     }
    00209
    00210     return m_render->contentHeight();
    00211 }
    00212
    00213 QImage HTMLImageElementImpl::currentImage() const
    00214 {
    00215     RenderImage *r = static_cast<RenderImage*>(renderer());
    00216
    00217     if(r)
    00218         return r->pixmap().convertToImage();
    00219
    00220     return QImage();
    00221 }
    00222
    00223
    00224 bool HTMLImageElementImpl::complete() const
    00225 {
    00226     RenderImage *r = static_cast<RenderImage*>(renderer());
    00227     if(r)
    00228         return r->complete();
    00229     return false;
    00230 }
    00231
    00232 // -------------------------------------------------------------------------
    00233
    00234 HTMLMapElementImpl::HTMLMapElementImpl(DocumentPtr *doc)
    00235     : HTMLElementImpl(doc)
    00236 {
    00237 }
    00238
    00239 HTMLMapElementImpl::~HTMLMapElementImpl()
    00240 {
    00241     if(getDocument() && getDocument()->isHTMLDocument())
    00242         static_cast<HTMLDocumentImpl*>(getDocument())->mapMap.remove(name);
    00243 }
    00244
    00245 NodeImpl::Id HTMLMapElementImpl::id() const
    00246 {
    00247     return ID_MAP;
    00248 }
    00249
    00250 bool
    00251 HTMLMapElementImpl::mapMouseEvent(int x_, int y_, int width_, int height_,
    00252                                   RenderObject::NodeInfo& info)
    00253 {
    00254     //cout << "map:mapMouseEvent " << endl;
    00255     //cout << x_ << " " << y_ <<" "<< width_ <<" "<< height_ << endl;
    00256     QPtrStack<NodeImpl> nodeStack;
    00257
    00258     NodeImpl *current = firstChild();
    00259     while(1)
    00260     {
    00261         if(!current)
    00262         {
    00263             if(nodeStack.isEmpty()) break;
    00264             current = nodeStack.pop();
    00265             current = current->nextSibling();
    00266             continue;
    00267         }
    00268         if(current->id()==ID_AREA)
    00269         {
    00270             //cout << "area found " << endl;
    00271             HTMLAreaElementImpl* area=static_cast<HTMLAreaElementImpl*>(current);
    00272             if (area->mapMouseEvent(x_,y_,width_,height_, info))
    00273                 return true;
    00274         }
    00275         NodeImpl *child = current->firstChild();
    00276         if(child)
    00277         {
    00278             nodeStack.push(current);
    00279             current = child;
    00280         }
    00281         else
    00282         {
    00283             current = current->nextSibling();
    00284         }
    00285     }
    00286
    00287     return false;
    00288 }
    00289
    00290 void HTMLMapElementImpl::parseAttribute(AttributeImpl *attr)
    00291 {
    00292     switch (attr->id())
    00293     {
    00294     case ATTR_ID:
    00295         if (getDocument()->htmlMode() != DocumentImpl::XHtml) break;
    00296         // fall through
    00297     case ATTR_NAME:
    00298     {
    00299         DOMString s = attr->value();
    00300         if(*s.unicode() == '#')
    00301             name = QString(s.unicode()+1, s.length()-1);
    00302         else
    00303             name = s.string();
    00304         // ### make this work for XML documents, e.g. in case of <html:map...>
    00305         if(getDocument()->isHTMLDocument())
    00306             static_cast<HTMLDocumentImpl*>(getDocument())->mapMap[name] = this;
    00307         break;
    00308     }
    00309     default:
    00310         HTMLElementImpl::parseAttribute(attr);
    00311     }
    00312 }
    00313
    00314 // -------------------------------------------------------------------------
    00315
    00316 HTMLAreaElementImpl::HTMLAreaElementImpl(DocumentPtr *doc)
    00317     : HTMLAnchorElementImpl(doc)
    00318 {
    00319     m_coords=0;
    00320     m_coordsLen = 0;
    00321     nohref = false;
    00322     shape = Unknown;
    00323     lasth = lastw = -1;
    00324 }
    00325
    00326 HTMLAreaElementImpl::~HTMLAreaElementImpl()
    00327 {
    00328     if (m_coords) delete [] m_coords;
    00329 }
    00330
    00331 NodeImpl::Id HTMLAreaElementImpl::id() const
    00332 {
    00333     return ID_AREA;
    00334 }
    00335
    00336 void HTMLAreaElementImpl::parseAttribute(AttributeImpl *attr)
    00337 {
    00338     switch (attr->id())
    00339     {
    00340     case ATTR_SHAPE:
    00341         if ( strcasecmp( attr->value(), "default" ) == 0 )
    00342             shape = Default;
    00343         else if ( strcasecmp( attr->value(), "circle" ) == 0 )
    00344             shape = Circle;
    00345         else if ( strcasecmp( attr->value(), "poly" ) == 0 )
    00346             shape = Poly;
    00347         else if ( strcasecmp( attr->value(), "rect" ) == 0 )
    00348             shape = Rect;
    00349         break;
    00350     case ATTR_COORDS:
    00351         if (m_coords) delete [] m_coords;
    00352         m_coords = attr->val()->toLengthArray(m_coordsLen);
    00353         break;
    00354     case ATTR_NOHREF:
    00355         nohref = attr->val() != 0;
    00356         break;
    00357     case ATTR_TARGET:
    00358         m_hasTarget = attr->val() != 0;
    00359         break;
    00360     case ATTR_ALT:
    00361         break;
    00362     case ATTR_ACCESSKEY:
    00363         break;
    00364     default:
    00365         HTMLAnchorElementImpl::parseAttribute(attr);
    00366     }
    00367 }
    00368
    00369 bool HTMLAreaElementImpl::mapMouseEvent(int x_, int y_, int width_, int height_,
    00370                                    RenderObject::NodeInfo& info)
    00371 {
    00372     bool inside = false;
    00373     if (width_ != lastw || height_ != lasth)
    00374     {
    00375         region=getRegion(width_, height_);
    00376         lastw=width_; lasth=height_;
    00377     }
    00378     if (region.contains(QPoint(x_,y_)))
    00379     {
    00380         inside = true;
    00381         info.setInnerNode(this);
    00382         info.setURLElement(this);
    00383     }
    00384
    00385     return inside;
    00386 }
    00387
    00388 QRect HTMLAreaElementImpl::getRect() const
    00389 {
    00390     if (parentNode()->renderer()==0)
    00391         return QRect();
    00392     int dx, dy;
    00393     if (!parentNode()->renderer()->absolutePosition(dx, dy))
    00394         return QRect();
    00395     QRegion region = getRegion(lastw,lasth);
    00396     region.translate(dx, dy);
    00397     return region.boundingRect();
    00398 }
    00399
    00400 QRegion HTMLAreaElementImpl::getRegion(int width_, int height_) const
    00401 {
    00402     QRegion region;
    00403     if (!m_coords)
    00404         return region;
    00405
    00406     // added broken HTML support (Dirk): some pages omit the SHAPE
    00407     // attribute, so we try to guess by looking at the coords count
    00408     // what the HTML author tried to tell us.
    00409
    00410     // a Poly needs at least 3 points (6 coords), so this is correct
    00411     if ((shape==Poly || shape==Unknown) && m_coordsLen > 5) {
    00412         // make sure its even
    00413         int len = m_coordsLen >> 1;
    00414         QPointArray points(len);
    00415         for (int i = 0; i < len; ++i)
    00416             points.setPoint(i, m_coords[(i<<1)].minWidth(width_),
    00417                             m_coords[(i<<1)+1].minWidth(height_));
    00418         region = QRegion(points);
    00419     }
    00420     else if (shape==Circle && m_coordsLen>=3 || shape==Unknown && m_coordsLen == 3) {
    00421         int r = kMin(m_coords[2].minWidth(width_), m_coords[2].minWidth(height_));
    00422         region = QRegion(m_coords[0].minWidth(width_)-r,
    00423                          m_coords[1].minWidth(height_)-r, 2*r, 2*r,QRegion::Ellipse);
    00424     }
    00425     else if (shape==Rect && m_coordsLen>=4 || shape==Unknown && m_coordsLen == 4) {
    00426         int x0 = m_coords[0].minWidth(width_);
    00427         int y0 = m_coords[1].minWidth(height_);
    00428         int x1 = m_coords[2].minWidth(width_);
    00429         int y1 = m_coords[3].minWidth(height_);
    00430         region = QRegion(x0,y0,x1-x0,y1-y0);
    00431     }
    00432     else if (shape==Default)
    00433         region = QRegion(0,0,width_,height_);
    00434     // else
    00435        // return null region
    00436
    00437     return region;
    00438 }

This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 13:33:54 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001