📄 loader.cpp
字号:
for (int x = 0; x < w; x += r.width()) copyBlt(bg, x, 0, &r, 0, 0, r.width(), r.height()); //Copy first stripe down for (int y = r.height(); y < h; y += r.height()) copyBlt(bg, 0, y, bg, 0, 0, w, r.height()); return *bg; }#endif if (#ifdef Q_WS_X11 !r.hasAlphaChannel() &&#endif ( (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); p.end(); 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;}const QPixmap &CachedImage::pixmap( ) const{ if(m_hadError) return *Cache::brokenPixmap; if(m_wasBlocked) return *Cache::blockedPixmap; if(m) { if(m->framePixmap().size() != m->getValidRect().size()) { // 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(); (*pixPart) = m->framePixmap(); if (m->getValidRect().size().isValid()) pixPart->resize(m->getValidRect().size()); else pixPart->resize(0, 0); return *pixPart; } else return m->framePixmap(); } else if(p) return *p; return *Cache::nullPixmap;}QSize CachedImage::pixmap_size() const{ if (m_wasBlocked) return Cache::blockedPixmap->size(); return (m_hadError ? Cache::brokenPixmap->size() : m ? m->framePixmap().size() : ( p ? p->size() : QSize()));}QRect CachedImage::valid_rect() const{ if (m_wasBlocked) return Cache::blockedPixmap->rect(); return (m_hadError ? Cache::brokenPixmap->rect() : m ? m->getValidRect() : ( p ? p->rect() : QRect()) );}void CachedImage::do_notify(const QPixmap& p, const QRect& r){ for (QPtrDictIterator<CachedObjectClient> it( m_clients ); it.current();) it()->setPixmap( p, r, this);}void CachedImage::movieUpdated( const QRect& r ){#ifdef LOADER_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 LOADER_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); } } // we have to delete our tiled bg variant here // because the frame has changed (in order to keep it in sync) delete bg; bg = 0; } if((status == QMovie::EndOfMovie && (!m || m->frameNumber() <= 1)) || ((status == QMovie::EndOfLoop) && (m_showAnimations == KHTMLSettings::KAnimationLoopOnce)) || ((status == QMovie::EndOfFrame) && (m_showAnimations == KHTMLSettings::KAnimationDisabled)) ) { if(imgSource) { setShowAnimations( KHTMLSettings::KAnimationDisabled ); // monochrome alphamasked images are usually about 10000 times // faster to draw, so this is worth the hack if (p && monochrome && p->depth() > 1) { QPixmap* pix = new QPixmap; pix->convertFromImage( p->convertToImage().convertDepth( 1 ), MonoOnly|AvoidDither ); if ( p->mask() ) pix->setMask( *p->mask() ); delete p; p = pix; monochrome = false; } } for (QPtrDictIterator<CachedObjectClient> it( m_clients ); it.current();) it()->notifyFinished( this ); m_status = Cached; //all done }#if 0 if((status == QMovie::EndOfFrame) || (status == QMovie::EndOfMovie)) {#ifdef LOADER_DEBUG QRect r(valid_rect()); qDebug("movie Status frame update %d/%d/%d/%d, pixmap size %d/%d", r.x(), r.y(), r.right(), r.bottom(), pixmap().size().width(), pixmap().size().height());#endif do_notify(pixmap(), valid_rect()); }#endif}void CachedImage::movieResize(const QSize& /*s*/){ do_notify(m->framePixmap(), QRect());}void CachedImage::setShowAnimations( KHTMLSettings::KAnimationAdvice showAnimations ){ m_showAnimations = showAnimations; if ( (m_showAnimations == KHTMLSettings::KAnimationDisabled) && imgSource ) { imgSource->cleanBuffer(); delete p; p = new QPixmap(m->framePixmap()); m->disconnectUpdate( this, SLOT( movieUpdated( const QRect &) )); m->disconnectStatus( this, SLOT( movieStatus( int ) )); m->disconnectResize( this, SLOT( movieResize( const QSize& ) ) ); QTimer::singleShot(0, this, SLOT( deleteMovie())); imgSource = 0; }}void CachedImage::deleteMovie(){ delete m; m = 0;}void CachedImage::clear(){ delete m; m = 0; delete p; p = 0; delete bg; bg = 0; bgColor = qRgba( 0, 0, 0, 0xff ); delete pixPart; pixPart = 0; formatType = 0; typeChecked = false; setSize(0); // No need to delete imageSource - QMovie does it for us imgSource = 0;}void CachedImage::data ( QBuffer &_buffer, bool eof ){#ifdef LOADER_DEBUG kdDebug( 6060 ) << this << "in CachedImage::data(buffersize " << _buffer.buffer().size() <<", eof=" << eof << endl;#endif if ( !typeChecked ) { // don't attempt incremental loading if we have all the data already assert(!eof); formatType = QImageDecoder::formatName( (const uchar*)_buffer.buffer().data(), _buffer.size()); if ( formatType && strcmp( formatType, "PNG" ) == 0 ) formatType = 0; // Some png files contain multiple images, we want to show only the first one typeChecked = true; if ( formatType ) // movie format exists { imgSource = new ImageSource( _buffer.buffer()); m = new QMovie( imgSource, 8192 ); m->connectUpdate( this, SLOT( movieUpdated( const QRect &) )); m->connectStatus( this, SLOT( movieStatus(int))); m->connectResize( this, SLOT( movieResize( const QSize& ) ) ); } } if ( imgSource ) { imgSource->setEOF(eof); imgSource->maybeReady(); } if(eof) { // QMovie currently doesn't support all kinds of image formats // so we need to use a QPixmap here when we finished loading the complete // picture and display it then all at once. if(typeChecked && !formatType) {#ifdef CACHE_DEBUG kdDebug(6060) << "CachedImage::data(): reloading as pixmap:" << endl;#endif p = new QPixmap; { QBuffer buffer(_buffer.buffer()); buffer.open(IO_ReadOnly); QImageIO io( &buffer, 0 ); io.setGamma(2.2); // hardcoded "reasonable value" bool result = io.read(); if (result) p->convertFromImage(io.image(), 0); } // set size of image.#ifdef CACHE_DEBUG kdDebug(6060) << "CachedImage::data(): image is null: " << p->isNull() << endl;#endif if(p->isNull()) { m_hadError = true; do_notify(pixmap(), QRect(0, 0, 16, 16)); // load "broken image" icon } else do_notify(*p, p->rect()); for (QPtrDictIterator<CachedObjectClient> it( m_clients ); it.current();) it()->notifyFinished( this ); m_status = Cached; //all done } }}void CachedImage::finish(){ Status oldStatus = m_status; CachedObject::finish(); if ( oldStatus != m_status ) { const QPixmap &pm = pixmap(); do_notify( pm, pm.rect() ); } QSize s = pixmap_size(); setSize( s.width() * s.height() * 2);}void CachedImage::error( int /*err*/, const char* /*text*/ ){ clear(); typeChecked = true; m_hadError = true; m_loading = false; do_notify(pixmap(), QRect(0, 0, 16, 16)); for (QPtrDictIterator<CachedObjectClient> it( m_clients ); it.current();) it()->notifyFinished(this);}// ------------------------------------------------------------------------------------------Request::Request(DocLoader* dl, CachedObject *_object, bool _incremental){ object = _object; object->setRequest(this); incremental = _incremental; m_docLoader = dl;}Request::~Request(){ object->setRequest(0);}// ------------------------------------------------------------------------------------------DocLoader::DocLoader(KHTMLPart* part, DocumentImpl* doc){ m_cachePolicy = KIO::CC_Verify; m_expireDate = 0; m_creationDate = time(0); m_bautoloadImages = true; m_showAnimations = KHTMLSettings::KAnimationEnabled; m_part = part; m_doc = doc; Cache::docloader->append( this );}DocLoader::~DocLoader(){ Cache::loader()->cancelRequests( this ); Cache::docloader->remove( this );}void DocLoader::setCacheCreationDate(time_t _creationDate){ if (_creationDate) m_creationDate = _creationDate; else m_creationDate = time(0); // Now}void DocLoader::setExpireDate(time_t _expireDate, bool relative){ if (relative) m_expireDate = _expireDate + m_creationDate; // Relative date else m_expireDate = _expireDate; // Absolute date#ifdef CACHE_DEBUG kdDebug(6061) << "docLoader: " << m_expireDate - time(0) << " seconds left until reload required.\n";#endif}void DocLoader::insertCachedObject( CachedObject* o ) const{ if ( m_docObjects.find(o) ) return; m_docObjects.insert( o, o ); if ( m_docObjects.count() > 3 * m_docObjects.size() ) m_docObjects.resize(khtml::nextSeed( m_docObjects.size() ) );}bool DocLoader::needReload(CachedObject *existing, const QString& fullURL){ bool reload = false; if (m_cachePolicy == KIO::CC_Verify) { if (!m_reloadedURLs.contains(fullURL)) { if (existing && existing->isExpired()) { Cache::removeCacheEntry(existing); m_reloadedURLs.append(fullURL); reload = true; } } } else if ((m_cachePolicy == KIO::CC_Reload) || (m_cachePolicy == KIO::CC_Refresh)) { if (!m_reloadedURLs.contains(fullURL)) { if (existing) { Cache::removeCacheEntry(existing); } m_reloadedURLs.append(fullURL); reload = true; } } return reload;}#define DOCLOADER_SECCHECK(doRedirectCheck) \ KURL fullURL (m_doc->completeURL( url.string() )); \ if ( !fullURL.isValid() || \ ( m_part && m_part->onlyLocalReferences() && fullURL.protocol() != "file" && fullURL.protocol() != "data") || \ doRedirectCheck && ( kapp && m_doc && !kapp->authorizeURLAction("redirect", m_doc->URL(), fullURL))) \ return 0L;CachedImage *DocLoader::requestImage( const DOM::DOMString &url){ DOCLOADER_SECCHECK(true); CachedImage* i = Cache::requestObject<CachedImage, CachedObject::Image>( this, fullURL, 0); if (i && i->status() == CachedObject::Unknown && autoloadImages()) Cache::loader()->load(this, i, true); return i;}CachedCSSStyleSheet *DocLoader::requestStyleSheet( const DOM::DOMString &url, const QString& charset, const char *accept, bool userSheet ){ DOCLOADER_SECCHECK(!userSheet); CachedCSSStyleSheet* s = Cache::requestObject<CachedCSSStyleSheet, CachedObject::CSSStyleSheet>( this, fullURL, accept ); if ( s && !charset.isEmpty() ) { s->setCharset( charset ); } return s;}CachedScript *DocLoader::requestScript( const DOM::DOMString &url, const QString& charset){ DOCLOADER_SECCHECK(true); if ( ! KHTMLFactory::defaultHTMLSettings()->isJavaScriptEnabled(fullURL.host()) || KHTMLFactory::defaultHTMLSettings()->isAdFiltered(fullURL.url())) return 0L; CachedScript* s = Cache::requestObject<CachedScript, CachedObject::Script>( this, fullURL, 0 ); if ( s && !charset.isEmpty() ) s->setCharset( charset ); return s;}#undef DOCLOADER_SECCHECKvoid DocLoader::setAutoloadImages( bool enable ){ if ( enable == m_bautoloadImages ) return; m_bautoloadImages = enable; if ( !m_bautoloadImages ) return; for ( QPtrDictIterator<CachedObject> it( m_docObjects ); it.current(); ++it ) if ( it.current()->type() == CachedObject::Image ) { CachedImage *img = const_cast<CachedImage*>( static_cast<const CachedImage *>( it.current()) ); CachedObject::Status status = img->status(); if ( status != CachedObject::Unknown ) continue; Cache::loader()->load(this, img, true); }}void DocLoader::setShowAnimations( KHTMLSettings::KAnimationAdvice showAnimations ){ if ( showAnimations == m_showAnimations ) return; m_showAnimations = showAnimations; for ( QPtrDictIterator<CachedObject> it( m_docObjects ); it.current(); ++it ) if ( it.current()->type() == CachedObject::Image ) { CachedImage *img = const_cast<CachedImage*>( static_cast<const CachedImage *>( it.current() ) ); img->setShowAnimations( m_showAnimations ); }}// ------------------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -