From eccd044bc2179fb81a499433179e1f7c42a28800 Mon Sep 17 00:00:00 2001 From: mrwastl Date: Thu, 13 May 2010 08:28:36 +0200 Subject: remove two printf-debugs --- glcdskin/parser.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'glcdskin') diff --git a/glcdskin/parser.c b/glcdskin/parser.c index b137a5f..d20988f 100644 --- a/glcdskin/parser.c +++ b/glcdskin/parser.c @@ -320,7 +320,7 @@ bool EndElem(const std::string & name) { if (object == NULL) { - printf("rotating parent to object\n"); + //printf("rotating parent to object\n"); object = parents[parents.size() - 1]; parents.pop_back(); } @@ -343,7 +343,7 @@ bool EndElem(const std::string & name) #endif if (parents.size() > 0) { - printf("pushing to parent\n"); + //printf("pushing to parent\n"); cSkinObject *parent = parents[parents.size() - 1]; if (parent->mObjects == NULL) parent->mObjects = new cSkinObjects(); -- cgit v1.2.3 From b0cd921fe42210fc3a029c330b7a38a036b8dabc Mon Sep 17 00:00:00 2001 From: mrwastl Date: Sat, 15 May 2010 11:30:17 +0200 Subject: glcdskin: added looping for images and scrolling for text-fields --- glcdskin/display.c | 11 +++ glcdskin/display.h | 2 + glcdskin/object.c | 270 ++++++++++++++++++++++++++++++++++++++++++++++++++++- glcdskin/object.h | 25 ++++- glcdskin/parser.c | 4 + 5 files changed, 306 insertions(+), 6 deletions(-) (limited to 'glcdskin') diff --git a/glcdskin/display.c b/glcdskin/display.c index b92fea5..a926bd9 100644 --- a/glcdskin/display.c +++ b/glcdskin/display.c @@ -28,6 +28,17 @@ void cSkinDisplay::Render(cBitmap * screen) } +bool cSkinDisplay::NeedsUpdate(uint64_t CurrentTime) +{ + for (uint32_t i = 0; i < NumObjects(); ++i) { + if ( GetObject(i)->NeedsUpdate(CurrentTime) ) { + return true; + } + } + return false; +} + + cSkinDisplays::cSkinDisplays(void) { } diff --git a/glcdskin/display.h b/glcdskin/display.h index af50179..3b19b0c 100644 --- a/glcdskin/display.h +++ b/glcdskin/display.h @@ -43,6 +43,8 @@ public: cSkinObject * GetObject(uint32_t n) const { return mObjects[n]; } void Render(cBitmap * screen); + + bool NeedsUpdate(uint64_t CurrentTime); }; class cSkinDisplays: public std::vector diff --git a/glcdskin/object.c b/glcdskin/object.c index c79fa59..5195806 100644 --- a/glcdskin/object.c +++ b/glcdskin/object.c @@ -3,6 +3,7 @@ #include "skin.h" #include "cache.h" #include "function.h" +#include namespace GLCD { @@ -43,6 +44,16 @@ cSkinObject::cSkinObject(cSkinDisplay * Parent) mFont(this, false), mText(this, false), mCondition(NULL), + mLastChange(0), + mChangeDelay(-1), // delay between two images frames: -1: not animated / don't care + mStoredImagePath(""), + mImageFrameId(0), // start with 1st frame + mScrollLoopMode(-1), // scroll (text) or loop (image) mode: default (-1) + mScrollLoopReached(false), // if scroll/loop == once: already looped once? + mScrollSpeed(0), // scroll speed: default (0) + mScrollTime(0), // scroll time interval: default (0) + mScrollOffset(0), // scroll offset (pixels) + mCurrText(""), mObjects(NULL) { } @@ -66,6 +77,16 @@ cSkinObject::cSkinObject(const cSkinObject & Src) mFont(Src.mFont), mText(Src.mText), mCondition(Src.mCondition), + mLastChange(0), + mChangeDelay(-1), + mStoredImagePath(""), + mImageFrameId(0), + mScrollLoopMode(Src.mScrollLoopMode), + mScrollLoopReached(Src.mScrollLoopReached), + mScrollSpeed(Src.mScrollSpeed), + mScrollTime(Src.mScrollTime), + mScrollOffset(Src.mScrollOffset), + mCurrText(Src.mCurrText), mObjects(NULL) { if (Src.mObjects) @@ -181,6 +202,50 @@ bool cSkinObject::ParseFontFace(const std::string & Text) return mFont.Parse(Text); } + +bool cSkinObject::ParseScrollLoopMode(const std::string & Text) +{ + if (Text == "never") + mScrollLoopMode = 0; + else if (Text == "once") + mScrollLoopMode = 1; + else if (Text == "always") + mScrollLoopMode = 2; + else + return false; + return true; +} + +bool cSkinObject::ParseScrollSpeed(const std::string & Text) +{ + int val; + if (!ParseIntParam(Text, val)) + return false; + + if (val < 0 || val > 10) + return false; + + mScrollSpeed = val; + return true; +} + +bool cSkinObject::ParseScrollTime(const std::string & Text) +{ + int val; + if (!ParseIntParam(Text, val)) + return false; + + if (val < 0 || val > 2000) + return false; + + if (val > 0 && val < 100) + val = 100; + + mScrollTime = val; + return true; +} + + void cSkinObject::SetListIndex(int MaxItems, int Index) { mText.SetListIndex(MaxItems, Index); @@ -211,22 +276,63 @@ tSize cSkinObject::Size(void) const void cSkinObject::Render(GLCD::cBitmap * screen) { + struct timeval tv; + uint64_t timestamp; + if (mCondition != NULL && !mCondition->Evaluate()) return; + gettimeofday(&tv, 0); + timestamp = tv.tv_sec * 1000 + tv.tv_usec / 1000; + switch (Type()) { case cSkinObject::image: { cImageCache * cache = mSkin->ImageCache(); - GLCD::cImage * image = cache->Get(mPath.Evaluate()); + int currScrollLoopMode = 2; //default if not configured in the skin: always + + cType evalPath = mPath.Evaluate(); + std::string currPath = evalPath; + + if (currPath != mStoredImagePath) { + mImageFrameId = 0; + mStoredImagePath = currPath; + mScrollLoopReached = false; + mLastChange = timestamp; + } + + GLCD::cImage * image = cache->Get(evalPath); if (image) { - const GLCD::cBitmap * bitmap = image->GetBitmap(); + int framecount = image->Count(); + + const GLCD::cBitmap * bitmap = image->GetBitmap(mImageFrameId); + if (bitmap) { screen->DrawBitmap(Pos().x, Pos().y, *bitmap, mColor); } + + if (mScrollLoopMode != -1) // if == -1: currScrollLoopMode already contains correct value + currScrollLoopMode = mScrollLoopMode; + + mChangeDelay = image->Delay(); + if (mChangeDelay != -1 && currScrollLoopMode > 0 && !mScrollLoopReached && framecount > 1) { + + if ( (int)(timestamp - mLastChange) >= mChangeDelay) { + + if (currScrollLoopMode == 1 && mImageFrameId+1 == framecount) { + mScrollLoopReached = true; // stop looping and switch to 1st frame + } + + mImageFrameId = (mImageFrameId+1) % framecount; + mLastChange = timestamp; + } + } + + if (mLastChange == 0) + mLastChange = timestamp; } break; } @@ -301,14 +407,49 @@ void cSkinObject::Render(GLCD::cBitmap * screen) } case cSkinObject::text: + case cSkinObject::scrolltext: { cSkinFont * skinFont = mSkin->GetFont(mFont.Evaluate()); + int currScrollLoopMode = 1; // default values if no setup default values available + int currScrollSpeed = 8; + int currScrollTime = 500; + + // get default values from derived config-class if available + tSkinToken token = tSkinToken(); + token.Id = mSkin->Config().GetTokenId("ScrollMode"); + if (token.Id >= 0) { + cType t = mSkin->Config().GetToken(token); + currScrollLoopMode = (int)(t); + } + token.Id = mSkin->Config().GetTokenId("ScrollSpeed"); + if (token.Id >= 0) { + cType t = mSkin->Config().GetToken(token); + currScrollSpeed = (int)(t); + } + token.Id = mSkin->Config().GetTokenId("ScrollTime"); + if (token.Id >= 0) { + cType t = mSkin->Config().GetToken(token); + currScrollTime = (int)(t); + } + if (skinFont) { const cFont * font = skinFont->Font(); std::string text = mText.Evaluate(); + + if (! (text == mCurrText) ) { + mScrollOffset = 0; + mCurrText = text; + mScrollLoopReached = false; + mLastChange = timestamp; + } + if (mMultiline) { + + // scrolling in multiline not supported at the moment + mScrollLoopReached = true; // avoid check in NeedsUpdate() + std::vector lines; font->WrapText(Size().w, Size().h, text, lines); for (size_t i = 0; i < lines.size(); i++) @@ -334,6 +475,9 @@ void cSkinObject::Render(GLCD::cBitmap * screen) if (text.find('\t') != std::string::npos && mSkin->Config().GetTabPosition(0, Size().w, *font) > 0) { + // scrolling in texts with tabulators not supported at the moment + mScrollLoopReached = true; // avoid check in NeedsUpdate() + std::string::size_type pos1; std::string::size_type pos2; std::string str; @@ -363,8 +507,12 @@ void cSkinObject::Render(GLCD::cBitmap * screen) { int w = font->Width(text); int x = Pos().x; + bool updateScroll = false; + if (w < Size().w) { + mScrollLoopReached = true; // avoid check in NeedsUpdate() + if (mAlign == taRight) { x += Size().w - w; @@ -373,18 +521,53 @@ void cSkinObject::Render(GLCD::cBitmap * screen) { x += (Size().w - w) / 2; } + } else { + + if (mScrollLoopMode != -1) // if == -1: currScrollLoopMode already contains correct value + currScrollLoopMode = mScrollLoopMode; + + if (mScrollSpeed > 0) + currScrollSpeed = mScrollSpeed; + + if (mScrollTime > 0) + currScrollTime = mScrollTime; + + if (currScrollLoopMode > 0 && (!mScrollLoopReached || mScrollOffset) && + ((int)(timestamp-mLastChange) >= currScrollTime) + ) + { + if (mScrollLoopReached) + mScrollOffset = 0; + else + updateScroll = true; + } + + } + screen->DrawText(x, Pos().y, x + Size().w - 1, text, font, mColor, true, mScrollOffset); + + if (updateScroll) { + mScrollOffset += currScrollSpeed; + + if ( x + Size().w + mScrollOffset > w+Size().w) { + if (currScrollLoopMode == 1) + // reset mScrollOffset in next step (else: string not redrawn when scroll done) + mScrollLoopReached = true; + else + mScrollOffset= 0; + } + updateScroll = false; + mLastChange = timestamp; } - screen->DrawText(x, Pos().y, x + Size().w - 1, text, font, mColor); } } } break; } - case cSkinObject::scrolltext: +// case cSkinObject::scrolltext: //DrawScrolltext(Object->Pos(), Object->Size(), Object->Fg(), Object->Text(), Object->Font(), // Object->Align()); - break; +// break; case cSkinObject::scrollbar: //DrawScrollbar(Object->Pos(), Object->Size(), Object->Bg(), Object->Fg()); @@ -430,6 +613,83 @@ void cSkinObject::Render(GLCD::cBitmap * screen) } } +bool cSkinObject::NeedsUpdate(uint64_t CurrentTime) +{ + if (mCondition != NULL && !mCondition->Evaluate()) + return false; + + switch (Type()) + { + case cSkinObject::image: + { + int currScrollLoopMode = 2; + + if (mScrollLoopMode != -1) + currScrollLoopMode = mScrollLoopMode; + + if ( mChangeDelay > 0 && currScrollLoopMode > 0 && !mScrollLoopReached && + ( (int)(CurrentTime-mLastChange) >= mChangeDelay) + ) + { + return true; + } + return false; + break; + } + case cSkinObject::text: + case cSkinObject::scrolltext: + { + int currScrollLoopMode = 1; // default values if no setup default values available + int currScrollTime = 500; + + // get default values from derived config-class if available + tSkinToken token = tSkinToken(); + token.Id = mSkin->Config().GetTokenId("ScrollMode"); + if (token.Id >= 0) { + cType t = mSkin->Config().GetToken(token); + currScrollLoopMode = (int)(t); + } + token.Id = mSkin->Config().GetTokenId("ScrollTime"); + if (token.Id >= 0) { + cType t = mSkin->Config().GetToken(token); + currScrollTime = (int)(t); + } + + if (mScrollLoopMode != -1) // if == -1: currScrollLoopMode already contains correct value + currScrollLoopMode = mScrollLoopMode; + + if (mScrollTime > 0) + currScrollTime = mScrollTime; + + if (currScrollLoopMode > 0 && (!mScrollLoopReached || mScrollOffset) && + (int)(CurrentTime-mLastChange) >= currScrollTime + ) + { + return true; + } + return false; + break; + } + case cSkinObject::progress: + return false; + break; + case cSkinObject::block: + { + for (uint32_t i = 0; i < NumObjects(); i++) { + if ( GetObject(i)->NeedsUpdate(CurrentTime) ) { + return true; + } + } + return false; + break; + } + default: // all other elements are static ones + return false; + } + return false; +} + + cSkinObjects::cSkinObjects(void) { } diff --git a/glcdskin/object.h b/glcdskin/object.h index f164747..188dd79 100644 --- a/glcdskin/object.h +++ b/glcdskin/object.h @@ -96,6 +96,21 @@ private: cSkinString mText; cSkinFunction * mCondition; + uint64_t mLastChange; // last change in dynamic object (scroll, frame change, ...) + int mChangeDelay; // delay between two changes (frame change, scrolling, ...) + // special values: -2: no further looping (mScrollLoopMode == 'once') + // -1: not set (ie: not an animated image) + + std::string mStoredImagePath; // stored image path + int mImageFrameId; // frame ID of image + + int mScrollLoopMode; // scroll (text) or loop (image) mode: -1: default, 0: never, 1: once, 2: always + bool mScrollLoopReached; // if scroll/loop == once: already looped once? + int mScrollSpeed; // scroll speed: 0: default, [1 - 10]: speed + int mScrollTime; // scroll time interval: 0: default, [100 - 2000]: time interval + int mScrollOffset; // scroll offset (pixels) + std::string mCurrText; // current text (for checks if text has changed) + cSkinObjects * mObjects; // used for block objects such as public: @@ -112,11 +127,15 @@ public: bool ParseWidth(const std::string &Text); bool ParseHeight(const std::string &Text); + bool ParseScrollLoopMode(const std::string & Text); + bool ParseScrollSpeed(const std::string & Text); + bool ParseScrollTime(const std::string & Text); + void SetListIndex(int MaxItems, int Index); eType Type(void) const { return mType; } cSkinFunction * Condition(void) const { return mCondition; } - cSkinDisplay * Display(void) const { return mDisplay; } + cSkinDisplay * Display(void) const { return mDisplay; } cSkin * Skin(void) const { return mSkin; } const std::string & TypeName(void) const; @@ -127,6 +146,10 @@ public: cSkinObject * GetObject(uint32_t Index) const; void Render(cBitmap * screen); + + // check if update is required for dynamic objects (image, text, progress, pane) + // false: no update required, true: update required + bool NeedsUpdate(uint64_t CurrentTime); }; class cSkinObjects: public std::vector diff --git a/glcdskin/parser.c b/glcdskin/parser.c index d20988f..cd76b24 100644 --- a/glcdskin/parser.c +++ b/glcdskin/parser.c @@ -205,6 +205,7 @@ bool StartElem(const std::string & name, std::map & att ATTRIB_OPT_FUNC_PARAM("y", object->ParseIntParam, object->mPos2.y); ATTRIB_OPT_FUNC("color", object->ParseColor); ATTRIB_MAN_FUNC("path", object->mPath.Parse); + ATTRIB_OPT_FUNC("loop", object->ParseScrollLoopMode); } else if (name == "text" || name == "scrolltext") @@ -213,6 +214,9 @@ bool StartElem(const std::string & name, std::map & att ATTRIB_OPT_FUNC("align", object->ParseAlignment); ATTRIB_OPT_FUNC("font", object->ParseFontFace); ATTRIB_OPT_BOOL("multiline", object->mMultiline); + ATTRIB_OPT_FUNC("scrollmode", object->ParseScrollLoopMode); + ATTRIB_OPT_FUNC("scrollspeed", object->ParseScrollSpeed); + ATTRIB_OPT_FUNC("scrolltime", object->ParseScrollTime); #if 0 if (name == "blink") { -- cgit v1.2.3 From 81e18b8c8a7c851d87e795febacc294e39b9ad3a Mon Sep 17 00:00:00 2001 From: mrwastl Date: Sat, 15 May 2010 15:40:18 +0200 Subject: glcdskin: bug fix in image loop / NeedsUpdate() code --- glcdskin/object.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'glcdskin') diff --git a/glcdskin/object.c b/glcdskin/object.c index 5195806..ce098f8 100644 --- a/glcdskin/object.c +++ b/glcdskin/object.c @@ -300,6 +300,7 @@ void cSkinObject::Render(GLCD::cBitmap * screen) mStoredImagePath = currPath; mScrollLoopReached = false; mLastChange = timestamp; + mChangeDelay = -1; } GLCD::cImage * image = cache->Get(evalPath); @@ -317,8 +318,8 @@ void cSkinObject::Render(GLCD::cBitmap * screen) if (mScrollLoopMode != -1) // if == -1: currScrollLoopMode already contains correct value currScrollLoopMode = mScrollLoopMode; - mChangeDelay = image->Delay(); - if (mChangeDelay != -1 && currScrollLoopMode > 0 && !mScrollLoopReached && framecount > 1) { + if (framecount > 1 && currScrollLoopMode > 0 && !mScrollLoopReached) { + mChangeDelay = image->Delay(); if ( (int)(timestamp - mLastChange) >= mChangeDelay) { -- cgit v1.2.3 From 592389da2c5dce76e1f89df80cbee340ed277475 Mon Sep 17 00:00:00 2001 From: mrwastl Date: Sat, 15 May 2010 17:29:10 +0200 Subject: glcdskin: improved scrolling of texts --- glcdskin/object.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'glcdskin') diff --git a/glcdskin/object.c b/glcdskin/object.c index ce098f8..471233d 100644 --- a/glcdskin/object.c +++ b/glcdskin/object.c @@ -544,7 +544,14 @@ void cSkinObject::Render(GLCD::cBitmap * screen) } } - screen->DrawText(x, Pos().y, x + Size().w - 1, text, font, mColor, true, mScrollOffset); + + if (updateScroll) { + w += font->Width(" "); + std::string textdoubled = text + " " + text; + screen->DrawText(x, Pos().y, x + Size().w - 1, textdoubled, font, mColor, true, mScrollOffset); + } else { + screen->DrawText(x, Pos().y, x + Size().w - 1, text, font, mColor, true, mScrollOffset); + } if (updateScroll) { mScrollOffset += currScrollSpeed; -- cgit v1.2.3 From 4a7aeebfab185320694c88d6d3ff5a1537f94660 Mon Sep 17 00:00:00 2001 From: mrwastl Date: Sun, 16 May 2010 09:45:39 +0200 Subject: glcdskin: another small bug fix for scrolling --- glcdskin/object.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'glcdskin') diff --git a/glcdskin/object.c b/glcdskin/object.c index 471233d..faa4758 100644 --- a/glcdskin/object.c +++ b/glcdskin/object.c @@ -545,7 +545,7 @@ void cSkinObject::Render(GLCD::cBitmap * screen) } - if (updateScroll) { + if (mScrollOffset) { w += font->Width(" "); std::string textdoubled = text + " " + text; screen->DrawText(x, Pos().y, x + Size().w - 1, textdoubled, font, mColor, true, mScrollOffset); -- cgit v1.2.3 From f5f1d102c99ef7b3f1e0aec6463a8c17d3262bad Mon Sep 17 00:00:00 2001 From: mrwastl Date: Fri, 18 Jun 2010 22:59:14 +0200 Subject: text-object: added support for alternative text / alternative condition; bug fixes: annoying update problems should now be fixed; bug fix in brightness update detection; overloadable method for getting a timestamp that is compliant to VDR timestamp (cSkinConfig::Now(), will be overloaded in vdr-plugin-graphlcd to return the value of cTimeMs::Now()); serdisp-driver: call rotate only if UpsideDown is set --- glcdskin/config.c | 11 ++++++++++ glcdskin/config.h | 2 ++ glcdskin/object.c | 63 +++++++++++++++++++++++++++++++++++++++++++++---------- glcdskin/object.h | 19 ++++++++++------- glcdskin/parser.c | 2 ++ 5 files changed, 79 insertions(+), 18 deletions(-) (limited to 'glcdskin') diff --git a/glcdskin/config.c b/glcdskin/config.c index 518218e..c733427 100644 --- a/glcdskin/config.c +++ b/glcdskin/config.c @@ -1,6 +1,8 @@ #include "config.h" #include "type.h" +#include + namespace GLCD { @@ -39,4 +41,13 @@ int cSkinConfig::GetTabPosition(int Index, int MaxWidth, const cFont & Font) return 0; } +uint64_t cSkinConfig::Now(void) +{ + struct timeval tv; + + gettimeofday(&tv, 0); + return (uint64_t)(tv.tv_sec * 1000 + tv.tv_usec / 1000); +} + + } // end of namespace diff --git a/glcdskin/config.h b/glcdskin/config.h index f6c8af9..ce68513 100644 --- a/glcdskin/config.h +++ b/glcdskin/config.h @@ -15,6 +15,7 @@ #include +#include namespace GLCD { @@ -35,6 +36,7 @@ public: virtual cType GetToken(const tSkinToken & Token); virtual int GetTokenId(const std::string & Name); virtual int GetTabPosition(int Index, int MaxWidth, const cFont & Font); + virtual uint64_t Now(void); }; } // end of namespace diff --git a/glcdskin/object.c b/glcdskin/object.c index faa4758..5e63361 100644 --- a/glcdskin/object.c +++ b/glcdskin/object.c @@ -3,7 +3,6 @@ #include "skin.h" #include "cache.h" #include "function.h" -#include namespace GLCD { @@ -53,7 +52,9 @@ cSkinObject::cSkinObject(cSkinDisplay * Parent) mScrollSpeed(0), // scroll speed: default (0) mScrollTime(0), // scroll time interval: default (0) mScrollOffset(0), // scroll offset (pixels) - mCurrText(""), + mCurrText(""), // current text (for checks if text has changed) + mAltText(""), // alternative text source for text-objects + mAltCondition(NULL), // condition when alternative sources are used mObjects(NULL) { } @@ -79,7 +80,7 @@ cSkinObject::cSkinObject(const cSkinObject & Src) mCondition(Src.mCondition), mLastChange(0), mChangeDelay(-1), - mStoredImagePath(""), + mStoredImagePath(Src.mStoredImagePath), mImageFrameId(0), mScrollLoopMode(Src.mScrollLoopMode), mScrollLoopReached(Src.mScrollLoopReached), @@ -87,6 +88,8 @@ cSkinObject::cSkinObject(const cSkinObject & Src) mScrollTime(Src.mScrollTime), mScrollOffset(Src.mScrollOffset), mCurrText(Src.mCurrText), + mAltText(Src.mAltText), + mAltCondition(Src.mAltCondition), mObjects(NULL) { if (Src.mObjects) @@ -246,6 +249,19 @@ bool cSkinObject::ParseScrollTime(const std::string & Text) } +bool cSkinObject::ParseAltCondition(const std::string & Text) +{ + cSkinFunction *result = new cSkinFunction(this); + if (result->Parse(Text)) + { + delete mAltCondition; + mAltCondition = result; + return true; + } + return false; +} + + void cSkinObject::SetListIndex(int MaxItems, int Index) { mText.SetListIndex(MaxItems, Index); @@ -276,14 +292,12 @@ tSize cSkinObject::Size(void) const void cSkinObject::Render(GLCD::cBitmap * screen) { - struct timeval tv; uint64_t timestamp; if (mCondition != NULL && !mCondition->Evaluate()) return; - gettimeofday(&tv, 0); - timestamp = tv.tv_sec * 1000 + tv.tv_usec / 1000; + timestamp = mSkin->Config().Now(); switch (Type()) { @@ -436,7 +450,19 @@ void cSkinObject::Render(GLCD::cBitmap * screen) if (skinFont) { const cFont * font = skinFont->Font(); - std::string text = mText.Evaluate(); + std::string text = ""; + + // is an alternative text defined + alternative condition defined and true? + if (mAltCondition != NULL && mAltCondition->Evaluate() && (mAltText.size() != 0)) { + cSkinString *result = new cSkinString(this, false); + + if (result->Parse(mAltText)) { + text = (std::string) result->Evaluate(); + } + delete result; + } else { // nope: use the original text + text = (std::string) mText.Evaluate(); + } if (! (text == mCurrText) ) { mScrollOffset = 0; @@ -447,7 +473,6 @@ void cSkinObject::Render(GLCD::cBitmap * screen) if (mMultiline) { - // scrolling in multiline not supported at the moment mScrollLoopReached = true; // avoid check in NeedsUpdate() @@ -556,7 +581,7 @@ void cSkinObject::Render(GLCD::cBitmap * screen) if (updateScroll) { mScrollOffset += currScrollSpeed; - if ( x + Size().w + mScrollOffset > w+Size().w) { + if ( x + Size().w + mScrollOffset >= (w+Size().w - font->Width(" "))) { if (currScrollLoopMode == 1) // reset mScrollOffset in next step (else: string not redrawn when scroll done) mScrollLoopReached = true; @@ -650,6 +675,20 @@ bool cSkinObject::NeedsUpdate(uint64_t CurrentTime) int currScrollLoopMode = 1; // default values if no setup default values available int currScrollTime = 500; + std::string text = ""; + + // is an alternative text defined + alternative condition defined and true? + if (mAltCondition != NULL && mAltCondition->Evaluate() && (mAltText.size() != 0)) { + cSkinString *result = new cSkinString(this, false); + + if (result->Parse(mAltText)) { + text = (std::string) result->Evaluate(); + } + delete result; + } else { // nope: use the original text + text = (std::string) mText.Evaluate(); + } + // get default values from derived config-class if available tSkinToken token = tSkinToken(); token.Id = mSkin->Config().GetTokenId("ScrollMode"); @@ -669,8 +708,10 @@ bool cSkinObject::NeedsUpdate(uint64_t CurrentTime) if (mScrollTime > 0) currScrollTime = mScrollTime; - if (currScrollLoopMode > 0 && (!mScrollLoopReached || mScrollOffset) && - (int)(CurrentTime-mLastChange) >= currScrollTime + if ( (text != mCurrText) || + ( (currScrollLoopMode > 0) && (!mScrollLoopReached || mScrollOffset) && + ((int)(CurrentTime-mLastChange) >= currScrollTime) + ) ) { return true; diff --git a/glcdskin/object.h b/glcdskin/object.h index 188dd79..2e05a12 100644 --- a/glcdskin/object.h +++ b/glcdskin/object.h @@ -77,9 +77,9 @@ public: }; private: - cSkinDisplay * mDisplay; + cSkinDisplay * mDisplay; // parent display cSkin * mSkin; - eType mType; + eType mType; // type of object, one of enum eType tPoint mPos1; tPoint mPos2; eColor mColor; @@ -96,7 +96,7 @@ private: cSkinString mText; cSkinFunction * mCondition; - uint64_t mLastChange; // last change in dynamic object (scroll, frame change, ...) + uint64_t mLastChange; // timestamp: last change in dynamic object (scroll, frame change, ...) int mChangeDelay; // delay between two changes (frame change, scrolling, ...) // special values: -2: no further looping (mScrollLoopMode == 'once') // -1: not set (ie: not an animated image) @@ -111,7 +111,10 @@ private: int mScrollOffset; // scroll offset (pixels) std::string mCurrText; // current text (for checks if text has changed) - cSkinObjects * mObjects; // used for block objects such as + std::string mAltText; // alternative text source for text-objects + cSkinFunction * mAltCondition; // condition when alternative sources are used + + cSkinObjects * mObjects; // used for block objects such as public: cSkinObject(cSkinDisplay * parent); @@ -127,9 +130,11 @@ public: bool ParseWidth(const std::string &Text); bool ParseHeight(const std::string &Text); - bool ParseScrollLoopMode(const std::string & Text); - bool ParseScrollSpeed(const std::string & Text); - bool ParseScrollTime(const std::string & Text); + bool ParseScrollLoopMode(const std::string & Text); // parse scroll mode ([never|once|always]) + bool ParseScrollSpeed(const std::string & Text); // parse scroll speed + bool ParseScrollTime(const std::string & Text); // parse scroll time interval + + bool ParseAltCondition(const std::string &Text); // parse condition for alternative use (eg. alternative sources) void SetListIndex(int MaxItems, int Index); diff --git a/glcdskin/parser.c b/glcdskin/parser.c index cd76b24..ce6ed2a 100644 --- a/glcdskin/parser.c +++ b/glcdskin/parser.c @@ -217,6 +217,8 @@ bool StartElem(const std::string & name, std::map & att ATTRIB_OPT_FUNC("scrollmode", object->ParseScrollLoopMode); ATTRIB_OPT_FUNC("scrollspeed", object->ParseScrollSpeed); ATTRIB_OPT_FUNC("scrolltime", object->ParseScrollTime); + ATTRIB_OPT_STRING("alttext", object->mAltText); + ATTRIB_OPT_FUNC("altcondition", object->ParseAltCondition); #if 0 if (name == "blink") { -- cgit v1.2.3 From e7a6f08bbc22a5cc547303219c384ac9702e3066 Mon Sep 17 00:00:00 2001 From: mrwastl Date: Sat, 19 Jun 2010 10:23:31 +0200 Subject: text-object: fix to avoid stumbling scrolling --- glcdskin/object.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'glcdskin') diff --git a/glcdskin/object.c b/glcdskin/object.c index 5e63361..651b199 100644 --- a/glcdskin/object.c +++ b/glcdskin/object.c @@ -571,9 +571,15 @@ void cSkinObject::Render(GLCD::cBitmap * screen) } if (mScrollOffset) { + int corr_scrolloffset = mScrollOffset; + if ((int)(timestamp-mLastChange) < currScrollTime) { + corr_scrolloffset -= currScrollSpeed; + if (corr_scrolloffset < 0) + corr_scrolloffset = 0; + } w += font->Width(" "); std::string textdoubled = text + " " + text; - screen->DrawText(x, Pos().y, x + Size().w - 1, textdoubled, font, mColor, true, mScrollOffset); + screen->DrawText(x, Pos().y, x + Size().w - 1, textdoubled, font, mColor, true, corr_scrolloffset); } else { screen->DrawText(x, Pos().y, x + Size().w - 1, text, font, mColor, true, mScrollOffset); } -- cgit v1.2.3 From d1e66f46673f4ad6c5e3a69652a1def8501b4621 Mon Sep 17 00:00:00 2001 From: mrwastl Date: Sun, 27 Jun 2010 12:03:20 +0200 Subject: added new attribute 'valign' (vertical alignment) for text objects. format: valign="top|middle|bottom", default: "top"; changed debug output information to print 'graphlcd/skin' instead of 'Text2Skin' --- glcdskin/object.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++----- glcdskin/object.h | 9 +++++++++ glcdskin/parser.c | 27 ++++++++++++++------------- 3 files changed, 71 insertions(+), 18 deletions(-) (limited to 'glcdskin') diff --git a/glcdskin/object.c b/glcdskin/object.c index 651b199..ab00a44 100644 --- a/glcdskin/object.c +++ b/glcdskin/object.c @@ -36,6 +36,7 @@ cSkinObject::cSkinObject(cSkinDisplay * Parent) mArc(0), mDirection(0), mAlign(taLeft), + mVerticalAlign(tvaTop), mMultiline(false), mPath(this, false), mCurrent(this, false), @@ -71,6 +72,7 @@ cSkinObject::cSkinObject(const cSkinObject & Src) mArc(Src.mArc), mDirection(Src.mDirection), mAlign(Src.mAlign), + mVerticalAlign(Src.mVerticalAlign), mMultiline(Src.mMultiline), mPath(Src.mPath), mCurrent(Src.mCurrent), @@ -150,6 +152,19 @@ bool cSkinObject::ParseAlignment(const std::string & Text) return true; } +bool cSkinObject::ParseVerticalAlignment(const std::string & Text) +{ + if (Text == "top") + mVerticalAlign = tvaTop; + else if (Text == "middle") + mVerticalAlign = tvaMiddle; + else if (Text == "bottom") + mVerticalAlign = tvaBottom; + else + return false; + return true; +} + bool cSkinObject::ParseIntParam(const std::string &Text, int & Param) { if (isalpha(Text[0]) || Text[0] == '#') @@ -478,6 +493,20 @@ void cSkinObject::Render(GLCD::cBitmap * screen) std::vector lines; font->WrapText(Size().w, Size().h, text, lines); + + // vertical alignment, calculate y offset + int yoff = 0; + int diff = Size().h - lines.size() * font->LineHeight(); + switch (mVerticalAlign) { + case tvaMiddle: + yoff = (diff > 0) ? diff >> 1 : 0; + break; + case tvaBottom: + yoff = (diff > 0) ? diff : 0; + break; + default: yoff = 0; + } + for (size_t i = 0; i < lines.size(); i++) { int w = font->Width(lines[i]); @@ -493,11 +522,24 @@ void cSkinObject::Render(GLCD::cBitmap * screen) x += (Size().w - w) / 2; } } - screen->DrawText(x, Pos().y + i * font->LineHeight(), x + Size().w - 1, lines[i], font, mColor); + screen->DrawText(x, yoff + Pos().y + i * font->LineHeight(), x + Size().w - 1, lines[i], font, mColor); } } else { + // vertical alignment, calculate y offset + int yoff = 0; + int diff = Size().h - font->LineHeight(); + switch (mVerticalAlign) { + case tvaMiddle: + yoff = (diff > 0) ? diff >> 1 : 0; + break; + case tvaBottom: + yoff = (diff > 0) ? diff : 0; + break; + default: yoff = 0; + } + if (text.find('\t') != std::string::npos && mSkin->Config().GetTabPosition(0, Size().w, *font) > 0) { @@ -518,7 +560,7 @@ void cSkinObject::Render(GLCD::cBitmap * screen) { str = text.substr(pos1, pos2 - pos1); tabWidth = mSkin->Config().GetTabPosition(tab, Size().w, *font); - screen->DrawText(x, Pos().y, x + tabWidth - 1, str, font, mColor); + screen->DrawText(x, yoff + Pos().y, x + tabWidth - 1, str, font, mColor); pos1 = pos2 + 1; pos2 = text.find('\t', pos1); tabWidth += font->Width(' '); @@ -527,7 +569,7 @@ void cSkinObject::Render(GLCD::cBitmap * screen) tab++; } str = text.substr(pos1); - screen->DrawText(x, Pos().y, x + w - 1, str, font, mColor); + screen->DrawText(x, yoff + Pos().y, x + w - 1, str, font, mColor); } else { @@ -572,6 +614,7 @@ void cSkinObject::Render(GLCD::cBitmap * screen) if (mScrollOffset) { int corr_scrolloffset = mScrollOffset; + /* object update before scrolltime? use previous offset to avoid 'stumbling' scrolling */ if ((int)(timestamp-mLastChange) < currScrollTime) { corr_scrolloffset -= currScrollSpeed; if (corr_scrolloffset < 0) @@ -579,9 +622,9 @@ void cSkinObject::Render(GLCD::cBitmap * screen) } w += font->Width(" "); std::string textdoubled = text + " " + text; - screen->DrawText(x, Pos().y, x + Size().w - 1, textdoubled, font, mColor, true, corr_scrolloffset); + screen->DrawText(x, yoff + Pos().y, x + Size().w - 1, textdoubled, font, mColor, true, corr_scrolloffset); } else { - screen->DrawText(x, Pos().y, x + Size().w - 1, text, font, mColor, true, mScrollOffset); + screen->DrawText(x, yoff + Pos().y, x + Size().w - 1, text, font, mColor, true, mScrollOffset); } if (updateScroll) { diff --git a/glcdskin/object.h b/glcdskin/object.h index 2e05a12..0dd996d 100644 --- a/glcdskin/object.h +++ b/glcdskin/object.h @@ -51,6 +51,13 @@ enum eTextAlignment taRight }; +enum eTextVerticalAlignment +{ + tvaTop, + tvaMiddle, + tvaBottom +}; + class cSkinObject { friend bool StartElem(const std::string & name, std::map & attrs); @@ -88,6 +95,7 @@ private: int mArc; int mDirection; eTextAlignment mAlign; + eTextVerticalAlignment mVerticalAlign; bool mMultiline; cSkinString mPath; cSkinString mCurrent; @@ -125,6 +133,7 @@ public: bool ParseColor(const std::string &Text); bool ParseCondition(const std::string &Text); bool ParseAlignment(const std::string &Text); + bool ParseVerticalAlignment(const std::string &Text); bool ParseFontFace(const std::string &Text); bool ParseIntParam(const std::string &Text, int & Param); bool ParseWidth(const std::string &Text); diff --git a/glcdskin/parser.c b/glcdskin/parser.c index ce6ed2a..d42cfb8 100644 --- a/glcdskin/parser.c +++ b/glcdskin/parser.c @@ -24,19 +24,19 @@ namespace GLCD { #define TAG_ERR_REMAIN(_context) do { \ - syslog(LOG_ERR, "ERROR: Text2Skin: Unexpected tag %s within %s", \ + syslog(LOG_ERR, "ERROR: graphlcd/skin: Unexpected tag %s within %s", \ name.c_str(), _context); \ return false; \ } while (0) #define TAG_ERR_CHILD(_context) do { \ - syslog(LOG_ERR, "ERROR: Text2Skin: No child tag %s expected within %s", \ + syslog(LOG_ERR, "ERROR: graphlcd/skin: No child tag %s expected within %s", \ name.c_str(), _context); \ return false; \ } while (0) #define TAG_ERR_END(_context) do { \ - syslog(LOG_ERR, "ERROR: Text2Skin: Unexpected closing tag for %s within %s", \ + syslog(LOG_ERR, "ERROR: graphlcd/skin: Unexpected closing tag for %s within %s", \ name.c_str(), _context); \ return false; \ } while (0) @@ -49,7 +49,7 @@ namespace GLCD #define ATTRIB_MAN_STRING(_attr,_target) \ ATTRIB_OPT_STRING(_attr,_target) \ else { \ - syslog(LOG_ERR, "ERROR: Text2Skin: Mandatory attribute %s missing in tag %s", \ + syslog(LOG_ERR, "ERROR: graphlcd/skin: Mandatory attribute %s missing in tag %s", \ _attr, name.c_str()); \ return false; \ } @@ -59,7 +59,7 @@ namespace GLCD char *_e; const char *_t = attrs[_attr].c_str(); \ long _l = strtol(_t, &_e, 10); \ if (_e ==_t || *_e != '\0') { \ - syslog(LOG_ERR, "ERROR: Text2Skin: Invalid numeric value \"%s\" in attribute %s", \ + syslog(LOG_ERR, "ERROR: graphlcd/skin: Invalid numeric value \"%s\" in attribute %s", \ _t, _attr); \ return false; \ } else \ @@ -69,7 +69,7 @@ namespace GLCD #define ATTRIB_MAN_NUMBER(_attr,_target) \ ATTRIB_OPT_NUMBER(_attr,_target) \ else { \ - syslog(LOG_ERR, "ERROR: Text2Skin: Mandatory attribute %s missing in tag %s", \ + syslog(LOG_ERR, "ERROR: graphlcd/skin: Mandatory attribute %s missing in tag %s", \ _attr, name.c_str()); \ return false; \ } @@ -81,7 +81,7 @@ namespace GLCD else if (attrs[_attr] == "no") \ _target = false; \ else { \ - syslog(LOG_ERR, "ERROR: Text2Skin: Invalid boolean value \"%s\" in attribute %s", \ + syslog(LOG_ERR, "ERROR: graphlcd/skin: Invalid boolean value \"%s\" in attribute %s", \ attrs[_attr].c_str(), _attr); \ return false; \ } \ @@ -90,7 +90,7 @@ namespace GLCD #define ATTRIB_MAN_BOOL(_attr,_target) \ ATTRIB_OPT_BOOL(_attr,_target) \ else { \ - syslog(LOG_ERR, "ERROR: Text2Skin: Mandatory attribute %s missing in tag %s", \ + syslog(LOG_ERR, "ERROR: graphlcd/skin: Mandatory attribute %s missing in tag %s", \ _attr, name.c_str()); \ return false; \ } @@ -98,7 +98,7 @@ namespace GLCD #define ATTRIB_OPT_FUNC(_attr,_func) \ if (attrs.find(_attr) != attrs.end()) { \ if (!_func(attrs[_attr])) { \ - syslog(LOG_ERR, "ERROR: Text2Skin: Unexpected value %s for attribute %s", \ + syslog(LOG_ERR, "ERROR: graphlcd/skin: Unexpected value %s for attribute %s", \ attrs[_attr].c_str(), _attr); \ return false; \ } \ @@ -107,7 +107,7 @@ namespace GLCD #define ATTRIB_MAN_FUNC(_attr,_func) \ ATTRIB_OPT_FUNC(_attr,_func) \ else { \ - syslog(LOG_ERR, "ERROR: Text2Skin: Mandatory attribute %s missing in tag %s", \ + syslog(LOG_ERR, "ERROR: graphlcd/skin: Mandatory attribute %s missing in tag %s", \ _attr, name.c_str()); \ return false; \ } @@ -115,7 +115,7 @@ namespace GLCD #define ATTRIB_OPT_FUNC_PARAM(_attr,_func,_param) \ if (attrs.find(_attr) != attrs.end()) { \ if (!_func(attrs[_attr],_param)) { \ - syslog(LOG_ERR, "ERROR: Text2Skin: Unexpected value %s for attribute %s", \ + syslog(LOG_ERR, "ERROR: graphlcd/skin: Unexpected value %s for attribute %s", \ attrs[_attr].c_str(), _attr); \ return false; \ } \ @@ -124,7 +124,7 @@ namespace GLCD #define ATTRIB_MAN_FUNC_PARAM(_attr,_func,_param) \ ATTRIB_OPT_FUNC_PARAM(_attr,_func,_param) \ else { \ - syslog(LOG_ERR, "ERROR: Text2Skin: Mandatory attribute %s missing in tag %s", \ + syslog(LOG_ERR, "ERROR: graphlcd/skin: Mandatory attribute %s missing in tag %s", \ _attr, name.c_str()); \ return false; \ } @@ -212,6 +212,7 @@ bool StartElem(const std::string & name, std::map & att { ATTRIB_OPT_FUNC("color", object->ParseColor); ATTRIB_OPT_FUNC("align", object->ParseAlignment); + ATTRIB_OPT_FUNC("valign", object->ParseVerticalAlignment); ATTRIB_OPT_FUNC("font", object->ParseFontFace); ATTRIB_OPT_BOOL("multiline", object->mMultiline); ATTRIB_OPT_FUNC("scrollmode", object->ParseScrollLoopMode); @@ -377,7 +378,7 @@ cSkin * XmlParse(cSkinConfig & Config, const std::string & Name, const std::stri xml.SetCDataCB(CharData); if (xml.Parse() != 0) { - syslog(LOG_ERR, "ERROR: Text2Skin: Parse error in %s, line %d", fileName.c_str(), xml.LineNr()); + syslog(LOG_ERR, "ERROR: graphlcd/skin: Parse error in %s, line %d", fileName.c_str(), xml.LineNr()); delete skin; skin = NULL; delete display; -- cgit v1.2.3 From 1eabbd742da6d0ce442865b35c364e554d946022 Mon Sep 17 00:00:00 2001 From: andreas 'randy' weinberger Date: Wed, 26 Jan 2011 11:37:15 +0100 Subject: removed unneeded LDFLAGS see http://projects.vdr-developer.org/issues/530 --- glcdskin/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'glcdskin') diff --git a/glcdskin/Makefile b/glcdskin/Makefile index c67582c..9b3b867 100644 --- a/glcdskin/Makefile +++ b/glcdskin/Makefile @@ -38,7 +38,7 @@ $(DEPFILE): Makefile all: $(LIBNAME) $(LIBNAME): $(OBJS) - $(CXX) $(CXXFLAGS) -shared $(OBJS) $(LIBS) -Wl,-soname="$(BASENAME).$(VERMAJOR)" -o $@ + $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) $(LIBS) -Wl,-soname="$(BASENAME).$(VERMAJOR)" -o $@ ln -sf $(LIBNAME) $(BASENAME) install: all -- cgit v1.2.3