📄 html_imageimpl.cpp
字号:
/**
* This file is part of the DOM implementation for KDE.
*
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
* Copyright (C) 2004 Apple Computer, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "html/html_imageimpl.h"
#include "html/html_formimpl.h"
#include "html/html_documentimpl.h"
#include "misc/htmlhashes.h"
#include "khtmlview.h"
#include "khtml_part.h"
#include <kstringhandler.h>
#include <kglobal.h>
#include <kdebug.h>
#include "rendering/render_image.h"
#include "rendering/render_flow.h"
#include "css/cssstyleselector.h"
#include "css/cssproperties.h"
#include "css/cssvalues.h"
#include "css/csshelper.h"
#include "xml/dom2_eventsimpl.h"
#include <qstring.h>
#include <qpoint.h>
#include <qregion.h>
#include <qptrstack.h>
#include <qimage.h>
#include <qpointarray.h>
using namespace DOM;
using namespace khtml;
//#define INSTRUMENT_LAYOUT_SCHEDULING 1
HTMLImageLoader::HTMLImageLoader(ElementImpl* elt)
:m_element(elt), m_image(0), m_firedLoad(true), m_imageComplete(true)
{
}
HTMLImageLoader::~HTMLImageLoader()
{
if (m_image)
m_image->deref(this);
if (m_element->getDocument())
m_element->getDocument()->removeImage(this);
}
void HTMLImageLoader::updateFromElement()
{
// If we're not making renderers for the page, then don't load images. We don't want to slow
// down the raw HTML parsing case by loading images we don't intend to display.
if (!element()->getDocument()->renderer())
return;
AtomicString attr;
if (element()->id() == ID_OBJECT)
attr = element()->getAttribute(ATTR_DATA);
else
attr = element()->getAttribute(ATTR_SRC);
// Treat a lack of src or empty string for src as no image at all.
CachedImage* newImage = 0;
if (!attr.isEmpty())
newImage = element()->getDocument()->docLoader()->requestImage(khtml::parseURL(attr));
if (newImage != m_image) {
m_firedLoad = false;
m_imageComplete = false;
CachedImage* oldImage = m_image;
m_image = newImage;
if (m_image)
m_image->ref(this);
if (oldImage)
oldImage->deref(this);
}
#if APPLE_CHANGES
khtml::RenderImage *renderer = static_cast<khtml::RenderImage*>(element()->renderer());
if (renderer)
renderer->resetAnimation();
#endif
}
void HTMLImageLoader::dispatchLoadEvent()
{
if (!m_firedLoad) {
m_firedLoad = true;
if (m_image->isErrorImage())
element()->dispatchHTMLEvent(EventImpl::ERROR_EVENT, false, false);
else
element()->dispatchHTMLEvent(EventImpl::LOAD_EVENT, false, false);
}
}
void HTMLImageLoader::notifyFinished(CachedObject* image)
{
m_imageComplete = true;
DocumentImpl* document = element()->getDocument();
if (document) {
document->dispatchImageLoadEventSoon(this);
#ifdef INSTRUMENT_LAYOUT_SCHEDULING
if (!document->ownerElement())
printf("Image loaded at %d\n", element()->getDocument()->elapsedTime());
#endif
}
if (element()->renderer()) {
RenderImage* imageObj = static_cast<RenderImage*>(element()->renderer());
imageObj->setImage(m_image);
}
}
// -------------------------------------------------------------------------
HTMLImageElementImpl::HTMLImageElementImpl(DocumentPtr *doc, HTMLFormElementImpl *f)
: HTMLElementImpl(doc), m_imageLoader(this), ismap(false), m_form(f)
{
if (m_form)
m_form->registerImgElement(this);
}
HTMLImageElementImpl::~HTMLImageElementImpl()
{
if (m_form)
m_form->removeImgElement(this);
}
NodeImpl::Id HTMLImageElementImpl::id() const
{
return ID_IMG;
}
bool HTMLImageElementImpl::mapToEntry(NodeImpl::Id attr, MappedAttributeEntry& result) const
{
switch(attr)
{
case ATTR_WIDTH:
case ATTR_HEIGHT:
case ATTR_VSPACE:
case ATTR_HSPACE:
case ATTR_VALIGN:
result = eUniversal;
return false;
case ATTR_BORDER:
case ATTR_ALIGN:
result = eReplaced; // Shared with embeds and iframes
return false;
default:
break;
}
return HTMLElementImpl::mapToEntry(attr, result);
}
void HTMLImageElementImpl::parseHTMLAttribute(HTMLAttributeImpl *attr)
{
switch (attr->id())
{
case ATTR_ALT:
if (m_render) static_cast<RenderImage*>(m_render)->updateAltText();
break;
case ATTR_SRC:
m_imageLoader.updateFromElement();
break;
case ATTR_WIDTH:
addCSSLength(attr, CSS_PROP_WIDTH, attr->value());
break;
case ATTR_HEIGHT:
addCSSLength(attr, CSS_PROP_HEIGHT, attr->value());
break;
case ATTR_BORDER:
// border="noborder" -> border="0"
if(attr->value().toInt()) {
addCSSLength(attr, CSS_PROP_BORDER_WIDTH, attr->value());
addCSSProperty(attr, CSS_PROP_BORDER_TOP_STYLE, CSS_VAL_SOLID);
addCSSProperty(attr, CSS_PROP_BORDER_RIGHT_STYLE, CSS_VAL_SOLID);
addCSSProperty(attr, CSS_PROP_BORDER_BOTTOM_STYLE, CSS_VAL_SOLID);
addCSSProperty(attr, CSS_PROP_BORDER_LEFT_STYLE, CSS_VAL_SOLID);
}
break;
case ATTR_VSPACE:
addCSSLength(attr, CSS_PROP_MARGIN_TOP, attr->value());
addCSSLength(attr, CSS_PROP_MARGIN_BOTTOM, attr->value());
break;
case ATTR_HSPACE:
addCSSLength(attr, CSS_PROP_MARGIN_LEFT, attr->value());
addCSSLength(attr, CSS_PROP_MARGIN_RIGHT, attr->value());
break;
case ATTR_ALIGN:
addHTMLAlignment(attr);
break;
case ATTR_VALIGN:
addCSSProperty(attr, CSS_PROP_VERTICAL_ALIGN, attr->value());
break;
case ATTR_USEMAP:
if ( attr->value().domString()[0] == '#' )
usemap = attr->value();
else {
QString url = getDocument()->completeURL( khtml::parseURL( attr->value() ).string() );
// ### we remove the part before the anchor and hope
// the map is on the same html page....
usemap = url;
}
m_hasAnchor = !attr->isNull();
case ATTR_ISMAP:
ismap = true;
break;
case ATTR_ONABORT: // ### add support for this
setHTMLEventListener(EventImpl::ABORT_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONERROR:
setHTMLEventListener(EventImpl::ERROR_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_ONLOAD:
setHTMLEventListener(EventImpl::LOAD_EVENT,
getDocument()->createHTMLEventListener(attr->value().string(), this));
break;
case ATTR_NOSAVE:
break;
#if APPLE_CHANGES
case ATTR_COMPOSITE:
_compositeOperator = attr->value().string();
break;
#endif
case ATTR_NAME:
{
QString newNameAttr = attr->value().string();
if (attached() && getDocument()->isHTMLDocument()) {
HTMLDocumentImpl *document = static_cast<HTMLDocumentImpl *>(getDocument());
document->removeNamedImageOrForm(oldNameAttr);
document->addNamedImageOrForm(newNameAttr);
}
oldNameAttr = newNameAttr;
}
break;
case ATTR_ID:
{
QString newIdAttr = attr->value().string();
if (attached() && getDocument()->isHTMLDocument()) {
HTMLDocumentImpl *document = static_cast<HTMLDocumentImpl *>(getDocument());
document->removeNamedImageOrForm(oldIdAttr);
document->addNamedImageOrForm(newIdAttr);
}
oldIdAttr = newIdAttr;
}
// fall through
default:
HTMLElementImpl::parseHTMLAttribute(attr);
}
}
DOMString HTMLImageElementImpl::altText() const
{
// lets figure out the alt text.. magic stuff
// http://www.w3.org/TR/1998/REC-html40-19980424/appendix/notes.html#altgen
// also heavily discussed by Hixie on bugzilla
DOMString alt( getAttribute( ATTR_ALT ) );
// fall back to title attribute
if ( alt.isNull() )
alt = getAttribute( ATTR_TITLE );
#if 0
if ( alt.isNull() ) {
QString p = KURL( getDocument()->completeURL( getAttribute(ATTR_SRC).string() ) ).prettyURL();
int pos;
if ( ( pos = p.findRev( '.' ) ) > 0 )
p.truncate( pos );
alt = DOMString( KStringHandler::csqueeze( p ) );
}
#endif
return alt;
}
RenderObject *HTMLImageElementImpl::createRenderer(RenderArena *arena, RenderStyle *style)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -