summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--glcddrivers/serdisp.c44
-rw-r--r--glcddrivers/serdisp.h11
-rw-r--r--glcdgraphics/extformats.h1
-rw-r--r--glcdgraphics/imagefile.c129
-rw-r--r--glcdgraphics/imagefile.h13
-rw-r--r--glcdskin/cache.c3
-rw-r--r--glcdskin/function.c2
-rw-r--r--glcdskin/object.c4
8 files changed, 182 insertions, 25 deletions
diff --git a/glcddrivers/serdisp.c b/glcddrivers/serdisp.c
index e9e15c4..f6863c7 100644
--- a/glcddrivers/serdisp.c
+++ b/glcddrivers/serdisp.c
@@ -22,6 +22,8 @@
// for memcpy
#include <string.h>
+#include <map>
+
#define SERDISP_VERSION(a,b) ((long)(((a) << 8) + (b)))
#define SERDISP_VERSION_GET_MAJOR(_c) ((int)( (_c) >> 8 ))
#define SERDISP_VERSION_GET_MINOR(_c) ((int)( (_c) & 0xFF ))
@@ -40,15 +42,13 @@ namespace GLCD
static void wrapEventListener(void* dd, SDGP_event_t* recylce);
-static int simpleTouchX=0, simpleTouchY=0, simpleTouchT=0;
-static bool simpleTouchChanged=false;
+static std::map<void* ,tTouchEvent*> touchEvents;
cDriverSerDisp::cDriverSerDisp(cDriverConfig * config)
: cDriver(config)
{
dd = (void *) NULL;
- simpleTouchChanged = false;
}
int cDriverSerDisp::Init(void)
@@ -335,6 +335,10 @@ int cDriverSerDisp::Init(void)
// clear display
Clear();
+ touchEvent = new tTouchEvent;
+ touchEvent->simpleTouchChanged = false;
+ touchEvents[dd] = touchEvent;
+
syslog(LOG_INFO, "%s: SerDisp with %s initialized.\n", config->name.c_str(), controller.c_str());
return 0;
}
@@ -344,6 +348,10 @@ int cDriverSerDisp::DeInit(void)
if (!dd)
return 0;
+ touchEvents.erase(dd);
+ delete touchEvent;
+ touchEvent = NULL;
+
//fp_serdisp_quit(dd);
/* use serdisp_close instead of serdisp_quit so that showpic and showtext are usable together with serdisplib */
fp_serdisp_close(dd);
@@ -502,12 +510,12 @@ void cDriverSerDisp::Refresh(bool refreshAll)
void cDriverSerDisp::SetBrightness(unsigned int percent)
{
- if ( supports_options && (fp_serdisp_isoption(dd, "BRIGHTNESS") == 1) ) /* if == 1: option is existing AND r/w */
+ if ( dd && supports_options && (fp_serdisp_isoption(dd, "BRIGHTNESS") == 1) ) /* if == 1: option is existing AND r/w */
fp_serdisp_setoption(dd, "BRIGHTNESS", (long)percent);
}
uint32_t cDriverSerDisp::GetDefaultBackgroundColor(void) {
- if ( supports_options && fp_serdisp_isoption(dd, "SELFEMITTING") && (fp_serdisp_getoption(dd, "SELFEMITTING", 0)) ) {
+ if ( dd && supports_options && fp_serdisp_isoption(dd, "SELFEMITTING") && (fp_serdisp_getoption(dd, "SELFEMITTING", 0)) ) {
return GRAPHLCD_Black;
}
return GRAPHLCD_White;
@@ -516,7 +524,7 @@ uint32_t cDriverSerDisp::GetDefaultBackgroundColor(void) {
bool cDriverSerDisp::SetFeature (const std::string & Feature, int value)
{
- if (strcasecmp(Feature.c_str(), "TOUCHSCREEN") == 0 || strcasecmp(Feature.c_str(), "TOUCH") == 0) {
+ if (dd && (strcasecmp(Feature.c_str(), "TOUCHSCREEN") == 0 || strcasecmp(Feature.c_str(), "TOUCH") == 0)) {
if (fp_SDGPI_search && fp_SDGPI_isenabled && fp_SDGPI_enable) {
uint8_t gpid = fp_SDGPI_search(dd, Feature.c_str());
if (gpid == 0xFF)
@@ -566,15 +574,17 @@ bool cDriverSerDisp::GetDriverFeature (const std::string & Feature, int & value
}
cGLCDEvent * cDriverSerDisp::GetEvent(void) {
- if (GLCD::simpleTouchChanged == false)
+ tTouchEvent* tev = touchEvents[dd];
+ if (tev && tev->simpleTouchChanged == false)
return NULL;
cSimpleTouchEvent * ev = new cSimpleTouchEvent();
- ev->x = simpleTouchX;
- ev->y = simpleTouchY;
- ev->touch = simpleTouchT;
- simpleTouchChanged = false;
+ ev->x = tev->simpleTouchX;
+ ev->y = tev->simpleTouchY;
+ ev->touch = tev->simpleTouchT;
+ tev->simpleTouchChanged = false;
+
return ev;
}
@@ -583,10 +593,14 @@ static void wrapEventListener(void* dd, SDGP_event_t* event) {
if (event->type == SDGPT_SIMPLETOUCH) {
SDGP_evpkt_simpletouch_t simpletouch;
memcpy(&simpletouch, &event->data, sizeof(SDGP_evpkt_simpletouch_t));
- simpleTouchChanged = true;
- simpleTouchX = simpletouch.norm_x;
- simpleTouchY = simpletouch.norm_y;
- simpleTouchT = simpletouch.norm_touch;
+
+ tTouchEvent* tev = touchEvents[dd];
+ if (tev) {
+ tev->simpleTouchChanged = true;
+ tev->simpleTouchX = simpletouch.norm_x;
+ tev->simpleTouchY = simpletouch.norm_y;
+ tev->simpleTouchT = simpletouch.norm_touch;
+ }
}
}
diff --git a/glcddrivers/serdisp.h b/glcddrivers/serdisp.h
index ea1be90..e8cd277 100644
--- a/glcddrivers/serdisp.h
+++ b/glcddrivers/serdisp.h
@@ -51,6 +51,15 @@ typedef struct SDGP_evpkt_simpletouch_s { /* 16 bytes */
int16_t norm_touch; /* normalised touch value */
} SDGP_evpkt_simpletouch_t;
+
+typedef struct {
+ bool simpleTouchChanged;
+ int simpleTouchX;
+ int simpleTouchY;
+ int simpleTouchT;
+} tTouchEvent;
+
+
typedef void (*fp_eventlistener_t) (void* dd, SDGP_event_t* recylce);
class cDriverConfig;
@@ -94,6 +103,8 @@ private:
int CheckSetup();
void eventListener (void* dd, SDGP_event_t* recycle);
+
+ tTouchEvent* touchEvent;
protected:
virtual bool GetDriverFeature (const std::string & Feature, int & value);
diff --git a/glcdgraphics/extformats.h b/glcdgraphics/extformats.h
index 2f6b2bc..b910c3c 100644
--- a/glcdgraphics/extformats.h
+++ b/glcdgraphics/extformats.h
@@ -29,7 +29,6 @@ public:
virtual bool Load(cImage & image, const std::string & fileName);
virtual bool Save(cImage & image, const std::string & fileName);
- virtual bool SupportsScaling(void) { return true; }
virtual bool LoadScaled(cImage & image, const std::string & fileName, uint16_t & scalew, uint16_t & scaleh);
};
diff --git a/glcdgraphics/imagefile.c b/glcdgraphics/imagefile.c
index 2f56f4a..d6baf24 100644
--- a/glcdgraphics/imagefile.c
+++ b/glcdgraphics/imagefile.c
@@ -11,6 +11,7 @@
#include "image.h"
#include "imagefile.h"
+#include "bitmap.h"
namespace GLCD
{
@@ -32,4 +33,132 @@ bool cImageFile::Save(cImage & image, const std::string & fileName)
return false;
}
+
+uint32_t cImageFile::Blend(uint32_t FgColour, uint32_t BgColour, uint8_t Level, double antiAliasGranularity) const
+{
+ if (antiAliasGranularity > 0.0)
+ Level = uint8_t(int(Level / antiAliasGranularity + 0.5) * antiAliasGranularity);
+ int Af = (FgColour & 0xFF000000) >> 24;
+ int Rf = (FgColour & 0x00FF0000) >> 16;
+ int Gf = (FgColour & 0x0000FF00) >> 8;
+ int Bf = (FgColour & 0x000000FF);
+ int Ab = (BgColour & 0xFF000000) >> 24;
+ int Rb = (BgColour & 0x00FF0000) >> 16;
+ int Gb = (BgColour & 0x0000FF00) >> 8;
+ int Bb = (BgColour & 0x000000FF);
+ int A = (Ab + (Af - Ab) * Level / 0xFF) & 0xFF;
+ int R = (Rb + (Rf - Rb) * Level / 0xFF) & 0xFF;
+ int G = (Gb + (Gf - Gb) * Level / 0xFF) & 0xFF;
+ int B = (Bb + (Bf - Bb) * Level / 0xFF) & 0xFF;
+ return (A << 24) | (R << 16) | (G << 8) | B;
+}
+
+bool cImageFile::Scale(cImage & image, uint16_t scalew, uint16_t scaleh, bool AntiAlias)
+{
+ if (! (scalew || scaleh) )
+ return false;
+
+ // one out of scalew/h == 0 ? -> auto aspect ratio
+ if (scalew && ! scaleh) {
+ scaleh = (uint16_t)( ((uint32_t)scalew * (uint32_t)image.Height()) / (uint32_t)image.Width() );
+ } else if (!scalew && scaleh) {
+ scalew = (uint16_t)( ((uint32_t)scaleh * (uint32_t)image.Width()) / (uint32_t)image.Height() );
+ }
+
+ cImage tempImg = cImage();
+ tempImg.SetWidth(scalew);
+ tempImg.SetHeight(scaleh);
+
+ // Scaling/Blending based on VDR / osd.c
+ // Fixed point scaling code based on www.inversereality.org/files/bitmapscaling.pdf
+ // by deltener@mindtremors.com
+ //
+ // slightly improved by Wolfgang Astleitner (modify factors and ratios so that scaled image is centered when upscaling)
+
+ double FactorX, FactorY;
+ int RatioX, RatioY;
+
+ if (!AntiAlias) {
+ FactorX = (double)scalew / (double)image.Width();
+ FactorY = (double)scaleh / (double)image.Height();
+ RatioX = (image.Width() << 16) / scalew;
+ RatioY = (image.Height() << 16) / scaleh;
+ } else {
+ FactorX = (double)scalew / (double)(image.Width()-1);
+ FactorY = (double)scaleh / (double)(image.Height()-1);
+ RatioX = ((image.Width()-1) << 16) / scalew;
+ RatioY = ((image.Height()-1) << 16) / scaleh;
+ }
+
+ bool downscale = (!AntiAlias || (FactorX <= 1.0 && FactorY <= 1.0));
+
+ for (unsigned int frame = 0; frame < image.Count() ; frame ++ ) {
+ cBitmap *b = new cBitmap(scalew, scaleh, GRAPHLCD_Transparent);
+
+ cBitmap *currFrame = image.GetBitmap(frame);
+
+ if (downscale) {
+ // Downscaling - no anti-aliasing:
+ const uint32_t *DestRow = b->Data();
+ int SourceY = 0;
+ for (int y = 0; y < scaleh; y++) {
+ int SourceX = 0;
+ const uint32_t *SourceRow = currFrame->Data() + (SourceY >> 16) * image.Width();
+ uint32_t *Dest = (uint32_t*) DestRow;
+ for (int x = 0; x < scalew; x++) {
+ *Dest++ = SourceRow[SourceX >> 16];
+ SourceX += RatioX;
+ }
+ SourceY += RatioY;
+ DestRow += scalew;
+ }
+ } else {
+ // Upscaling - anti-aliasing:
+ int SourceY = 0;
+ for (int y = 0; y < scaleh /*- 1*/; y++) {
+ int SourceX = 0;
+ int sy = SourceY >> 16;
+ uint8_t BlendY = 0xFF - ((SourceY >> 8) & 0xFF);
+ for (int x = 0; x < scalew /*- 1*/; x++) {
+ int sx = SourceX >> 16;
+ uint8_t BlendX = 0xFF - ((SourceX >> 8) & 0xFF);
+ // TODO: antiAliasGranularity
+ uint32_t c1 = Blend(currFrame->GetPixel(sx, sy), currFrame->GetPixel(sx + 1, sy), BlendX);
+ uint32_t c2 = Blend(currFrame->GetPixel(sx, sy + 1), currFrame->GetPixel(sx + 1, sy + 1), BlendX);
+ uint32_t c3 = Blend(c1, c2, BlendY);
+ b->DrawPixel(x, y, c3);
+ SourceX += RatioX;
+ }
+ SourceY += RatioY;
+ }
+ }
+ tempImg.AddBitmap(b);
+ }
+ // clear all bitmaps from image
+ image.Clear();
+ // set new resolution
+ image.SetWidth(scalew);
+ image.SetHeight(scaleh);
+ // re-add bitmaps from scaled image container
+ for (unsigned int frame = 0; frame < tempImg.Count(); frame ++) {
+ image.AddBitmap(new cBitmap(scalew, scaleh, (uint32_t*)tempImg.GetBitmap(frame)->Data()));
+ }
+ return true;
+}
+
+bool cImageFile::LoadScaled(cImage & image, const std::string & fileName, uint16_t & scalew, uint16_t & scaleh)
+{
+ if (Load(image, fileName)) {
+ if (scalew || scaleh) {
+ return Scale(image, scalew, scaleh, true);
+ } else {
+ return true;
+ }
+ } else {
+ scalew = 0;
+ scaleh = 0;
+ return false;
+ }
+}
+
} // end of namespace
diff --git a/glcdgraphics/imagefile.h b/glcdgraphics/imagefile.h
index bc7e835..2cc1eba 100644
--- a/glcdgraphics/imagefile.h
+++ b/glcdgraphics/imagefile.h
@@ -21,18 +21,19 @@ class cImage;
class cImageFile
{
+private:
+ uint32_t Blend(uint32_t fgcol, uint32_t bgcol, uint8_t level, double antiAliasGranularity = 0.0) const;
+protected:
+ bool Scale(cImage & image, uint16_t scalew, uint16_t scaleh, bool AntiAlias = false);
public:
cImageFile();
virtual ~cImageFile();
virtual bool Load(cImage & image, const std::string & fileName);
virtual bool Save(cImage & image, const std::string & fileName);
- virtual bool SupportsScaling(void) { return false; }
- virtual bool LoadScaled(cImage & image, const std::string & fileName, uint16_t & scalew, uint16_t & scaleh) {
- scalew = 0;
- scaleh = 0;
- return Load(image, fileName);
- }
+ virtual bool SupportsScaling(void) { return true; }
+
+ virtual bool LoadScaled(cImage & image, const std::string & fileName, uint16_t & scalew, uint16_t & scaleh);
};
} // end of namespace
diff --git a/glcdskin/cache.c b/glcdskin/cache.c
index a0b2929..f0543d9 100644
--- a/glcdskin/cache.c
+++ b/glcdskin/cache.c
@@ -17,6 +17,8 @@
#include <stdlib.h>
#include <string.h>
+#include <syslog.h>
+
#include "cache.h"
#include "skin.h"
@@ -102,6 +104,7 @@ cImage * cImageCache::Get(const std::string & path, uint16_t & scalew, uint16_t
item = LoadImage(path, scalew, scaleh);
if (item)
{
+ syslog(LOG_INFO, "INFO: graphlcd: successfully loaded image '%s'\n", path.c_str());
if (images.size() == size)
{
images.erase(oldest);
diff --git a/glcdskin/function.c b/glcdskin/function.c
index 6d96c57..2593f70 100644
--- a/glcdskin/function.c
+++ b/glcdskin/function.c
@@ -176,7 +176,7 @@ bool cSkinFunction::Parse(const std::string & Text)
{
if (inExpr == 0)
{
- syslog(LOG_ERR, "ERROR: Unmatched '%c' in expression", *ptr);
+ syslog(LOG_ERR, "ERROR: Unmatched '%c' in expression (%s)", *ptr, Text.c_str());
return false;
}
diff --git a/glcdskin/object.c b/glcdskin/object.c
index 7e99092..204b0d4 100644
--- a/glcdskin/object.c
+++ b/glcdskin/object.c
@@ -484,9 +484,9 @@ void cSkinObject::Render(GLCD::cBitmap * screen)
uint16_t xoff = 0;
uint16_t yoff = 0;
if (scalew || scaleh) {
- if (image->Width() < Size().w) {
+ if (image->Width() < (uint16_t)Size().w) {
xoff = (Size().w - image->Width() ) / 2;
- } else if (image->Height() < Size().h) {
+ } else if (image->Height() < (uint16_t)Size().h) {
yoff = (Size().h - image->Height() ) / 2;
}
}