khtml Library API Documentation

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 }
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.4.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Sun Feb 27 22:16:35 2005 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001