⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 renderimage.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) 1999 Lars Knoll (knoll@kde.org) *           (C) 1999 Antti Koivisto (koivisto@kde.org) *           (C) 2000 Dirk Mueller (mueller@kde.org) *           (C) 2006 Allan Sandfeld Jensen (kde@carewolf.com) *           (C) 2006 Samuel Weinig (sam.weinig@gmail.com) * Copyright (C) 2003, 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. * * 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., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */#include "config.h"#include "RenderImage.h"#include "BitmapImage.h"#include "Document.h"#include "FrameView.h"#include "GraphicsContext.h"#include "HTMLImageElement.h"#include "HTMLInputElement.h"#include "HTMLMapElement.h"#include "HTMLNames.h"#include "HitTestResult.h"#include "Page.h"#include "RenderView.h"#include <wtf/CurrentTime.h>#if ENABLE(WML)#include "WMLImageElement.h"#include "WMLNames.h"#endifusing namespace std;namespace WebCore {static const double cInterpolationCutoff = 800. * 800.;static const double cLowQualityTimeThreshold = 0.050; // 50 msclass RenderImageScaleData {public:    RenderImageScaleData(RenderImage* image, const IntSize& size, double time, bool lowQualityScale)        : m_size(size)        , m_time(time)        , m_lowQualityScale(lowQualityScale)        , m_highQualityRepaintTimer(image, &RenderImage::highQualityRepaintTimerFired)    {    }    ~RenderImageScaleData()    {        m_highQualityRepaintTimer.stop();    }        const IntSize& size() const { return m_size; }    double time() const { return m_time; }    bool useLowQualityScale() const { return m_lowQualityScale; }    Timer<RenderImage>& hiqhQualityRepaintTimer() { return m_highQualityRepaintTimer; }    void setSize(const IntSize& s) { m_size = s; }    void setTime(double t) { m_time = t; }    void setUseLowQualityScale(bool b)    {        m_highQualityRepaintTimer.stop();        m_lowQualityScale = b;        if (b)            m_highQualityRepaintTimer.startOneShot(cLowQualityTimeThreshold);    }    private:    IntSize m_size;    double m_time;    bool m_lowQualityScale;    Timer<RenderImage> m_highQualityRepaintTimer;};class RenderImageScaleObserver{public:    static bool shouldImagePaintAtLowQuality(RenderImage*, const IntSize&);    static void imageDestroyed(RenderImage* image)    {        if (gImages) {            RenderImageScaleData* data = gImages->take(image);            delete data;            if (gImages->size() == 0) {                delete gImages;                gImages = 0;            }        }    }        static void highQualityRepaintTimerFired(RenderImage* image)    {        RenderImageScaleObserver::imageDestroyed(image);        image->repaint();    }        static HashMap<RenderImage*, RenderImageScaleData*>* gImages;};bool RenderImageScaleObserver::shouldImagePaintAtLowQuality(RenderImage* image, const IntSize& size){    // If the image is not a bitmap image, then none of this is relevant and we just paint at high    // quality.    if (!image->image() || !image->image()->isBitmapImage())        return false;    // Make sure to use the unzoomed image size, since if a full page zoom is in effect, the image    // is actually being scaled.    IntSize imageSize(image->image()->width(), image->image()->height());    // Look ourselves up in the hashtable.    RenderImageScaleData* data = 0;    if (gImages)        data = gImages->get(image);    if (imageSize == size) {        // There is no scale in effect.  If we had a scale in effect before, we can just delete this data.        if (data) {            gImages->remove(image);            delete data;        }        return false;    }    // There is no need to hash scaled images that always use low quality mode when the page demands it.  This is the iChat case.    if (image->document()->page()->inLowQualityImageInterpolationMode()) {        double totalPixels = static_cast<double>(image->image()->width()) * static_cast<double>(image->image()->height());        if (totalPixels > cInterpolationCutoff)            return true;    }    // If there is no data yet, we will paint the first scale at high quality and record the paint time in case a second scale happens    // very soon.    if (!data) {        data = new RenderImageScaleData(image, size, currentTime(), false);        if (!gImages)            gImages = new HashMap<RenderImage*, RenderImageScaleData*>;        gImages->set(image, data);        return false;    }    // We are scaled, but we painted already at this size, so just keep using whatever mode we last painted with.    if (data->size() == size)        return data->useLowQualityScale();    // We have data and our size just changed.  If this change happened quickly, go into low quality mode and then set a repaint    // timer to paint in high quality mode.  Otherwise it is ok to just paint in high quality mode.    double newTime = currentTime();    data->setUseLowQualityScale(newTime - data->time() < cLowQualityTimeThreshold);    data->setTime(newTime);    data->setSize(size);    return data->useLowQualityScale();}HashMap<RenderImage*, RenderImageScaleData*>* RenderImageScaleObserver::gImages = 0;void RenderImage::highQualityRepaintTimerFired(Timer<RenderImage>*){    RenderImageScaleObserver::highQualityRepaintTimerFired(this);}using namespace HTMLNames;RenderImage::RenderImage(Node* node)    : RenderReplaced(node, IntSize(0, 0))    , m_cachedImage(0){    updateAltText();    view()->frameView()->setIsVisuallyNonEmpty();}RenderImage::~RenderImage(){    if (m_cachedImage)        m_cachedImage->removeClient(this);    RenderImageScaleObserver::imageDestroyed(this);}void RenderImage::setCachedImage(CachedImage* newImage){    if (m_cachedImage == newImage)        return;    if (m_cachedImage)        m_cachedImage->removeClient(this);    m_cachedImage = newImage;    if (m_cachedImage) {        m_cachedImage->addClient(this);        if (m_cachedImage->errorOccurred())            imageChanged(m_cachedImage.get());    }}// If we'll be displaying either alt text or an image, add some padding.static const unsigned short paddingWidth = 4;static const unsigned short paddingHeight = 4;// Alt text is restricted to this maximum size, in pixels.  These are// signed integers because they are compared with other signed values.static const int maxAltTextWidth = 1024;static const int maxAltTextHeight = 256;// Sets the image height and width to fit the alt text.  Returns true if the// image size changed.bool RenderImage::setImageSizeForAltText(CachedImage* newImage /* = 0 */){    int imageWidth = 0;    int imageHeight = 0;      // If we'll be displaying either text or an image, add a little padding.    if (!m_altText.isEmpty() || newImage) {        imageWidth = paddingWidth;        imageHeight = paddingHeight;    }      if (newImage) {        // imageSize() returns 0 for the error image.  We need the true size of the        // error image, so we have to get it by grabbing image() directly.        imageWidth += newImage->image()->width() * style()->effectiveZoom();        imageHeight += newImage->image()->height() * style()->effectiveZoom();    }      // we have an alt and the user meant it (its not a text we invented)    if (!m_altText.isEmpty()) {        const Font& font = style()->font();        imageWidth = max(imageWidth, min(font.width(TextRun(m_altText.characters(), m_altText.length())), maxAltTextWidth));        imageHeight = max(imageHeight, min(font.height(), maxAltTextHeight));    }      IntSize imageSize = IntSize(imageWidth, imageHeight);    if (imageSize == intrinsicSize())        return false;    setIntrinsicSize(imageSize);    return true;}void RenderImage::imageChanged(WrappedImagePtr newImage, const IntRect* rect){    if (documentBeingDestroyed())        return;    if (hasBoxDecorations() || hasMask())        RenderReplaced::imageChanged(newImage, rect);        if (newImage != imagePtr() || !newImage)        return;    bool imageSizeChanged = false;    // Set image dimensions, taking into account the size of the alt text.    if (errorOccurred())        imageSizeChanged = setImageSizeForAltText(m_cachedImage.get());        bool shouldRepaint = true;    // Image dimensions have been changed, see what needs to be done    if (imageSize(style()->effectiveZoom()) != intrinsicSize() || imageSizeChanged) {        if (!errorOccurred())            setIntrinsicSize(imageSize(style()->effectiveZoom()));        // In the case of generated image content using :before/:after, we might not be in the        // render tree yet.  In that case, we don't need to worry about check for layout, since we'll get a        // layout when we get added in to the render tree hierarchy later.        if (containingBlock()) {            // lets see if we need to relayout at all..            int oldwidth = width();            int oldheight = height();            if (!prefWidthsDirty())                setPrefWidthsDirty(true);            calcWidth();            calcHeight();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -