vdr-plugin-skindesigner/libcore/pixmapcontainer.c

478 lines
14 KiB
C

#define __STL_CONFIG_H
#include "pixmapcontainer.h"
#include "../config.h"
cMutex cPixmapContainer::mutex;
cOsd *cPixmapContainer::osd = NULL;
eFlushState cPixmapContainer::flushState = fsOpen;
cPixmapContainer::cPixmapContainer(int numPixmaps) {
this->numPixmaps = numPixmaps;
pixContainerInit = true;
mutex.Lock();
pixmaps = new cPixmap*[numPixmaps];
pixmapsTransparency = new int[numPixmaps];
for(int i=0; i < numPixmaps; i++) {
pixmaps[i] = NULL;
pixmapsTransparency[i] = 0;
}
mutex.Unlock();
checkRunning = false;
fadeTime = 0;
deleteOsdOnExit = false;
}
cPixmapContainer::~cPixmapContainer(void) {
for (int i=0; i < numPixmaps; i++) {
mutex.Lock();
if (pixmaps[i] && osd) {
osd->DestroyPixmap(pixmaps[i]);
pixmaps[i] = NULL;
}
mutex.Unlock();
}
delete[] pixmaps;
delete[] pixmapsTransparency;
if (deleteOsdOnExit && osd) {
mutex.Lock();
delete osd;
osd = NULL;
mutex.Unlock();
}
}
bool cPixmapContainer::CreateOsd(int Left, int Top, int Width, int Height) {
if (osd) {
return true;
}
cOsd *newOsd = cOsdProvider::NewOsd(Left, Top);
if (newOsd) {
tArea Area = { 0, 0, Width, Height, 32 };
if (newOsd->SetAreas(&Area, 1) == oeOk) {
osd = newOsd;
return true;
}
}
return false;
}
void cPixmapContainer::LockFlush(void) {
flushState = fsLock;
}
void cPixmapContainer::OpenFlush(void) {
flushState = fsOpen;
}
bool cPixmapContainer::PixmapExists(int num) {
cMutexLock MutexLock(&mutex);
if (pixmaps[num])
return true;
return false;
}
void cPixmapContainer::DoFlush(void) {
cMutexLock MutexLock(&mutex);
if (!osd || (checkRunning && !Running()))
return;
if (flushState == fsOpen) {
osd->Flush();
}
}
void cPixmapContainer::CreatePixmap(int num, int Layer, const cRect &ViewPort, const cRect &DrawPort) {
cMutexLock MutexLock(&mutex);
if (!osd || (checkRunning && !Running()))
return;
pixmaps[num] = osd->CreatePixmap(Layer, ViewPort, DrawPort);
pixmaps[num]->Fill(clrTransparent);
if (pixContainerInit && fadeTime) {
pixmaps[num]->SetAlpha(0);
} else if (pixmapsTransparency[num] > 0) {
int alpha = (100 - pixmapsTransparency[num])*255/100;
pixmaps[num]->SetAlpha(alpha);
}
}
bool cPixmapContainer::DestroyPixmap(int num) {
cMutexLock MutexLock(&mutex);
if (pixmaps[num] && osd) {
osd->DestroyPixmap(pixmaps[num]);
pixmaps[num] = NULL;
return true;
}
return false;
}
void cPixmapContainer::DrawText(int num, const cPoint &Point, const char *s, tColor ColorFg, tColor ColorBg, std::string fontName, int fontSize) {
if (checkRunning && !Running())
return;
cMutexLock MutexLock(&mutex);
if (!pixmaps[num])
return;
fontManager->Lock();
cFont *font = fontManager->Font(fontName, fontSize);
if (font)
pixmaps[num]->DrawText(Point, s, ColorFg, ColorBg, font);
fontManager->Unlock();
}
void cPixmapContainer::DrawRectangle(int num, const cRect &Rect, tColor Color) {
if (checkRunning && !Running())
return;
cMutexLock MutexLock(&mutex);
if (!pixmaps[num])
return;
pixmaps[num]->DrawRectangle(Rect, Color);
}
void cPixmapContainer::DrawEllipse(int num, const cRect &Rect, tColor Color, int Quadrants) {
if (checkRunning && !Running())
return;
cMutexLock MutexLock(&mutex);
if (!pixmaps[num])
return;
pixmaps[num]->DrawEllipse(Rect, Color, Quadrants);
}
void cPixmapContainer::DrawImage(int num, const cPoint &Point, const cImage &Image) {
if (checkRunning && !Running())
return;
cMutexLock MutexLock(&mutex);
if (!pixmaps[num])
return;
pixmaps[num]->DrawImage(Point, Image);
}
void cPixmapContainer::DrawBitmap(int num, const cPoint &Point, const cBitmap &Bitmap, tColor ColorFg, tColor ColorBg, bool Overlay) {
if (checkRunning && !Running())
return;
cMutexLock MutexLock(&mutex);
if (!pixmaps[num])
return;
pixmaps[num]->DrawBitmap(Point, Bitmap, ColorFg, ColorBg, Overlay);
}
void cPixmapContainer::Fill(int num, tColor Color) {
if (checkRunning && !Running())
return;
cMutexLock MutexLock(&mutex);
if (!pixmaps[num])
return;
pixmaps[num]->Fill(Color);
}
void cPixmapContainer::SetAlpha(int num, int Alpha) {
if (checkRunning && !Running())
return;
cMutexLock MutexLock(&mutex);
if (!pixmaps[num])
return;
pixmaps[num]->SetAlpha(Alpha);
}
void cPixmapContainer::SetTransparency(int num, int Transparency) {
if (Transparency < 0 && Transparency > 100)
return;
pixmapsTransparency[num] = Transparency;
}
void cPixmapContainer::SetLayer(int num, int Layer) {
cMutexLock MutexLock(&mutex);
if (!pixmaps[num])
return;
pixmaps[num]->SetLayer(Layer);
}
int cPixmapContainer::Width(int num) {
if (checkRunning && !Running())
return 0;
cMutexLock MutexLock(&mutex);
if (!pixmaps[num])
return 0;
int width = pixmaps[num]->ViewPort().Width();
return width;
}
int cPixmapContainer::Height(int num) {
if (checkRunning && !Running())
return 0;
cMutexLock MutexLock(&mutex);
if (!pixmaps[num])
return 0;
int height = pixmaps[num]->ViewPort().Height();
return height;
}
int cPixmapContainer::DrawportWidth(int num) {
if (checkRunning && !Running())
return 0;
cMutexLock MutexLock(&mutex);
if (!pixmaps[num])
return 0;
int width = pixmaps[num]->DrawPort().Width();
return width;
}
int cPixmapContainer::DrawportHeight(int num) {
if (checkRunning && !Running())
return 0;
cMutexLock MutexLock(&mutex);
if (!pixmaps[num])
return 0;
int height = pixmaps[num]->DrawPort().Height();
return height;
}
int cPixmapContainer::DrawportX(int num) {
if (checkRunning && !Running())
return 0;
cMutexLock MutexLock(&mutex);
if (!pixmaps[num])
return 0;
int x = pixmaps[num]->DrawPort().X();
return x;
}
int cPixmapContainer::DrawportY(int num) {
if (checkRunning && !Running())
return 0;
cMutexLock MutexLock(&mutex);
if (!pixmaps[num])
return 0;
int y = pixmaps[num]->DrawPort().Y();
return y;
}
void cPixmapContainer::SetDrawPortPoint(int num, const cPoint &Point) {
if (checkRunning && !Running())
return;
cMutexLock MutexLock(&mutex);
if (!pixmaps[num])
return;
pixmaps[num]->SetDrawPortPoint(Point);
}
/***************************************************************************
* HELPERS -- do not access the pixmaps array directly, use wrapper functions
* to ensure that a proper lock is set before accessing pixmaps
****************************************************************************/
void cPixmapContainer::FadeIn(void) {
if (!fadeTime)
return;
uint64_t Start = cTimeMs::Now();
int FadeFrameTime = fadeTime / 10;
while (Running()) {
uint64_t Now = cTimeMs::Now();
double t = min(double(Now - Start) / fadeTime, 1.0);
int Alpha = t * ALPHA_OPAQUE;
for (int i = 0; i < numPixmaps; i++) {
if (!PixmapExists(i))
continue;
if (pixmapsTransparency[i] > 0) {
int alpha = (100 - pixmapsTransparency[i])*Alpha/100;
SetAlpha(i, alpha);
} else {
SetAlpha(i, Alpha);
}
}
DoFlush();
int Delta = cTimeMs::Now() - Now;
if (Running() && (Delta < FadeFrameTime))
cCondWait::SleepMs(FadeFrameTime - Delta);
if ((int)(Now - Start) > fadeTime)
break;
}
}
void cPixmapContainer::FadeOut(void) {
if (!fadeTime)
return;
uint64_t Start = cTimeMs::Now();
int FadeFrameTime = fadeTime / 10;
while (true) {
uint64_t Now = cTimeMs::Now();
double t = min(double(Now - Start) / fadeTime, 1.0);
int Alpha = (1 - t) * ALPHA_OPAQUE;
for (int i = 0; i < numPixmaps; i++) {
if (!PixmapExists(i))
continue;
if (pixmapsTransparency[i] > 0) {
int alpha = (100 - pixmapsTransparency[i])*Alpha/100;
SetAlpha(i, alpha);
} else {
SetAlpha(i, Alpha);
}
}
DoFlush();
int Delta = cTimeMs::Now() - Now;
if (Running() && (Delta < FadeFrameTime))
cCondWait::SleepMs(FadeFrameTime - Delta);
if ((int)(Now - Start) > fadeTime)
break;
}
}
/*****************************************
* scrollSpeed: 1 slow
* 2 medium
* 3 fast
******************************************/
void cPixmapContainer::ScrollHorizontal(int num, int scrollDelay, int scrollSpeed, int scrollMode) {
bool carriageReturn = (scrollMode == 1) ? true : false;
int scrollDelta = 1;
int drawPortX;
int FrameTime = 0;
if (scrollSpeed == 1)
FrameTime = 50;
else if (scrollSpeed == 2)
FrameTime = 30;
else
FrameTime = 15;
if (!Running())
return;
int maxX = DrawportWidth(num) - Width(num);
bool doSleep = false;
while (Running()) {
if (doSleep) {
DoSleep(scrollDelay);
doSleep = false;
}
if (!Running())
return;
uint64_t Now = cTimeMs::Now();
drawPortX = DrawportX(num);
drawPortX -= scrollDelta;
if (abs(drawPortX) > maxX) {
DoSleep(scrollDelay);
if (carriageReturn)
drawPortX = 0;
else {
scrollDelta *= -1;
drawPortX -= scrollDelta;
}
doSleep = true;
}
if (!carriageReturn && (drawPortX == 0)) {
scrollDelta *= -1;
doSleep = true;
}
SetDrawPortPoint(num, cPoint(drawPortX, 0));
int Delta = cTimeMs::Now() - Now;
DoFlush();
if (Running() && (Delta < FrameTime))
cCondWait::SleepMs(FrameTime - Delta);
}
}
/*****************************************
* scrollSpeed: 1 slow
* 2 medium
* 3 fast
******************************************/
void cPixmapContainer::ScrollVertical(int num, int scrollDelay, int scrollSpeed) {
if (!scrollSpeed)
return;
DoSleep(scrollDelay);
int drawPortY;
int FrameTime = 0;
if (scrollSpeed == 1)
FrameTime = 50;
else if (scrollSpeed == 2)
FrameTime = 30;
else
FrameTime = 15;
int maxY = DrawportHeight(num) - Height(num);
bool doSleep = false;
while (Running()) {
if (doSleep) {
doSleep = false;
DoSleep(scrollDelay);
}
uint64_t Now = cTimeMs::Now();
drawPortY = DrawportY(num);
drawPortY -= 1;
if (abs(drawPortY) > maxY) {
doSleep = true;
DoSleep(scrollDelay);
drawPortY = 0;
}
SetDrawPortPoint(num, cPoint(0, drawPortY));
if (doSleep) {
DoSleep(scrollDelay);
}
int Delta = cTimeMs::Now() - Now;
DoFlush();
if (Running() && (Delta < FrameTime))
cCondWait::SleepMs(FrameTime - Delta);
}
}
void cPixmapContainer::CancelSave(void) {
Cancel(-1);
while (Active())
cCondWait::SleepMs(10);
}
void cPixmapContainer::DoSleep(int duration) {
int sleepSlice = 10;
for (int i = 0; Running() && (i*sleepSlice < duration); i++)
cCondWait::SleepMs(sleepSlice);
}
void cPixmapContainer::DrawBlendedBackground(int num, int xStart, int width, tColor color, tColor colorBlending, bool fromTop) {
int height = Height(num);
int numSteps = 16;
int alphaStep = 0x0F;
int alpha = 0x00;
int step, begin, end;
if (fromTop) {
step = 1;
begin = 0;
end = numSteps;
} else {
step = -1;
begin = height;
end = height - numSteps;
}
tColor clr;
bool cont = true;
for (int i = begin; cont; i = i + step) {
clr = AlphaBlend(color, colorBlending, alpha);
DrawRectangle(num, cRect(xStart,i,width,1), clr);
alpha += alphaStep;
if (i == end)
cont = false;
}
}
void cPixmapContainer::DrawRoundedCorners(int num, int radius, int x, int y, int width, int height) {
if (radius > 2) {
DrawEllipse(num, cRect(x, y, radius, radius), clrTransparent, -2);
DrawEllipse(num, cRect(x + width - radius, y , radius, radius), clrTransparent, -1);
DrawEllipse(num, cRect(x, y + height - radius, radius, radius), clrTransparent, -3);
DrawEllipse(num, cRect(x + width - radius, y + height - radius, radius, radius), clrTransparent, -4);
}
}
void cPixmapContainer::DrawRoundedCornersWithBorder(int num, tColor borderColor, int radius, int width, int height) {
if (radius < 3)
return;
DrawEllipse(num, cRect(0,0,radius,radius), borderColor, -2);
DrawEllipse(num, cRect(-1,-1,radius,radius), clrTransparent, -2);
DrawEllipse(num, cRect(width-radius,0,radius,radius), borderColor, -1);
DrawEllipse(num, cRect(width-radius+1,-1,radius,radius), clrTransparent, -1);
DrawEllipse(num, cRect(0,height-radius,radius,radius), borderColor, -3);
DrawEllipse(num, cRect(-1,height-radius+1,radius,radius), clrTransparent, -3);
DrawEllipse(num, cRect(width-radius,height-radius,radius,radius), borderColor, -4);
DrawEllipse(num, cRect(width-radius+1,height-radius+1,radius,radius), clrTransparent, -4);
}