📄 loader.cpp
字号:
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() ) { bg = new QPixmap(w, h); QPixmap pix = pixmap(); 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 = qRgba( 0, 0, 0, 0xFF ); } else bgColor= newc.rgb(); return *bg; } return r;}const QPixmap &CachedImage::pixmap( ) const{ if(errorOccured) return *Cache::brokenPixmap; 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; 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){ // do not chang the hack with the update list unless you know what you are doing. // When removing this hack, directory listings as eg produced by apache will // get *really* slow QList<CachedObjectClient> updateList; CachedObjectClient *c; for ( c = m_clients.first(); c != 0; c = m_clients.next() ) {#ifdef CACHE_DEBUG kdDebug( 6060 ) << "found a client to update: " << c << endl;#endif bool manualUpdate = false; // set the pixmap, dont update yet. c->setPixmap( p, r, this, &manualUpdate); if (manualUpdate) updateList.append(c); } for ( c = updateList.first(); c != 0; c = updateList.next() ) { bool manualUpdate = true; // Update! // Actually we want to do c->updateSize() // This is a terrible hack which does the same. // updateSize() does not exist in CachecObjectClient only // in RenderBox() c->setPixmap( p, r, this, &manualUpdate); }}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 if((status == QMovie::EndOfFrame) || (status == QMovie::EndOfMovie)) { // 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(); 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) { // the movie has ended and it doesn't loop nor is it an animation, // so there is no need to keep the buffer in memory if(imgSource && m->frameNumber() == 1) setShowAnimations( false ); CachedObjectClient *c; for ( c = m_clients.first(); c != 0; c = m_clients.next() ) c->notifyFinished(this); }#ifdef CACHE_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()); }}void CachedImage::movieResize(const QSize& /*s*/){// do_notify(m->framePixmap(), QRect());}void CachedImage::setShowAnimations( bool enable ){ if ( !enable && m ) { 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& ) ) ); delete m; m = 0; imgSource = 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; m_size = 0; // No need to delete imageSource - QMovie does it for us imgSource = 0;}void CachedImage::data ( QBuffer &_buffer, bool eof ){#ifdef CACHE_DEBUG kdDebug( 6060 ) << this << "in CachedImage::data(buffersize " << _buffer.buffer().size() <<", eof=" << eof << endl;#endif if ( !typeChecked ) { formatType = QImageDecoder::formatName( (const uchar*)_buffer.buffer().data(), _buffer.size()); 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( _buffer.buffer() ); // set size of image.#ifdef CACHE_DEBUG kdDebug(6060) << "CachedImage::data(): image is null: " << p->isNull() << endl;#endif if(p->isNull()) { errorOccured = true; do_notify(pixmap(), QRect(0, 0, 16, 16)); // load "broken image" icon } else do_notify(*p, p->rect()); } QSize s = pixmap_size(); m_size = s.width() * s.height() * 2; }}void CachedImage::error( int /*err*/, const char */*text*/ ){#ifdef CACHE_DEBUG kdDebug(6060) << "CahcedImage::error" << endl;#endif clear(); typeChecked = true; errorOccured = true; do_notify(pixmap(), QRect(0, 0, 16, 16));}// ------------------------------------------------------------------------------------------Request::Request(CachedObject *_object, const DOM::DOMString &baseURL, bool _incremental){ object = _object; object->setRequest(this); incremental = _incremental; m_baseURL = baseURL;}Request::~Request(){ object->setRequest(0);}// ------------------------------------------------------------------------------------------DocLoader::DocLoader(KHTMLPart* part){ m_reloading = false; m_expireDate = 0; m_bautoloadImages = true; m_showAnimations = true; m_part = part; Cache::docloader->append( this );}DocLoader::~DocLoader(){ Cache::docloader->remove( this );}void DocLoader::setExpireDate(int _expireDate){ m_expireDate = _expireDate;}CachedImage *DocLoader::requestImage( const DOM::DOMString &url, const DOM::DOMString &baseUrl){ KURL fullURL = Cache::completeURL( url, baseUrl ); if ( m_part && m_part->onlyLocalReferences() && fullURL.protocol() != "file") return 0; if (m_reloading) { if (!m_reloadedURLs.contains(fullURL.url())) { CachedObject *existing = Cache::cache->find(fullURL.url()); if (existing) Cache::removeCacheEntry(existing); m_reloadedURLs.append(fullURL.url()); return Cache::requestImage(this, url,baseUrl,true,m_expireDate); } } CachedImage* ci = Cache::requestImage(this, url,baseUrl,false, m_expireDate); return ci;}CachedCSSStyleSheet *DocLoader::requestStyleSheet( const DOM::DOMString &url, const DOM::DOMString &baseUrl, const QString& charset){ KURL fullURL = Cache::completeURL( url, baseUrl ); if ( m_part && m_part->onlyLocalReferences() && fullURL.protocol() != "file") return 0; if (m_reloading) { if (!m_reloadedURLs.contains(fullURL.url())) { CachedObject *existing = Cache::cache->find(fullURL.url()); if (existing) Cache::removeCacheEntry(existing); m_reloadedURLs.append(fullURL.url()); return Cache::requestStyleSheet(this, url,baseUrl,true,m_expireDate, charset); } } return Cache::requestStyleSheet(this, url,baseUrl,false,m_expireDate, charset);}CachedScript *DocLoader::requestScript( const DOM::DOMString &url, const DOM::DOMString &baseUrl, const QString& charset){ KURL fullURL = Cache::completeURL( url, baseUrl ); if ( m_part && m_part->onlyLocalReferences() && fullURL.protocol() != "file") return 0; if (m_reloading) { if (!m_reloadedURLs.contains(fullURL.url())) { CachedObject *existing = Cache::cache->find(fullURL.url()); if (existing) Cache::removeCacheEntry(existing); m_reloadedURLs.append(fullURL.url()); return Cache::requestScript(this, url,baseUrl,true,m_expireDate, charset); } } return Cache::requestScript(this, url,baseUrl,false,m_expireDate, charset);}void DocLoader::setAutoloadImages( bool enable ){ if ( enable == m_bautoloadImages ) return; m_bautoloadImages = enable; if ( !m_bautoloadImages ) return; for ( const CachedObject* co=m_docObjects.first(); co; co=m_docObjects.next() ) if ( co->type() == CachedObject::Image ) { CachedImage *img = const_cast<CachedImage*>( static_cast<const CachedImage *>( co ) ); CachedObject::Status status = img->status(); if ( status != CachedObject::Unknown || status == CachedObject::Cached || status == CachedObject::Uncacheable || status == CachedObject::Pending ) continue; Cache::loader()->load(img, img->baseURL(), true); }}void DocLoader::setReloading( bool enable ){ m_reloading = enable;}void DocLoader::setShowAnimations( bool enable ){ if ( enable == m_showAnimations ) return; const CachedObject* co; for ( co=m_docObjects.first(); co; co=m_docObjects.next() ) if ( co->type() == CachedObject::Image ) { CachedImage *img = const_cast<CachedImage*>( static_cast<const CachedImage *>( co ) ); img->setShowAnimations( enable ); }}void DocLoader::removeCachedObject( CachedObject* o ) const{ m_docObjects.removeRef( o );}// ------------------------------------------------------------------------------------------Loader::Loader() : QObject(){ m_requestsPending.setAutoDelete( true ); m_requestsLoading.setAutoDelete( true );}Loader::~Loader(){}void Loader::load(CachedObject *object, const DOMString &baseURL, bool incremental){ Request *req = new Request(object, baseURL, incremental); m_requestsPending.append(req); servePendingRequests();}void Loader::servePendingRequests(){ if ( m_requestsPending.count() == 0 ) return; // get the first pending request Request *req = m_requestsPending.take(0);#ifdef CACHE_DEBUG kdDebug( 6060 ) << "starting Loader url=" << req->object->url().string() << endl;#endif KIO::TransferJob* job = KIO::get( req->object->url().string(), req->object->reload(), false /*no GUI*/); if (!req->object->accept().isEmpty()) job->addMetaData("accept", req->object->accept()); job->addMetaData("referrer", req->m_baseURL.string()); connect( job, SIGNAL( result( KIO::Job * ) ), this, SLOT( slotFinished( KIO::Job * ) ) ); connect( job, SIGNAL( data( KIO::Job*, const QByteArray &)), SLOT( slotData( KIO::Job*, const QByteArray &))); KIO::Scheduler::scheduleJob( job );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -