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

📄 loader.cpp

📁 手机浏览器源码程序,功能强大
💻 CPP
📖 第 1 页 / 共 5 页
字号:
{
    if(eof && pos == buffer.size())
        return -1;

    return  buffer.size() - pos;
}

void ImageSource::sendTo(QDataSink* sink, int n)
{
    sink->receive((const uchar*)&buffer.at(pos), n);

    pos += n;

    // buffer is no longer needed
    if(eof && pos == buffer.size() && !rewable)
    {
        buffer.resize(0);
        pos = 0;
    }
}

void ImageSource::setEOF( bool state )
{
    eof = state;
}

// ImageSource's is rewindable.
bool ImageSource::rewindable() const
{
    return rewable;
}

// Enables rewinding.  No special action is taken.
void ImageSource::enableRewind(bool on)
{
    rew = on;
}

// Calls reset() on the QIODevice.
void ImageSource::rewind()
{
    pos = 0;
    if (!rew) {
        QDataSource::rewind();
    } else
        ready();
}

void ImageSource::cleanBuffer()
{
    // if we need to be able to rewind, buffer is needed
    if(rew)
        return;

    rewable = false;

    // buffer is no longer needed
    if(eof && pos == buffer.size())
    {
        buffer.resize(0);
        pos = 0;
    }
}

static QString buildAcceptHeader()
{
    QString result = KImageIO::mimeTypes( KImageIO::Reading ).join(", ");
    if (result.right(2) == ", ")
        result = result.left(result.length()-2);
    return result;
}

#endif // APPLE_CHANGES

static bool crossDomain(const QString &a, const QString &b)
{
    if (a == b) return false;

    QStringList l1 = QStringList::split('.', a);
    QStringList l2 = QStringList::split('.', b);

    while(l1.count() > l2.count())
        l1.pop_front();

    while(l2.count() > l1.count())
        l2.pop_front();

    while(l2.count() >= 2)
    {
        if (l1 == l2)
           return false;

        l1.pop_front();
        l2.pop_front();
    }
    return true;
}

// -------------------------------------------------------------------------------------
#if APPLE_CHANGES
void CachedImageCallback::notifyUpdate()
{
    if (cachedImage) {
        cachedImage->do_notify (cachedImage->pixmap(), cachedImage->pixmap().rect());
        QSize s = cachedImage->pixmap_size();
        cachedImage->setSize(s.width() * s.height() * 2);

        // After receiving the image header we are guaranteed to know
        // the image size.  Although all of the data may not have arrived or
        // been decoded we can consider the image loaded for purposed of
        // layout and dispatching the image's onload handler.  Removing the request from
        // the list of background decoding requests will ensure that Loader::numRequests()
        // does not count this background request.  Further numRequests() can
        // be correctly used by the part to determine if loading is sufficiently
        // complete to dispatch the page's onload handler.
        Request *r = cachedImage->m_request;
        if( r ) {
        DocLoader *dl = r->m_docLoader;

        khtml::Cache::loader()->removeBackgroundDecodingRequest(r);

        // Poke the part to get it to do a checkCompleted().  Only do this for
        // the first update to minimize work.  Note that we are guaranteed to have
        // read the header when we received this first update, which is triggered
        // by the first kCGImageStatusIncomplete status from CG. kCGImageStatusIncomplete
        // really means that the CG decoder is waiting for more data, but has already
        // read the header.
        if (!headerReceived) {
            emit khtml::Cache::loader()->requestDone( dl, cachedImage );
            headerReceived = true;
            }
        }
    }
}

void CachedImageCallback::notifyFinished()
{
    if (cachedImage) {
        cachedImage->do_notify (cachedImage->pixmap(), cachedImage->pixmap().rect());
        cachedImage->m_loading = false;
        cachedImage->checkNotify();
        QSize s = cachedImage->pixmap_size();
        cachedImage->setSize(s.width() * s.height() * 2);

        Request *r = cachedImage->m_request;
        if( r ) {
        DocLoader *dl = r->m_docLoader;

        khtml::Cache::loader()->removeBackgroundDecodingRequest(r);

        // Poke the part to get it to do a checkCompleted().
        emit khtml::Cache::loader()->requestDone( dl, cachedImage );

        delete r;
        }
    }
}

void CachedImageCallback::notifyDecodingError()
{
    if (cachedImage) {
        handleError();
    }
}

void CachedImageCallback::handleError()
{
    if (cachedImage) {
        cachedImage->errorOccured = true;
        QPixmap ep = cachedImage->pixmap();
        cachedImage->do_notify (ep, ep.rect());
        Cache::removeCacheEntry (cachedImage);

        clear();
    }
}

void CachedImageCallback::clear()
{
    if (cachedImage && cachedImage->m_request) {
        Request *r = cachedImage->m_request;
        DocLoader *dl = r->m_docLoader;

        khtml::Cache::loader()->removeBackgroundDecodingRequest(r);

        // Poke the part to get it to do a checkCompleted().
        emit khtml::Cache::loader()->requestFailed( dl, cachedImage );

        delete r;
    }
    cachedImage = 0;
}
#endif

CachedImage::CachedImage(DocLoader* dl, const DOMString &url, KIO::CacheControl _cachePolicy, time_t _expireDate)
    : QObject(), CachedObject(url, Image, _cachePolicy, _expireDate)
#if APPLE_CHANGES
    , m_dataSize(0)
#endif
{
#if !APPLE_CHANGES
    static const QString &acceptHeader = KGlobal::staticQString( buildAcceptHeader() );
#endif

    m = 0;
    p = 0;
    pixPart = 0;
    bg = 0;
#if !APPLE_CHANGES
    bgColor = qRgba( 0, 0, 0, 0xFF );
    typeChecked = false;
#endif
    isFullyTransparent = false;
    errorOccured = false;
    monochrome = false;
    formatType = 0;
    m_status = Unknown;
    imgSource = 0;
    m_loading = true;
#if !APPLE_CHANGES
    setAccept( acceptHeader );
#endif
#if NOKIA_CHANGES
    setAccept( QString::fromLatin1("*/*") );
#endif

    m_showAnimations = dl->showAnimations();
#if APPLE_CHANGES
#if BUILDING_ON_PANTHER
    m_decoderCallback = 0;
#else
    if (QPixmap::shouldUseThreadedDecoding())
        m_decoderCallback = new CachedImageCallback(this);
    else
        m_decoderCallback = 0;
#endif
#endif
}

CachedImage::~CachedImage()
{
    clear();
}

void CachedImage::ref( CachedObjectClient *c )
{
#ifdef CACHE_DEBUG
    kdDebug( 6060 ) << this << " CachedImage::ref(" << c << ") " << endl;
#endif

    CachedObject::ref(c);

    if( m ) {
        m->unpause();
        if( m->finished() || m_clients.count() == 1 )
            m->restart();
    }

    // for mouseovers, dynamic changes
    if (!valid_rect().isNull())
        c->setPixmap( pixmap(), valid_rect(), this);

    if(!m_loading) c->notifyFinished(this);
}

void CachedImage::deref( CachedObjectClient *c )
{
#ifdef CACHE_DEBUG
    kdDebug( 6060 ) << this << " CachedImage::deref(" << c << ") " << endl;
#endif
    Cache::flush();
    CachedObject::deref(c);
    if(m && m_clients.isEmpty() && m->running())
        m->pause();
    if ( canDelete() && m_free )
        delete this;
}

#define BGMINWIDTH      32
#define BGMINHEIGHT     32

const QPixmap &CachedImage::tiled_pixmap(const QColor& newc)
{
#if APPLE_CHANGES
    return pixmap();
#else
    static QRgb bgTransparant = qRgba( 0, 0, 0, 0xFF );
    if ( (bgColor != bgTransparant) && (bgColor != newc.rgb()) ) {
        delete bg; bg = 0;
    }

    if (bg)
        return *bg;

    const QPixmap &r = pixmap();

    if (r.isNull()) return r;

    // no error indication for background images
    if(errorOccured) return *Cache::nullPixmap;

    bool isvalid = newc.isValid();
    QSize s(pixmap_size());
    int w = r.width();
    int h = r.height();
    if ( w*h < 8192 )
    {
        if ( r.width() < BGMINWIDTH )
            w = ((BGMINWIDTH  / s.width())+1) * s.width();
        if ( r.height() < BGMINHEIGHT )
            h = ((BGMINHEIGHT / s.height())+1) * s.height();
    }
    if ( (w != r.width()) || (h != r.height()) || (isvalid && r.mask()))
    {
        QPixmap pix = r;
        if ( w != r.width() || (isvalid && pix.mask()))
        {
            bg = new QPixmap(w, r.height());
            QPainter p(bg);
            if(isvalid) p.fillRect(0, 0, w, r.height(), newc);
            p.drawTiledPixmap(0, 0, w, r.height(), pix);
            if(!isvalid && pix.mask())
            {
                // unfortunately our anti-transparency trick doesn't work here
                // we need to create a mask.
                QBitmap newmask(w, r.height());
                QPainter pm(&newmask);
                pm.drawTiledPixmap(0, 0, w, r.height(), *pix.mask());
                bg->setMask(newmask);
                bgColor = bgTransparant;
            }
            else
                bgColor= newc.rgb();
            pix = *bg;
        }
        if ( h != r.height() )
        {
            delete bg;
            bg = new QPixmap(w, h);
            QPainter p(bg);
            if(isvalid) p.fillRect(0, 0, w, h, newc);
            p.drawTiledPixmap(0, 0, w, h, pix);
            if(!isvalid && pix.mask())
            {
                // unfortunately our anti-transparency trick doesn't work here
                // we need to create a mask.
                QBitmap newmask(w, h);
                QPainter pm(&newmask);
                pm.drawTiledPixmap(0, 0, w, h, *pix.mask());
                bg->setMask(newmask);
                bgColor = bgTransparant;
            }
            else
                bgColor= newc.rgb();
        }
        return *bg;
    }

    return r;
#endif
}

const QPixmap &CachedImage::pixmap( ) const
{
    if(errorOccured)
        return *Cache::brokenPixmap;

#if NOKIA_CHANGES
    if (isErrorImage())
        return *Cache::brokenPixmap;
#endif

#if APPLE_CHANGES
    if (p)
        return *p;
#else
    if(m)
    {
        if(m->framePixmap().size() != m->getValidRect().size() && m->getValidRect().size().isValid())
        {
            // pixmap is not yet completely loaded, so we
            // return a clipped version. asserting here
            // that the valid rect is always from 0/0 to fullwidth/ someheight
            if(!pixPart) pixPart = new QPixmap(m->getValidRect().size());

            (*pixPart) = m->framePixmap();
            pixPart->resize(m->getValidRect().size());
            return *pixPart;
        }
        else
            return m->framePixmap();
    }
    else if(p)
        return *p;
#endif // APPLE_CHANGES

    return *Cache::nullPixmap;
}


QSize CachedImage::pixmap_size() const
{
    return (m ? m->framePixmap().size() : ( p ? p->size() : QSize()));
}


QRect CachedImage::valid_rect() const
{
    return m ? m->getValidRect() : ( p ? p->rect() : QRect());
}


void CachedImage::do_notify(const QPixmap& p, const QRect& r)
{
    CachedObjectClientWalker w(m_clients);
    while (CachedObjectClient *c = w.next())
        c->setPixmap(p, r, this);
}

#if !APPLE_CHANGES

void CachedImage::movieUpdated( const QRect& r )
{
#ifdef CACHE_DEBUG
    qDebug("movie updated %d/%d/%d/%d, pixmap size %d/%d", r.x(), r.y(), r.right(), r.bottom(),
           m->framePixmap().size().width(), m->framePixmap().size().height());
#endif

    do_notify(m->framePixmap(), r);
}

void CachedImage::movieStatus(int status)
{
#ifdef CACHE_DEBUG
    qDebug("movieStatus(%d)", status);
#endif

    // ### the html image objects are supposed to send the load event after every frame (according to
    // netscape). We have a problem though where an image is present, and js code creates a new Image object,
    // which uses the same CachedImage, the one in the document is not supposed to be notified

    // just another Qt 2.2.0 bug. we cannot call
    // QMovie::frameImage if we're after QMovie::EndOfMovie
    if(status == QMovie::EndOfFrame)
    {
        const QImage& im = m->frameImage();
        monochrome = ( ( im.depth() <= 8 ) && ( im.numColors() - int( im.hasAlphaBuffer() ) <= 2 ) );
        for (int i = 0; monochrome && i < im.numColors(); ++i)
            if (im.colorTable()[i] != qRgb(0xff, 0xff, 0xff) &&
                im.colorTable()[i] != qRgb(0x00, 0x00, 0x00))
                monochrome = false;
        if((im.width() < 5 || im.height() < 5) && im.hasAlphaBuffer()) // only evaluate for small images
        {
            QImage am = im.createAlphaMask();
            if(am.depth() == 1)
            {
                bool solid = false;
                for(int y = 0; y < am.height(); y++)
                    for(int x = 0; x < am.width(); x++)
                        if(am.pixelIndex(x, y)) {
                            solid = true;
                            break;
                        }
                isFullyTransparent = (!solid);
            }
        }

⌨️ 快捷键说明

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