mirror of
https://projects.vdr-developer.org/git/vdr-plugin-skindesigner.git
synced 2023-10-19 15:58:31 +00:00
drawing ellipses antialiased with Cairo
This commit is contained in:
@@ -3,9 +3,10 @@
|
||||
#include <map>
|
||||
#include <fstream>
|
||||
#include <sys/stat.h>
|
||||
#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<int, cImage*>::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<int, cImage*>(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<std::string, cImage*>::const_iterator it = skinPartsCache.begin(); it != skinPartsCache.end(); it++) {
|
||||
for(map<string, cImage*>::const_iterator it = skinPartsCache.begin(); it != skinPartsCache.end(); it++) {
|
||||
cImage *img = (cImage*)it->second;
|
||||
delete img;
|
||||
}
|
||||
skinPartsCache.clear();
|
||||
|
||||
for(map<int, cImage*>::const_iterator it = cairoImageCache.begin(); it != cairoImageCache.end(); it++) {
|
||||
cImage *img = (cImage*)it->second;
|
||||
delete img;
|
||||
}
|
||||
cairoImageCache.clear();
|
||||
}
|
||||
|
||||
void cImageCache::Debug(bool full) {
|
||||
|
@@ -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<string, cImage*> iconCache;
|
||||
map<string, cImage*> channelLogoCache;
|
||||
map<string, cImage*> skinPartsCache;
|
||||
map<int, cImage*> cairoImageCache;
|
||||
bool LoadIcon(eImageType type, string name);
|
||||
bool LoadLogo(const cChannel *channel);
|
||||
bool LoadSeparatorLogo(string name);
|
||||
|
202
libcore/imagecreator.c
Normal file
202
libcore/imagecreator.c
Normal file
@@ -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);
|
||||
}
|
26
libcore/imagecreator.h
Normal file
26
libcore/imagecreator.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef __IMAGECREATOR_H
|
||||
#define __IMAGECREATOR_H
|
||||
|
||||
#include <cairo.h>
|
||||
#include <vdr/osd.h>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
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
|
Reference in New Issue
Block a user