diff --git a/HISTORY b/HISTORY index 7384352..b633002 100644 --- a/HISTORY +++ b/HISTORY @@ -103,3 +103,5 @@ Version 0.0.7 - fixed bug that global double vars are not working Version 0.0.8 + +- drawing ellipses antialiased with Cairo \ No newline at end of file diff --git a/Makefile b/Makefile index ace7d29..5fcf791 100644 --- a/Makefile +++ b/Makefile @@ -66,8 +66,9 @@ OBJS = $(PLUGIN).o \ libcore/pixmapcontainer.o \ libcore/fontmanager.o \ libcore/imagecache.o \ - libcore/helpers.o \ libcore/imageloader.o \ + libcore/imagecreator.o \ + libcore/helpers.o \ libcore/recfolderinfo.o \ libcore/extrecinfo.o \ libcore/timers.o \ diff --git a/libcore/imagecache.c b/libcore/imagecache.c index cfaf255..4d68722 100644 --- a/libcore/imagecache.c +++ b/libcore/imagecache.c @@ -3,9 +3,10 @@ #include #include #include -#include "imagecache.h" +#include "imagecreator.h" #include "../config.h" #include "helpers.h" +#include "imagecache.h" cMutex cImageCache::mutex; @@ -300,6 +301,37 @@ cImage *cImageCache::GetSkinpart(string name, int width, int height) { return NULL; } +void cImageCache::CacheEllipse(int id, int width, int height, tColor color, int quadrant) { + esyslog("skindesigner: caching ellipse %d, w %d, h %d, color %x, quadrant %d", id, width, height, color, quadrant); + GetEllipse(id, width, height, color, quadrant); +} + +cImage *cImageCache::GetEllipse(int id, int width, int height, tColor color, int quadrant) { + if (width < 1 || width > 1920 || height < 1 || height > 1080) + return NULL; + cMutexLock MutexLock(&mutex); + map::iterator hit = cairoImageCache.find(id); + if (hit != cairoImageCache.end()) { + return (cImage*)hit->second; + } else { + cImageCreator ic; + if (!ic.InitCairoImage(width, height)) + return NULL; + ic.DrawEllipse(color, quadrant); + cImage *ellipse = ic.GetImage(); + cairoImageCache.insert(pair(id, ellipse)); + hit = cairoImageCache.find(id); + if (hit != cairoImageCache.end()) { + return (cImage*)hit->second; + } + } + return NULL; +} + +/**************************************************************************************** +* PRIVATE FUNCTIONS +****************************************************************************************/ + bool cImageCache::LoadIcon(eImageType type, string name) { cString subdir(""); if (type == itMenuIcon) @@ -361,11 +393,17 @@ void cImageCache::Clear(void) { } channelLogoCache.clear(); - for(map::const_iterator it = skinPartsCache.begin(); it != skinPartsCache.end(); it++) { + for(map::const_iterator it = skinPartsCache.begin(); it != skinPartsCache.end(); it++) { cImage *img = (cImage*)it->second; delete img; } skinPartsCache.clear(); + + for(map::const_iterator it = cairoImageCache.begin(); it != cairoImageCache.end(); it++) { + cImage *img = (cImage*)it->second; + delete img; + } + cairoImageCache.clear(); } void cImageCache::Debug(bool full) { diff --git a/libcore/imagecache.h b/libcore/imagecache.h index 95148b2..4a26710 100644 --- a/libcore/imagecache.h +++ b/libcore/imagecache.h @@ -30,6 +30,9 @@ public: //skinparts void CacheSkinpart(string path, int width, int height); cImage *GetSkinpart(string name, int width, int height); + //Cairo Images + void CacheEllipse(int id, int width, int height, tColor color, int quadrant); + cImage *GetEllipse(int id, int width, int height, tColor color, int quadrant); //helpers void Clear(void); void Debug(bool full); @@ -46,6 +49,7 @@ private: map iconCache; map channelLogoCache; map skinPartsCache; + map cairoImageCache; bool LoadIcon(eImageType type, string name); bool LoadLogo(const cChannel *channel); bool LoadSeparatorLogo(string name); diff --git a/libcore/imagecreator.c b/libcore/imagecreator.c new file mode 100644 index 0000000..65eea04 --- /dev/null +++ b/libcore/imagecreator.c @@ -0,0 +1,202 @@ +#include "imagecreator.h" + +cImageCreator::cImageCreator(void) { + surface = NULL; + cr = NULL; +} + +cImageCreator::~cImageCreator() { + if (cr) + cairo_destroy (cr); + if (surface) + cairo_surface_destroy (surface); +} + +bool cImageCreator::InitCairoImage(int width, int height) { + this->width = width; + this->height = height; + if (width < 1 || height < 1 || width > 1920 || height > 1080) + return false; + surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); + cr = cairo_create(surface); + cairo_set_antialias(cr, CAIRO_ANTIALIAS_BEST); + return true; +} + +/********************************************************************************** +* Public Functions +**********************************************************************************/ + +///< 0 draws the entire ellipse +///< 1..4 draws only the first, second, third or fourth quadrant, respectively +///< 5..8 draws the right, top, left or bottom half, respectively +///< -1..-4 draws the inverted part of the given quadrant +///< If Quadrants is not 0, the coordinates are those of the actual area, not +///< the full circle! +void cImageCreator::DrawEllipse(tColor color, int quadrants) { + if (!cr || !surface) + return; + //center of the ellipse + double x, y; + //radius + double radius; + //start and stop angle (radian) + double arcStart, arcStop; + //scaling factors + double scaleX, scaleY; + //draw inverted ellipse + bool inverted; + + scaleX = width; + scaleY = height; + inverted = false; + + switch (quadrants) { + case 0: + x = 0.5; + y = 0.5; + radius = 0.5; + arcStart = 0.0; + arcStop = 2 * M_PI; + break; + case 1: + x = 0.0; + y = 1.0; + radius = 1.0; + arcStart = M_PI; + arcStop = 2 * M_PI; + break; + case 2: + x = 1.0; + y = 1.0; + radius = 1.0; + arcStart = M_PI; + arcStop = 2 * M_PI; + break; + case 3: + x = 1.0; + y = 0.0; + radius = 1.0; + arcStart = 0; + arcStop = M_PI; + break; + case 4: + x = 0.0; + y = 0.0; + radius = 1.0; + arcStart = 0; + arcStop = M_PI; + break; + case 5: + scaleX = 2 * width; + x = 0.0; + y = 0.5; + radius = 0.5; + arcStart = 0; + arcStop = 2* M_PI; + break; + case 6: + scaleY = 2 * height; + x = 0.5; + y = 0.5; + radius = 0.5; + arcStart = 0; + arcStop = 2* M_PI; + break; + case 7: + scaleX = 2 * width; + x = 0.5; + y = 0.5; + radius = 0.5; + arcStart = 0; + arcStop = 2* M_PI; + break; + case 8: + scaleY = 2 * height; + x = 0.5; + y = 0.0; + radius = 0.5; + arcStart = 0; + arcStop = 2* M_PI; + break; + case -1: + x = 0.0; + y = 1.0; + radius = 1.0; + arcStart = M_PI; + arcStop = 2* M_PI; + inverted = true; + break; + case -2: + x = 1.0; + y = 1.0; + radius = 1.0; + arcStart = M_PI; + arcStop = 2 * M_PI; + inverted = true; + break; + case -3: + x = 1.0; + y = 0.0; + radius = 1.0; + arcStart = 0; + arcStop = M_PI; + inverted = true; + break; + case -4: + x = 0.0; + y = 0.0; + radius = 1.0; + arcStart = 0; + arcStop = M_PI; + inverted = true; + break; + default: + x = 0.5; + y = 0.5; + radius = 0.5; + arcStart = 0.0; + arcStop = 2 * M_PI; + break; + } + + SetColor(color); + //Draw Background for inverted ellipses + if (inverted) { + cairo_rectangle(cr, 0.0, 0.0, width, height); + cairo_fill (cr); + cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); + } + //Draw Ellipse + cairo_scale(cr, scaleX, scaleY); + cairo_arc(cr, x, y, radius, arcStart, arcStop); + cairo_fill(cr); +} + +cImage *cImageCreator::GetImage(void) { + if (!cr || !surface) + NULL; + unsigned char *data = cairo_image_surface_get_data(surface); + cImage *image = new cImage(cSize(width, height), (tColor*)data); + return image; +} + +/********************************************************************************** +* Private Functions +**********************************************************************************/ + +void cImageCreator::SetColor(tColor color) { + if (!cr || !surface) + return; + tIndex tAlpha = (color & 0xFF000000) >> 24; + tIndex tRed = (color & 0x00FF0000) >> 16; + tIndex tGreen = (color & 0x0000FF00) >> 8; + tIndex tBlue = (color & 0x000000FF); + + double a = (int)tAlpha / (double)255; + double r = (int)tRed / (double)255; + double g = (int)tGreen / (double)255; + double b = (int)tBlue / (double)255; + + cairo_set_source_rgba(cr, r, g, b, a); +} diff --git a/libcore/imagecreator.h b/libcore/imagecreator.h new file mode 100644 index 0000000..b877a3f --- /dev/null +++ b/libcore/imagecreator.h @@ -0,0 +1,26 @@ +#ifndef __IMAGECREATOR_H +#define __IMAGECREATOR_H + +#include +#include +#include +#include + +using namespace std; + +class cImageCreator { +private: + int width; + int height; + cairo_surface_t *surface; + cairo_t *cr; + void SetColor(tColor color); +public: + cImageCreator(void); + virtual ~cImageCreator(); + bool InitCairoImage(int width, int height); + void DrawEllipse(tColor color, int quadrants = 0); + cImage *GetImage(void); +}; + +#endif //__IMAGECREATOR_H diff --git a/libtemplate/template.c b/libtemplate/template.c index ef7d677..e6141f2 100644 --- a/libtemplate/template.c +++ b/libtemplate/template.c @@ -250,6 +250,8 @@ void cTemplate::CachePixmapImages(cTemplatePixmap *pix) { while(func = pix->GetNextFunction()) { if (func->GetType() == ftDrawImage) { CacheImage(func); + } else if (func->GetType() == ftDrawEllipse) { + CacheEllipse(func); } } } @@ -279,3 +281,12 @@ void cTemplate::CacheImage(cTemplateFunction *func) { break; } } + +void cTemplate::CacheEllipse(cTemplateFunction *func) { + int id = func->GetId(); + int w = func->GetNumericParameter(ptWidth); + int h = func->GetNumericParameter(ptHeight); + tColor clr = func->GetColorParameter(ptColor); + int quadrant = func->GetNumericParameter(ptQuadrant); + imgCache->CacheEllipse(id, w, h, clr, quadrant); +} diff --git a/libtemplate/template.h b/libtemplate/template.h index 2c1cfb2..e0a8066 100644 --- a/libtemplate/template.h +++ b/libtemplate/template.h @@ -34,6 +34,7 @@ private: eViewType viewType; void CachePixmapImages(cTemplatePixmap *pix); void CacheImage(cTemplateFunction *func); + void CacheEllipse(cTemplateFunction *func); protected: cGlobals *globals; cTemplateView *rootView; diff --git a/libtemplate/templatefunction.c b/libtemplate/templatefunction.c index 8465961..1ddf297 100644 --- a/libtemplate/templatefunction.c +++ b/libtemplate/templatefunction.c @@ -6,7 +6,10 @@ using namespace std; // --- cTemplateFunction ------------------------------------------------------------- -cTemplateFunction::cTemplateFunction(eFuncType type) { +int cTemplateFunction::nextId = 0; + +cTemplateFunction::cTemplateFunction(eFuncType type) { + id = nextId++; this->type = type; debug = false; containerX = 0; diff --git a/libtemplate/templatefunction.h b/libtemplate/templatefunction.h index f7af25c..59d6002 100644 --- a/libtemplate/templatefunction.h +++ b/libtemplate/templatefunction.h @@ -102,7 +102,10 @@ enum eOverflowType { }; class cTemplateFunction { +private: + static int nextId; protected: + int id; eFuncType type; bool debug; int containerX; //X of parent container @@ -185,6 +188,7 @@ public: //Parse parameters with dynamically set Tokens bool ParseParameters(void); //Getter Functions + int GetId(void) { return id; }; eFuncType GetType(void) { return type; }; bool DoDebug(void) { return debug; }; string GetParameter(eParamType type); diff --git a/skins/nopacity/xmlfiles/displaymenu.xml b/skins/nopacity/xmlfiles/displaymenu.xml index f6040f6..de48380 100644 --- a/skins/nopacity/xmlfiles/displaymenu.xml +++ b/skins/nopacity/xmlfiles/displaymenu.xml @@ -22,19 +22,13 @@ - + - + - - - - - - - + diff --git a/views/view.c b/views/view.c index 2b9c4bf..d8c37a0 100644 --- a/views/view.c +++ b/views/view.c @@ -636,14 +636,17 @@ void cView::DoDrawEllipse(int num, cTemplateFunction *func, int x0, int y0) { y += y0; int w = func->GetNumericParameter(ptWidth); int h = func->GetNumericParameter(ptHeight); - cRect size(x, y, w, h); tColor clr = func->GetColorParameter(ptColor); int quadrant = func->GetNumericParameter(ptQuadrant); if (quadrant < -4 || quadrant > 8) { esyslog("skindesigner: wrong quadrant %d for drawellipse, allowed values are from -4 to 8", quadrant); quadrant = 0; } - DrawEllipse(num, size, clr, quadrant); + cImage *ellipse = imgCache->GetEllipse(func->GetId(), w, h, clr, quadrant); + if (ellipse) { + const cPoint point(x, y); + DrawImage(num, point, *ellipse); + } } void cView::DoDrawSlope(int num, cTemplateFunction *func, int x0, int y0) {