[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gzz-commits] gzz/gfx/libimagecache ImageCache.cxx ImageCache...
From: |
Tero Mäyränen |
Subject: |
[Gzz-commits] gzz/gfx/libimagecache ImageCache.cxx ImageCache... |
Date: |
Fri, 13 Sep 2002 10:35:37 -0400 |
CVSROOT: /cvsroot/gzz
Module name: gzz
Changes by: Tero Mäyränen <address@hidden> 02/09/13 10:35:37
Modified files:
gfx/libimagecache: ImageCache.cxx ImageCache.hxx
Log message:
Changed ImageCache to use STL list and cache only one level of detail.
The
level of detail will gradually drop when the image is not being used.
CVSWeb URLs:
http://savannah.gnu.org/cgi-bin/viewcvs/gzz/gzz/gfx/libimagecache/ImageCache.cxx.diff?tr1=1.1&tr2=1.2&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gzz/gzz/gfx/libimagecache/ImageCache.hxx.diff?tr1=1.1&tr2=1.2&r1=text&r2=text
Patches:
Index: gzz/gfx/libimagecache/ImageCache.cxx
diff -c gzz/gfx/libimagecache/ImageCache.cxx:1.1
gzz/gfx/libimagecache/ImageCache.cxx:1.2
*** gzz/gfx/libimagecache/ImageCache.cxx:1.1 Wed Sep 11 07:16:26 2002
--- gzz/gfx/libimagecache/ImageCache.cxx Fri Sep 13 10:35:37 2002
***************
*** 4,318 ****
//---------------------------------------------------------------------------
! void on_loader_frame_done(GdkPixbufLoader *loader, gpointer arg1,
gpointer user_data) {
! ImageCache *imageCache =
! (ImageCache *)gtk_object_get_user_data(GTK_OBJECT(loader));
! imageCache->loaderImageDone((CachedURX *)user_data);
}
! //---------------------------------------------------------------------------
!
! CachedURX::CachedURX() {
! loader = NULL;
! }
!
! CachedURX::~CachedURX() {
! if (loader != NULL) delete loader;
! }
! CachedLOD *CachedURX::getCachedLOD(int lod) {
! return cachedLODs[lod];
}
! GdkPixbuf *CachedURX::getLoaderPixbuf() {
! return (loader == NULL ? NULL : gdk_pixbuf_loader_get_pixbuf(loader));
! }
! void CachedURX::setCachedLOD(int lod, CachedLOD *cl) {
! if (cl == NULL) cachedLODs.erase(lod);
! else cachedLODs[lod] = cl;
! }
! void CachedURX::write(char *data, int len, ImageCache *imageCache) {
if (loader == NULL) {
loader = gdk_pixbuf_loader_new();
! gtk_object_set_user_data(GTK_OBJECT(loader), imageCache);
gtk_signal_connect(GTK_OBJECT(loader), "frame-done",
GTK_SIGNAL_FUNC(on_loader_frame_done), this);
! }
! gdk_pixbuf_loader_write(loader, (guchar *)data, len);
! }
! void CachedURX::closeLoader() {
! if (loader != NULL) {
! gdk_pixbuf_loader_close(loader);
! loader = NULL;
}
}
! //---------------------------------------------------------------------------
! void CachedLOD::createScaled(GdkPixbuf *from, double scale) {
! int orig_width = gdk_pixbuf_get_width (from);
! int orig_height = gdk_pixbuf_get_height(from);
! int width = (int)(scale * orig_width ); if (width < 1) width = 1;
! int height = (int)(scale * orig_height); if (height < 1) height = 1;
! pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8, width, height);
! gdk_pixbuf_ref(pixbuf);
! gdk_pixbuf_scale(from, pixbuf, 0, 0, width, height, 0, 0,
! scale, scale, GDK_INTERP_BILINEAR);
! size = width*height*4;
! }
!
! CachedLOD::CachedLOD(int newLOD, CachedURX *cu, gboolean final) {
! next = NULL; prev = NULL;
!
! lod = newLOD;
! cachedURX = cu;
! createScaled(cu->getLoaderPixbuf(), 1.0 / (1 << lod));
! fullyLoaded = final;
! cachedURX->setCachedLOD(lod, this);
}
! CachedLOD::CachedLOD(int newLOD, CachedLOD *cl) {
! next = NULL; prev = NULL;
!
! cachedURX = cl->getCachedURX();
! lod = newLOD;
! int orig_lod = cl->getLOD();
! int lod_dif = orig_lod - lod;
! if (lod_dif >= 0) {
! createScaled(cl->pixbuf, 1.0 / (1 << lod_dif));
! fullyLoaded = cl->isFullyLoaded();
! }
! else {
! createScaled(cl->pixbuf, 1 << (-lod_dif));
! fullyLoaded = false;
! }
! cachedURX->setCachedLOD(lod, this);
! }
! CachedLOD::~CachedLOD() {
! cachedURX->setCachedLOD(lod, NULL);
! gdk_pixbuf_unref(pixbuf);
}
! CachedLOD *CachedLOD::getNext() { return next; }
! CachedLOD *CachedLOD::getPrev() { return prev; }
! void CachedLOD::setNext(CachedLOD *cl) { next = cl; }
! void CachedLOD::setPrev(CachedLOD *cl) { prev = cl; }
! GdkPixbuf *CachedLOD::getPixbuf() { return pixbuf; }
! int CachedLOD::getSize() { return size; }
! CachedURX *CachedLOD::getCachedURX() { return cachedURX; }
! int CachedLOD::getLOD() { return lod; }
! gboolean CachedLOD::isFullyLoaded() { return fullyLoaded; }
! void CachedLOD::update(GdkPixbuf *from, gboolean final) {
! if ((pixbuf == NULL) || fullyLoaded) return;
! int width = gdk_pixbuf_get_width (pixbuf);
! int height = gdk_pixbuf_get_height(pixbuf);
! double scale = 1.0 / (1 << lod);
! gdk_pixbuf_scale(from, pixbuf, 0, 0, width, height, 0, 0,
! scale, scale, GDK_INTERP_BILINEAR);
! fullyLoaded = final;
}
//---------------------------------------------------------------------------
ImageCache::ImageCache() {
- recentlyUsedLODs = NULL;
size = 0;
! maxSize = 10*1024*1024;
! loaderPixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, false, 8, 16, 16);
! gdk_pixbuf_ref(loaderPixbuf);
}
ImageCache::~ImageCache() {
! CachedURX *cu;
! CachedLOD *cl = recentlyUsedLODs;
! CachedLOD *oldcl;
! while (cl != NULL) {
! cu = cl->getCachedURX();
! cu->closeLoader();
! oldcl = cl;
! cl = cl->getNext();
! delete oldcl;
! }
! cachedURXs.clear();
! gdk_pixbuf_unref(loaderPixbuf);
! }
! /**
! * Create new level of detail from another level
! * and put it on top of the recentlyUsedLODs list.
! */
! CachedLOD *ImageCache::createCachedLOD(int lod, CachedLOD *oldcl) {
! CachedLOD *cl = new CachedLOD(lod, oldcl);
! size += cl->getSize();
! cl->setNext(recentlyUsedLODs);
! cl->getNext()->setPrev(cl);
! recentlyUsedLODs = cl;
! return cl;
! }
!
! /**
! * Create a new level of detail from a (LOD 0) pixbuf
! * and put it on top of the recentlyUsedLODs list.
! */
! CachedLOD *ImageCache::createCachedLOD(int lod, CachedURX *cu,
! gboolean final) {
! CachedLOD *cl = new CachedLOD(lod, cu, final);
! size += cl->getSize();
! cl->setNext(recentlyUsedLODs);
! cl->getNext()->setPrev(cl);
! recentlyUsedLODs = cl;
! return cl;
! }
!
! /**
! * Move a level of detail to the top of the recentlyUsedLODs list.
! */
! void ImageCache::useCachedLOD(CachedLOD *cl) {
! if (cl->getNext() != NULL) cl->getNext()->setPrev(cl->getPrev());
! if (cl->getPrev() != NULL) cl->getPrev()->setNext(cl->getNext());
! cl->setPrev(NULL);
! cl->setNext(recentlyUsedLODs);
! cl->getNext()->setPrev(cl);
! recentlyUsedLODs = cl;
}
GdkPixbuf *ImageCache::getPixbuf(string urx, int lod) {
! CachedLOD *wantedLOD;
! CachedLOD *gotLOD;
! CachedURX *wantedURX = cachedURXs[urx];
!
! //-----------------------------------------------------------------
! // If the wanted URX was not found...
! //-----------------------------------------------------------------
! if (wantedURX == NULL) {
! // Start loading!
! // backgroundLoader.startLoading(urx); XXXXXXX
! return loaderPixbuf;
! }
! //-----------------------------------------------------------------
! // The wanted URX was found, how about the Level of Detail?
! //-----------------------------------------------------------------
! wantedLOD = wantedURX->getCachedLOD(lod);
! //-----------------------------------------------------------------
! // If the wanted LOD was not found...
! //-----------------------------------------------------------------
! if (wantedLOD == NULL) {
! // See if it can be resized from another LOD
! // Try to find one that is bigger, and fully loaded...
! for (int tryLOD = lod-1; tryLOD >= 0; tryLOD--) {
! gotLOD = wantedURX->getCachedLOD(tryLOD);
! if ((gotLOD != NULL) && (gotLOD->isFullyLoaded())) {
! wantedLOD = createCachedLOD(lod, gotLOD);
! return wantedLOD->getPixbuf();
! }
! }
! // There was no fully loaded one, so try the pixbufloader:
! GdkPixbuf *pb = wantedURX->getLoaderPixbuf();
! if (pb != NULL) {
! wantedLOD = createCachedLOD(lod, wantedURX, false);
! return wantedLOD->getPixbuf();
! }
! // Finally check the few next levels for smaller versions
! // if one is found, copy it and start loading a better one
! for (int tryLOD = lod+1; tryLOD < lod+6; tryLOD++) {
! gotLOD = wantedURX->getCachedLOD(tryLOD);
! if ((gotLOD != NULL) && (gotLOD->isFullyLoaded())) {
! wantedLOD = createCachedLOD(lod, gotLOD);
! // backgroundLoader.startLoading(urx); XXXXXXX
! return wantedLOD->getPixbuf();
! }
! }
! return loaderPixbuf;
! }
! //-----------------------------------------------------------------
! // If the wanted LOD is not fully loaded:
! //-----------------------------------------------------------------
! if (!wantedLOD->isFullyLoaded()) {
! // Check if it's being loaded in the pixbufloader:
! GdkPixbuf *pb = wantedURX->getLoaderPixbuf();
! if (pb != NULL) {
! wantedLOD->update(pb, false);
! useCachedLOD(wantedLOD);
! return wantedLOD->getPixbuf();
! }
! // See if it can be resized from another LOD:
! for (int tryLOD = lod-1; tryLOD >= 0; tryLOD--) {
! gotLOD = wantedURX->getCachedLOD(tryLOD);
! if ((gotLOD != NULL) && (gotLOD->isFullyLoaded())) {
! wantedLOD->update(gotLOD->getPixbuf(), true);
! useCachedLOD(wantedLOD);
! return wantedLOD->getPixbuf();
! }
! }
! // The pixbufloader's area has not been prepared yet?
! return loaderPixbuf;
! }
! //-----------------------------------------------------------------
! // The wanted LOD was fully loaded:
! //-----------------------------------------------------------------
! useCachedLOD(wantedLOD); // move to top of recentlyUsedLODs
! return wantedLOD->getPixbuf();
! //-----------------------------------------------------------------
! }
! int ImageCache::getWidth(string urx, int lod) {
! return gdk_pixbuf_get_width(getPixbuf(urx,lod));
}
! int ImageCache::getHeight(string urx, int lod) {
! return gdk_pixbuf_get_height(getPixbuf(urx,lod));
}
! int *ImageCache::getPixels(string urx, int lod) {
! return (int *)gdk_pixbuf_get_pixels(getPixbuf(urx,lod));
! }
! void ImageCache::write(string urx, char *data, int len) {
! CachedURX *wantedURX = cachedURXs[urx];
! if (wantedURX == NULL) {
! wantedURX = new CachedURX();
! cachedURXs[urx] = wantedURX;
! }
! wantedURX->write(data, len, this);
! }
! void ImageCache::loaderImageDone(CachedURX *cu) {
! CachedLOD *cl = cu->getCachedLOD(0);
! if (cl == NULL) {
! cl = createCachedLOD(0, cu, true);
! }
! else {
! cl->update(cu->getLoaderPixbuf(), true);
! useCachedLOD(cl);
}
! cu->closeLoader();
}
//---------------------------------------------------------------------------
--- 4,223 ----
//---------------------------------------------------------------------------
! void on_loader_area_prepared(GdkPixbufLoader *loader, gpointer arg1,
gpointer user_data) {
! ((CachedImage *)user_data)->loaderPrepared();
}
! void on_loader_frame_done(GdkPixbufLoader *loader, gpointer arg1,
! gpointer user_data) {
! ((CachedImage *)user_data)->loaderDone();
}
! //---------------------------------------------------------------------------
! #define START_PIXBUF_BACKGROUND_LOADER ((GdkPixbuf *)(-1))
! CachedImage::CachedImage() {
! loader = NULL;
! requestedLOD = -1;
! pixbuf = NULL;
! pixbufLOD = -1;
! lastSize = 0;
! currentSize = 0;
! }
!
! CachedImage::~CachedImage() {
! closeLoader();
! if (pixbuf != NULL) gdk_pixbuf_unref(pixbuf);
! }
!
! GdkPixbuf *CachedImage::getPixbuf(int lod) {
! if (lod < 0) lod = 0;
! if ((pixbuf != NULL) && (lod >= pixbufLOD)) {
! return pixbuf;
! }
if (loader == NULL) {
+ requestedLOD = lod;
loader = gdk_pixbuf_loader_new();
! if (loader == NULL) return NULL;
gtk_signal_connect(GTK_OBJECT(loader), "frame-done",
GTK_SIGNAL_FUNC(on_loader_frame_done), this);
! gtk_signal_connect(GTK_OBJECT(loader), "area-prepared",
! GTK_SIGNAL_FUNC(on_loader_area_prepared), this);
! return START_PIXBUF_BACKGROUND_LOADER;
}
+ if (lod < requestedLOD) requestedLOD = lod;
+
+ GdkPixbuf *pb = gdk_pixbuf_loader_get_pixbuf(loader);
+ return (pb == NULL ? pixbuf : pb);
}
! int CachedImage::write(char *data, int len) {
! if (loader == NULL) return -1;
! gdk_pixbuf_loader_write(loader, (guchar *)data, len);
! return 0;
! }
! void CachedImage::dropLOD() {
! closeLoader();
! if (pixbuf == NULL) return;
! int dest_width = gdk_pixbuf_get_width (pixbuf) >> 1;
! int dest_height = gdk_pixbuf_get_height(pixbuf) >> 1;
! if (dest_width == 0) dest_width = 1;
! if (dest_height == 0) dest_height = 1;
! GdkPixbuf *dest = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8,
! dest_width, dest_height);
! gdk_pixbuf_scale(pixbuf, dest, 0, 0, dest_width, dest_height, 0, 0,
! 0.5, 0.5, GDK_INTERP_BILINEAR);
! gdk_pixbuf_unref(pixbuf);
! pixbuf = dest;
! gdk_pixbuf_ref(pixbuf);
! --pixbufLOD;
! currentSize = dest_width * dest_height * 4;
! gtk_object_set_user_data(GTK_OBJECT(pixbuf), (gpointer)pixbufLOD);
}
! void CachedImage::loaderPrepared() {
! if ((pixbuf == NULL) || (loader == NULL)) return;
! GdkPixbuf *dest = gdk_pixbuf_loader_get_pixbuf(loader);
! double scale = 1 << pixbufLOD;
! gdk_pixbuf_scale(pixbuf, dest, 0, 0,
! gdk_pixbuf_get_width(dest), gdk_pixbuf_get_height(dest),
! 0, 0, scale, scale, GDK_INTERP_BILINEAR);
! gtk_object_set_user_data(GTK_OBJECT(dest), (gpointer)0);
}
! void CachedImage::loaderDone() {
! if (loader == NULL) return;
! if (pixbuf != NULL) gdk_pixbuf_unref(pixbuf);
! GdkPixbuf *src = gdk_pixbuf_loader_get_pixbuf(loader);
! int dest_width = gdk_pixbuf_get_width (src) >> requestedLOD;
! int dest_height = gdk_pixbuf_get_height(src) >> requestedLOD;
! if (dest_width == 0) dest_width = 1;
! if (dest_height == 0) dest_height = 1;
! double scale = 1.0 / (1 << requestedLOD);
! pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8,
! dest_width, dest_height);
! gdk_pixbuf_ref(pixbuf);
! gdk_pixbuf_scale(src, pixbuf, 0, 0, dest_width, dest_height, 0, 0,
! scale, scale, GDK_INTERP_BILINEAR);
! pixbufLOD = requestedLOD;
! currentSize = dest_width * dest_height * 4;
! gtk_object_set_user_data(GTK_OBJECT(pixbuf), (gpointer)pixbufLOD);
! closeLoader();
! }
! void CachedImage::closeLoader() {
! if (loader != NULL) {
! gdk_pixbuf_loader_close(loader);
! loader = NULL;
! }
! }
! int CachedImage::getSizeChange() {
! int change = currentSize - lastSize;
! lastSize = currentSize;
! return change;
! }
! int CachedImage::getCurrentSize() {
! return currentSize;
}
//---------------------------------------------------------------------------
ImageCache::ImageCache() {
size = 0;
! loading = gdk_pixbuf_new(GDK_COLORSPACE_RGB, false, 8, 16, 16);
! gdk_pixbuf_ref(loading);
}
ImageCache::~ImageCache() {
! imageByUrx.clear();
! urxByImage.clear();
!
! list<CachedImage *>::iterator iter;
! for (iter = recentlyUsedImages.begin();
! iter != recentlyUsedImages.end();
! ++iter) {
!
! delete *iter;
! }
! recentlyUsedImages.clear();
! gdk_pixbuf_unref(loading);
}
GdkPixbuf *ImageCache::getPixbuf(string urx, int lod) {
! CachedImage *ci = imageByUrx[urx];
! if (ci == NULL) {
! ci = new CachedImage();
! imageByUrx[urx] = ci;
! urxByImage[ci] = urx;
! }
! else recentlyUsedImages.remove(ci);
! recentlyUsedImages.push_front(ci);
! size += ci->getSizeChange();
! GdkPixbuf *pb = ci->getPixbuf(lod);
! if (pb == START_PIXBUF_BACKGROUND_LOADER) {
! //backgroundLoader->startLoading(urx);
! pb = ci->getPixbuf(lod);
! }
! return (pb == NULL ? loading : pb);
}
! int ImageCache::write(string urx, char *data, int len) {
! CachedImage *ci = imageByUrx[urx];
! return (ci == NULL ? -1 : ci->write(data, len));
}
! int ImageCache::cropToSize(int maxSize) {
! CachedImage *ci;
! int sizeChange;
! while ((size >= maxSize) && (!recentlyUsedImages.empty())) {
! ci = recentlyUsedImages.back();
! recentlyUsedImages.pop_back();
! ci->dropLOD();
! sizeChange = ci->getSizeChange();
! if (sizeChange == 0) {
! string urx = urxByImage[ci];
! urxByImage.erase(ci);
! imageByUrx.erase(urx);
! size -= ci->getCurrentSize();
! delete ci;
! }
! else {
! size += sizeChange;
! recentlyUsedImages.push_front(ci);
! }
}
! return size;
}
//---------------------------------------------------------------------------
Index: gzz/gfx/libimagecache/ImageCache.hxx
diff -c gzz/gfx/libimagecache/ImageCache.hxx:1.1
gzz/gfx/libimagecache/ImageCache.hxx:1.2
*** gzz/gfx/libimagecache/ImageCache.hxx:1.1 Wed Sep 11 07:16:26 2002
--- gzz/gfx/libimagecache/ImageCache.hxx Fri Sep 13 10:35:37 2002
***************
*** 6,11 ****
--- 6,12 ----
#include <string>
#include <map>
+ #include <list>
#include <gtk/gtk.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
***************
*** 15,92 ****
using std::string;
using std::map;
! class CachedLOD;
! class ImageCache;
!
! class CachedURX {
GdkPixbufLoader *loader;
! map<int,CachedLOD *> cachedLODs;
public:
! CachedURX();
! ~CachedURX();
! CachedLOD *getCachedLOD(int lod);
! GdkPixbuf *getLoaderPixbuf();
! void setCachedLOD(int lod, CachedLOD *cl);
! void write(char *data, int len, ImageCache *imageCache);
void closeLoader();
! };
!
! class CachedLOD {
! private:
! CachedLOD *prev;
! CachedLOD *next;
! GdkPixbuf *pixbuf;
! CachedURX *cachedURX;
! int lod;
! int size;
! gboolean fullyLoaded;
!
! void createScaled(GdkPixbuf *from, double scale);
! public:
! CachedLOD(int newLOD, CachedURX *cu, gboolean final);
! CachedLOD(int newLOD, CachedLOD *cl);
! ~CachedLOD();
!
! CachedLOD *getNext();
! CachedLOD *getPrev();
! void setNext(CachedLOD *cl);
! void setPrev(CachedLOD *cl);
!
! GdkPixbuf *getPixbuf();
! int getSize();
! CachedURX *getCachedURX();
! int getLOD();
! gboolean isFullyLoaded();
! void update(GdkPixbuf *from, gboolean final);
};
class ImageCache {
private:
! GdkPixbuf *loaderPixbuf;
! map<string,CachedURX *> cachedURXs;
! CachedLOD *recentlyUsedLODs;
int size;
- int maxSize;
-
- CachedLOD *createCachedLOD(int lod, CachedURX *cu, gboolean final);
- CachedLOD *createCachedLOD(int lod, CachedLOD *oldcl);
- void useCachedLOD(CachedLOD *cl);
public:
ImageCache();
~ImageCache();
GdkPixbuf *getPixbuf(string urx, int lod);
- int getWidth(string urx, int lod);
- int getHeight(string urx, int lod);
- int *getPixels(string urx, int lod);
! void write(string urx, char *data, int n);
! void loaderImageDone(CachedURX *cu);
};
-
}
#endif
--- 16,62 ----
using std::string;
using std::map;
+ using std::list;
! class CachedImage {
! private:
GdkPixbufLoader *loader;
! int requestedLOD;
! GdkPixbuf *pixbuf;
! int pixbufLOD;
! int lastSize;
! int currentSize;
public:
! CachedImage();
! ~CachedImage();
! GdkPixbuf *getPixbuf(int lod);
! int write(char *data, int len);
! void dropLOD();
! void loaderPrepared();
! void loaderDone();
void closeLoader();
! int getSizeChange();
! int getCurrentSize();
};
class ImageCache {
private:
! GdkPixbuf *loading;
! map<string,CachedImage *> imageByUrx;
! map<CachedImage *,string> urxByImage;
! list<CachedImage *> recentlyUsedImages;
int size;
public:
ImageCache();
~ImageCache();
GdkPixbuf *getPixbuf(string urx, int lod);
! int write(string urx, char *data, int n);
! int cropToSize(int maxSize);
};
}
#endif