khtml Library API Documentation

html_imageimpl.cpp

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