drawing ellipses antialiased with Cairo

This commit is contained in:
louis 2014-12-03 18:12:37 +01:00
parent def1b3cc30
commit 7ce445025e
12 changed files with 304 additions and 15 deletions

View File

@ -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

View File

@ -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 \

View File

@ -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) {

View File

@ -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
View 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
View 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

View File

@ -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);
}

View File

@ -34,6 +34,7 @@ private:
eViewType viewType;
void CachePixmapImages(cTemplatePixmap *pix);
void CacheImage(cTemplateFunction *func);
void CacheEllipse(cTemplateFunction *func);
protected:
cGlobals *globals;
cTemplateView *rootView;

View File

@ -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;

View File

@ -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);

View File

@ -22,19 +22,13 @@
<area x="0" y="0" width="100%" height="100%" layer="1">
<!-- top bar -->
<drawrectangle x="0" y="0" width="{areawidth}" height="10%" color="{clrBackground}" />
<drawrectangle x="30%" y="{areaheight}*0.1 - 1" width="71%" height="1" color="{clrBorder}" />
<drawrectangle x="29%" y="10%" width="71%" height="1" color="{clrBorder}" />
<!-- menu bar -->
<drawrectangle x="0" y="10%" width="{areawidth}*29/100" height="81%" color="{clrBackground}" />
<drawrectangle x="{areawidth}*29/100 - 1" y="12%" width="1" height="76%" color="{clrBorder}" />
<drawrectangle x="29%" y="10%" width="1" height="81%" color="{clrBorder}" />
<!-- bottom bar -->
<drawrectangle x="0" y="90%" width="{areawidth}" height="10%" color="{clrBackground}" />
<drawrectangle x="30%" y="{areaheight}*0.9 - 1" width="71%" height="1" color="{clrBorder}" />
<!-- upper corner -->
<drawellipse x="{areawidth}*29/100" y="{areaheight}/10" width="{areawidth}*2/100" height="{areawidth}*2/100" quadrant="-2" color="{clrBorder}" />
<drawellipse x="{areawidth}*29/100 - 1" y="{areaheight}/10 - 1" width="{areawidth}*2/100" height="{areawidth}*2/100" quadrant="-2" color="{clrBackground}" />
<!-- lower corner -->
<drawellipse x="{areawidth}*29/100" y="{areaheight}*90/100 - {areawidth}*2/100" width="{areawidth}*2/100" height="{areawidth}*2/100" quadrant="-3" color="{clrBorder}" />
<drawellipse x="{areawidth}*29/100 - 1" y="{areaheight}*90/100 - {areawidth}*2/100 + 1" width="{areawidth}*2/100" height="{areawidth}*2/100" quadrant="-3" color="{clrBackground}" />
<drawrectangle x="29%" y="90%" width="71%" height="1" color="{clrBorder}" />
</area>
<area x="0" y="0" width="100%" height="10%" layer="2">
<drawimage imagetype="skinpart" path="headertop" x="0" y="0" width="100%" height="100%"/>

View File

@ -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) {