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(-) 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(-) 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(-) 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(-) 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(-) 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 --- glcddrivers/serdisp.c | 3 ++- glcdskin/config.c | 11 +++++++++ glcdskin/config.h | 2 ++ glcdskin/object.c | 63 ++++++++++++++++++++++++++++++++++++++++++--------- glcdskin/object.h | 19 ++++++++++------ glcdskin/parser.c | 2 ++ 6 files changed, 81 insertions(+), 19 deletions(-) diff --git a/glcddrivers/serdisp.c b/glcddrivers/serdisp.c index 7521105..b092659 100644 --- a/glcddrivers/serdisp.c +++ b/glcddrivers/serdisp.c @@ -341,7 +341,8 @@ int cDriverSerDisp::Init(void) fp_serdisp_feature(dd, FEATURE_REVERSE, config->invert); } else { /* standard options */ - fp_serdisp_setoption(dd, "ROTATE", config->upsideDown); + if (config->upsideDown) + fp_serdisp_setoption(dd, "ROTATE", config->upsideDown); fp_serdisp_setoption(dd, "CONTRAST", config->contrast); fp_serdisp_setoption(dd, "BACKLIGHT", config->backlight); fp_serdisp_setoption(dd, "INVERT", config->invert); 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(-) 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(-) 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 5c6cbd1eb40cf4508a42a6948b4a3166f65f7664 Mon Sep 17 00:00:00 2001 From: andreas 'randy' weinberger Date: Sat, 25 Sep 2010 10:03:41 +0200 Subject: fixed compiler warnings http://projects.vdr-developer.org/issues/352 --- glcddrivers/g15daemon.c | 2 +- glcddrivers/gu256x64-372.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/glcddrivers/g15daemon.c b/glcddrivers/g15daemon.c index 91f08c9..e275b38 100644 --- a/glcddrivers/g15daemon.c +++ b/glcddrivers/g15daemon.c @@ -33,7 +33,7 @@ #define G15_HEIGHT 43 -static int g15_send(int sock, char *buf, int len) +static int g15_send(int sock, const char *buf, int len) { int total = 0; int retval = 0; diff --git a/glcddrivers/gu256x64-372.c b/glcddrivers/gu256x64-372.c index 57ec981..52dab2a 100644 --- a/glcddrivers/gu256x64-372.c +++ b/glcddrivers/gu256x64-372.c @@ -131,7 +131,7 @@ int cDriverGU256X64_372::Init() RDLO = kStandardRDLO; CDHI = kStandardCDHI; CDLO = kStandardCDLO; - syslog(LOG_DEBUG, "%s: using standard wiring\n"); + syslog(LOG_DEBUG, "%s: using standard wiring\n", config->name.c_str()); } else if (config->options[i].value == kWiringWindows) { @@ -141,7 +141,7 @@ int cDriverGU256X64_372::Init() RDLO = kWindowsRDLO; CDHI = kWindowsCDHI; CDLO = kWindowsCDLO; - syslog(LOG_DEBUG, "%s: using windows wiring\n"); + syslog(LOG_DEBUG, "%s: using windows wiring\n", config->name.c_str()); } else { -- cgit v1.2.3 From c3aacc4722ff5c441b5c36b8443d96f90dbf0ae6 Mon Sep 17 00:00:00 2001 From: andreas 'randy' weinberger Date: Sat, 25 Sep 2010 10:16:54 +0200 Subject: added futuba MDM166A driver from andreas brachold http://projects.vdr-developer.org/issues/351 --- README | 3 +- docs/DRIVER.futabaMDM166A | 69 +++++++ glcddrivers/Makefile | 6 + glcddrivers/drivers.c | 10 + glcddrivers/drivers.h | 1 + glcddrivers/futabaMDM166A.c | 465 ++++++++++++++++++++++++++++++++++++++++++++ glcddrivers/futabaMDM166A.h | 75 +++++++ graphlcd.conf | 15 ++ 8 files changed, 643 insertions(+), 1 deletion(-) create mode 100644 docs/DRIVER.futabaMDM166A create mode 100644 glcddrivers/futabaMDM166A.c create mode 100644 glcddrivers/futabaMDM166A.h diff --git a/README b/README index 3256627..a4dc5c8 100644 --- a/README +++ b/README @@ -11,7 +11,7 @@ based on the graphlcd plugin for the Video Disc Recorder from 0.0.8 on maintained by Andreas Regel (andreas.regel AT powarman.de) from 0.1.5 on maintained by Wolfgang Astleitner (mrwastl AT users.sourceforge.net) & Andreas 'randy' Weinberger (vdr AT smue.org) - gu140x32f driver by Andreas Brachold (vdr04 AT deltab.de) + gu140x32f driver by Andreas Brachold (vdr07 AT deltab.de) gu256x64-372 driver by Andreas Weinberger (vdr AT smue.org) gu256x64-3xx0 driver by Ralf Mueller (ralf AT bj-ig.de) gu126x64D-K610A4 driver by Alexander Rieger (Alexander.Rieger AT inka.de) @@ -25,6 +25,7 @@ based on the graphlcd plugin for the Video Disc Recorder t6963c driver by Andreas Regel (andreas.regel AT powarman.de) noritake800 driver by Lucian Muresan (lucianm AT users.sourceforge.net) futaba dm140 driver by Stephan Skrodzki (skrodzki AT stevekist.de) + futama md166 driver by Andreas Brachold Project's homepage: http://graphlcd.berlios.de/ GIT repo: http://projects.vdr-developer.org/projects/show/graphlcd diff --git a/docs/DRIVER.futabaMDM166A b/docs/DRIVER.futabaMDM166A new file mode 100644 index 0000000..94e6179 --- /dev/null +++ b/docs/DRIVER.futabaMDM166A @@ -0,0 +1,69 @@ +--------------------------------------------------------------------- +GraphLCD driver library + +The futabaMDM166A driver +--------------------------------------------------------------------- + +Description +----------- +The Futaba MDM166A driver supports Futaba MDM166A VFD displays. +The VFD is connected to a PC's USB port. + +Installation Notes +------------------ + +You need installed library libhid to use the futabaMDM166A driver. +This library libhid is used to access and interact with a USB HID device. + + * http://libhid.alioth.debian.org/ + +If Debian used, you can install them with the command : + +#> apt-get install libhid-dev libhid0 + +Wirings +------- +The futabaMDM166A driver supports a connections on a USB port. + + +Configuration Parameters +------------------------ +The futabaMDM166A driver supports the following parameters in config file: + +Width + Sets the horizontal size of the display. If this parameter is not + given, a default value of 96 pixels is used. + +Height + Sets the vertical size of the display. If this parameter is not + given, a default value of 16 pixels is used. + +UpsideDown + Rotates the display output by 180 degrees. This might be useful, if + the LCD is mounted upside-down. + Possible values: 'yes', 'no' + Default value: 'no' + +Invert + Inverts the display. + Possible values: 'yes', 'no' + Default value: 'no' + +Brightness + Sets the brightness of your display's backlight. + Possible values: 0 <= x <= 100) + Default value: 50 + +RefreshDisplay + Normally, most of the drivers do not update the whole display, but + only the areas that have changed since last update. So it might be, + that some faulty pixels would stay a longer time. To avoid this, the + plugin makes a complete refresh from time to time. This parameter + defines how often a complete refresh will be done. + e.g.: A value of 5 means, that the plugin will make a complete + refresh on every 5th update. + A value of 0 completely disables complete refreshs. + Possible values: 0 <= x <= 50 + Default value: 50 + + diff --git a/glcddrivers/Makefile b/glcddrivers/Makefile index 671c581..331c829 100644 --- a/glcddrivers/Makefile +++ b/glcddrivers/Makefile @@ -18,6 +18,12 @@ OBJS = common.o config.o driver.o drivers.o port.o simlcd.o framebuffer.o gu140x HEADERS = config.h driver.h drivers.h +ifeq ($(shell pkg-config --exists libhid && echo 1), 1) +OBJS += futabaMDM166A.o +INCLUDES += $(shell pkg-config --cflags libhid) +LIBS += $(shell pkg-config --libs libhid) +DEFINES += -DHAVE_LIBHID +endif ### Implicit rules: diff --git a/glcddrivers/drivers.c b/glcddrivers/drivers.c index 08149df..946ab39 100644 --- a/glcddrivers/drivers.c +++ b/glcddrivers/drivers.c @@ -30,6 +30,9 @@ #include "dm140gink.h" #include "serdisp.h" #include "g15daemon.h" +#ifdef HAVE_LIBHID +#include "futabaMDM166A.h" +#endif namespace GLCD { @@ -52,6 +55,9 @@ tDriver drivers[] = {"network", kDriverNetwork}, {"gu126x64D-K610A4", kDriverGU126X64D_K610A4}, {"dm140gink", kDriverDM140GINK}, +#ifdef HAVE_LIBHID + {"futabaMDM166A", kDriverFutabaMDM166A}, +#endif {"serdisp", kDriverSerDisp}, {"g15daemon", kDriverG15daemon}, {"", kDriverUnknown} @@ -108,6 +114,10 @@ cDriver * CreateDriver(int driverID, cDriverConfig * config) return new cDriverGU126X64D_K610A4(config); case kDriverDM140GINK: return new cDriverDM140GINK(config); +#ifdef HAVE_LIBHID + case kDriverFutabaMDM166A: + return new cDriverFutabaMDM166A(config); +#endif case kDriverSerDisp: return new cDriverSerDisp(config); case kDriverG15daemon: diff --git a/glcddrivers/drivers.h b/glcddrivers/drivers.h index 08054ec..b088713 100644 --- a/glcddrivers/drivers.h +++ b/glcddrivers/drivers.h @@ -40,6 +40,7 @@ enum eDriver kDriverNetwork = 14, kDriverGU126X64D_K610A4 = 15, kDriverDM140GINK = 16, + kDriverFutabaMDM166A = 17, kDriverSerDisp = 100, kDriverG15daemon = 200 }; diff --git a/glcddrivers/futabaMDM166A.c b/glcddrivers/futabaMDM166A.c new file mode 100644 index 0000000..2fc8d67 --- /dev/null +++ b/glcddrivers/futabaMDM166A.c @@ -0,0 +1,465 @@ +/* + * GraphLCD driver library + * + * (C) 2010 Andreas Brachold + + * This file is released under the GNU General Public License. + * + * See the files README and COPYING for details. + * + */ + +#include +#include +#include +#include +#include + + +#include +#include +#include + +#include "common.h" +#include "config.h" +#include "futabaMDM166A.h" + +static const byte STATE_OFF = 0x00; //Symbol off +static const byte STATE_ON = 0x01; //Symbol on +static const byte STATE_ONHIGH = 0x02; //Symbol on, high intensity, can only be used with the volume symbols + +static const byte CMD_PREFIX = 0x1b; +static const byte CMD_SETCLOCK = 0x00; //Actualize the time of the display +static const byte CMD_SMALLCLOCK = 0x01; //Display small clock on display +static const byte CMD_BIGCLOCK = 0x02; //Display big clock on display +static const byte CMD_SETSYMBOL = 0x30; //Enable or disable symbol +static const byte CMD_SETDIMM = 0x40; //Set the dimming level of the display +static const byte CMD_RESET = 0x50; //Reset all configuration data to default and clear +static const byte CMD_SETRAM = 0x60; //Set the actual graphics RAM offset for next data write +static const byte CMD_SETPIXEL = 0x70; //Write pixel data to RAM of the display +static const byte CMD_TEST1 = 0xf0; //Show vertical test pattern +static const byte CMD_TEST2 = 0xf1; //Show horizontal test pattern + +static const byte TIME_12 = 0x00; //12 hours format +static const byte TIME_24 = 0x01; //24 hours format + +static const byte BRIGHT_OFF = 0x00; //Display off +static const byte BRIGHT_DIMM = 0x01; //Display dimmed +static const byte BRIGHT_FULL = 0x02; //Display full brightness + +namespace GLCD { + +cHIDQueue::cHIDQueue() { + hid = NULL; + bInit = false; +} + +cHIDQueue::~cHIDQueue() { + cHIDQueue::close(); +} + +bool cHIDQueue::open() +{ + HIDInterfaceMatcher matcher = { 0x19c2, 0x6a11, NULL, NULL, 0 }; + hid_return ret; + + /* see include/debug.h for possible values */ + hid_set_debug(HID_DEBUG_NONE); + hid_set_debug_stream(0); + /* passed directly to libusb */ + hid_set_usb_debug(0); + + ret = hid_init(); + if (ret != HID_RET_SUCCESS) { + syslog(LOG_ERR, "libhid: init - %s (%d)", hiderror(ret), ret); + return false; + } + bInit = true; + + hid = hid_new_HIDInterface(); + if (hid == 0) { + syslog(LOG_ERR, "libhid: hid_new_HIDInterface() failed, out of memory?\n"); + return false; + } + + ret = hid_force_open(hid, 0, &matcher, 3); + if (ret != HID_RET_SUCCESS) { + syslog(LOG_ERR, "libhid: open - %s (%d)", hiderror(ret), ret); + hid_close(hid); + hid_delete_HIDInterface(&hid); + hid = 0; + return false; + } + + while (!empty()) { + pop(); + } + //ret = hid_write_identification(stdout, hid); + //if (ret != HID_RET_SUCCESS) { + // syslog(LOG_INFO, "libhid: write_identification %s (%d)", hiderror(ret), ret); + // return false; + //} + return true; +} + +void cHIDQueue::close() { + hid_return ret; + if (hid != 0) { + ret = hid_close(hid); + if (ret != HID_RET_SUCCESS) { + syslog(LOG_ERR, "libhid: close - %s (%d)", hiderror(ret), ret); + } + + hid_delete_HIDInterface(&hid); + hid = 0; + } + if(bInit) { + ret = hid_cleanup(); + if (ret != HID_RET_SUCCESS) { + syslog(LOG_ERR, "libhid: cleanup - %s (%d)", hiderror(ret), ret); + } + bInit = false; + } +} + +void cHIDQueue::Cmd(const byte & cmd) { + this->push(CMD_PREFIX); + this->push(cmd); +} + +void cHIDQueue::Data(const byte & data) { + this->push(data); +} + +bool cHIDQueue::Flush() { + + if(empty()) + return true; + if(!isopen()) { + return false; + } + + int const PATH_OUT[1] = { 0xff7f0004 }; + char buf[64]; + hid_return ret; + + while (!empty()) { + buf[0] = (char) std::min((size_t)63,size()); + for(unsigned int i = 0;i < 63 && !empty();++i) { + buf[i+1] = (char) front(); //the first element in the queue + pop(); //remove the first element of the queue + } + ret = hid_set_output_report(hid, PATH_OUT, sizeof(PATH_OUT), buf, (buf[0] + 1)); + if (ret != HID_RET_SUCCESS) { + syslog(LOG_ERR, "libhid: set_output_report - %s (%d)", hiderror(ret), ret); + while (!empty()) { + pop(); + } + cHIDQueue::close(); + return false; + } + } + return true; +} + +const char *cHIDQueue::hiderror(hid_return ret) const +{ + switch(ret) { + case HID_RET_SUCCESS: + return "success"; + case HID_RET_INVALID_PARAMETER: + return "invalid parameter"; + case HID_RET_NOT_INITIALISED: + return "not initialized"; + case HID_RET_ALREADY_INITIALISED: + return "hid_init() already called"; + case HID_RET_FAIL_FIND_BUSSES: + return "failed to find any USB busses"; + case HID_RET_FAIL_FIND_DEVICES: + return "failed to find any USB devices"; + case HID_RET_FAIL_OPEN_DEVICE: + return "failed to open device"; + case HID_RET_DEVICE_NOT_FOUND: + return "device not found"; + case HID_RET_DEVICE_NOT_OPENED: + return "device not yet opened"; + case HID_RET_DEVICE_ALREADY_OPENED: + return "device already opened"; + case HID_RET_FAIL_CLOSE_DEVICE: + return "could not close device"; + case HID_RET_FAIL_CLAIM_IFACE: + return "failed to claim interface; is another driver using it?"; + case HID_RET_FAIL_DETACH_DRIVER: + return "failed to detach kernel driver"; + case HID_RET_NOT_HID_DEVICE: + return "not recognized as a HID device"; + case HID_RET_HID_DESC_SHORT: + return "HID interface descriptor too short"; + case HID_RET_REPORT_DESC_SHORT: + return "HID report descriptor too short"; + case HID_RET_REPORT_DESC_LONG: + return "HID report descriptor too long"; + case HID_RET_FAIL_ALLOC: + return "failed to allocate memory"; + case HID_RET_OUT_OF_SPACE: + return "no space left in buffer"; + case HID_RET_FAIL_SET_REPORT: + return "failed to set report"; + case HID_RET_FAIL_GET_REPORT: + return "failed to get report"; + case HID_RET_FAIL_INT_READ: + return "interrupt read failed"; + case HID_RET_NOT_FOUND: + return "not found"; +#ifdef HID_RET_TIMEOUT + case HID_RET_TIMEOUT: + return "timeout"; +#endif + } + return "unknown error"; +} + + +cDriverFutabaMDM166A::cDriverFutabaMDM166A(cDriverConfig * config) +: config(config) +, m_pDrawMem(0) +, m_pVFDMem(0) +{ + oldConfig = new cDriverConfig(*config); + m_nRefreshCounter = 0; + lastIconState = 0; +} + +cDriverFutabaMDM166A::~cDriverFutabaMDM166A() +{ + delete oldConfig; +} + +int cDriverFutabaMDM166A::Init() +{ + // default values + width = config->width; + if (width <= 0 || width > 96) + width = 96; + height = config->height; + if (height <= 0 || height > 16) + height = 16; + m_iSizeYb = ((height + 7) / 8); + + + /*for (unsigned int i = 0; i < config->options.size(); i++) + { + if (config->options[i].name == "") + { + } + }*/ + + *oldConfig = *config; + + // setup the memory array for the drawing array + m_pDrawMem = new unsigned char[width * m_iSizeYb]; + // setup the memory array for the display array + m_pVFDMem = new unsigned char[width * m_iSizeYb]; + if(!m_pDrawMem || !m_pVFDMem) { + syslog(LOG_ERR, "FutabaMDM166A: malloc frame buffer failed, out of memory?\n"); + return -1; + } + + // clear display + ClearVFDMem(); + Clear(); + + + if(!cHIDQueue::open()) { + return -1; + } + lastIconState = 0; + + cHIDQueue::Cmd(CMD_RESET); + // Set Display SetBrightness + SetBrightness(config->brightness ? config->brightness : 50); + + if(cHIDQueue::Flush()) { + syslog(LOG_INFO, "%s: initialized.\n", config->name.c_str()); + return 0; + } + return -1; +} + +int cDriverFutabaMDM166A::DeInit() +{ + cHIDQueue::close(); + + if (m_pVFDMem) + delete[] m_pVFDMem; + if (m_pDrawMem) + delete[] m_pDrawMem; + + return 0; +} + +int cDriverFutabaMDM166A::CheckSetup() +{ + if (config->width != oldConfig->width || + config->height != oldConfig->height) + { + DeInit(); + return Init(); + } + + if (config->brightness != oldConfig->brightness) + { + oldConfig->brightness = config->brightness; + SetBrightness(config->brightness); + } + + if (config->upsideDown != oldConfig->upsideDown || + config->invert != oldConfig->invert) + { + oldConfig->upsideDown = config->upsideDown; + oldConfig->invert = config->invert; + return 1; + } + return 0; +} + +void cDriverFutabaMDM166A::ClearVFDMem() +{ + for (unsigned int n = 0; m_pVFDMem && n < (width * m_iSizeYb); n++) + m_pVFDMem[n] = 0x00; +} + +void cDriverFutabaMDM166A::Clear() +{ + for (unsigned int n = 0; m_pDrawMem && n < (width * m_iSizeYb); n++) + m_pDrawMem[n] = 0x00; +} + +void cDriverFutabaMDM166A::SetPixel(int x, int y) +{ + byte c; + int n; + + if (!m_pDrawMem) + return; + + if (x >= width || x < 0) + return; + if (y >= height || y < 0) + return; + + if (config->upsideDown) + { + x = width - 1 - x; + y = height - 1 - y; + } + + n = x + ((y / 8) * width); + c = 0x80 >> (y % 8); + + m_pDrawMem[n] |= c; +} + +void cDriverFutabaMDM166A::Set8Pixels(int x, int y, byte data) +{ + int n; + + // x - pos is'nt mayby align to 8 + x &= 0xFFF8; + + for (n = 0; n < 8; ++n) + { + if (data & (0x80 >> n)) // if bit is set + SetPixel(x + n, y); + } +} + +void cDriverFutabaMDM166A::Refresh(bool refreshAll) +{ + unsigned int n, x, yb; + + if (!m_pVFDMem || !m_pDrawMem) + return; + + bool doRefresh = false; + unsigned int nWidth = width; + unsigned int minX = nWidth; + unsigned int maxX = 0; + + int s = CheckSetup(); + if(s < 0) + return; + if (s > 0) + refreshAll = true; + + for (yb = 0; yb < m_iSizeYb; ++yb) + for (x = 0; x < nWidth; ++x) + { + n = x + (yb * nWidth); + if (m_pVFDMem[n] != m_pDrawMem[n]) + { + m_pVFDMem[n] = m_pDrawMem[n]; + minX = std::min(minX, x); + maxX = std::max(maxX, x + 1); + doRefresh = true; + } + } + + m_nRefreshCounter = (m_nRefreshCounter + 1) % (config->refreshDisplay ? config->refreshDisplay : 50); + + if (!refreshAll && !m_nRefreshCounter) + refreshAll = true; + + if (refreshAll || doRefresh) + { + if (refreshAll) { + minX = 0; + maxX = nWidth; + // and reset RefreshCounter + m_nRefreshCounter = 0; + } + + maxX = std::min(maxX, nWidth); + + unsigned int nData = (maxX-minX) * m_iSizeYb; + if(nData) { + // send data to display, controller + cHIDQueue::Cmd(CMD_SETRAM); + cHIDQueue::Data(minX*m_iSizeYb); + cHIDQueue::Cmd(CMD_SETPIXEL); + cHIDQueue::Data(nData); + + for (x = minX; x < maxX; ++x) + for (yb = 0; yb < m_iSizeYb; ++yb) + { + n = x + (yb * nWidth); + cHIDQueue::Data((m_pVFDMem[n]) ^ (config->invert ? 0xff : 0x00)); + } + } + } + cHIDQueue::Flush(); +} + +/** + * Sets the brightness of the display. + * + * \param nBrightness The value the brightness (less 33% = off + * more then 66% = highest brightness,else half brightness ). + */ +void cDriverFutabaMDM166A::SetBrightness(unsigned int percent) +{ + byte nBrightness = 1; + if (percent < 33) { + nBrightness = 0; + } else if (nBrightness > 66) { + nBrightness = 2; + } + cHIDQueue::Cmd(CMD_SETDIMM); + cHIDQueue::Data(nBrightness); +} + +} + + + + diff --git a/glcddrivers/futabaMDM166A.h b/glcddrivers/futabaMDM166A.h new file mode 100644 index 0000000..ca1783d --- /dev/null +++ b/glcddrivers/futabaMDM166A.h @@ -0,0 +1,75 @@ +/* + * GraphLCD driver library + * + * (C) 2010 Andreas Brachold + * + * This file is released under the GNU General Public License. + * + * See the files README and COPYING for details. + * + */ + +#ifndef _GLCDDRIVERS_FutabaMDM166A_H_ +#define _GLCDDRIVERS_FutabaMDM166A_H_ + +#include "driver.h" + +#define HAVE_STDBOOL_H +#include +#include + +namespace GLCD +{ + class cDriverConfig; + + class cHIDQueue : public std::queue { + HIDInterface* hid; + bool bInit; + public: + cHIDQueue(); + virtual ~cHIDQueue(); + virtual bool open(); + virtual void close(); + virtual bool isopen() const { return hid != 0; } + void Cmd(const byte & cmd); + void Data(const byte & data); + bool Flush(); + private: + const char *hiderror(hid_return ret) const; + }; + + class cDriverFutabaMDM166A : public cDriver, cHIDQueue + { + cDriverConfig * config; + cDriverConfig * oldConfig; + unsigned char *m_pDrawMem; // the draw "memory" + unsigned char *m_pVFDMem; // the double buffed display "memory" + unsigned int m_iSizeYb; + unsigned int m_nRefreshCounter; + unsigned int lastIconState; + int CheckSetup(); + protected: + void ClearVFDMem(); + void SetPixel(int x, int y); + void icons(unsigned int state); + bool SendCmdClock(); + bool SendCmdShutdown(); + + public: + cDriverFutabaMDM166A(cDriverConfig * config); + virtual ~cDriverFutabaMDM166A(); + + virtual int Init(); + virtual int DeInit(); + + virtual void Clear(); + virtual void Set8Pixels(int x, int y, byte data); + virtual void Refresh(bool refreshAll = false); + + virtual void SetBrightness(unsigned int percent); + }; +}; +#endif + + + diff --git a/graphlcd.conf b/graphlcd.conf index 2b0e784..2aa61a2 100644 --- a/graphlcd.conf +++ b/graphlcd.conf @@ -560,3 +560,18 @@ Driver=dm140gink # USB ID activy 5xx: #Vendor=0x1509 #Product=0x925d + +######################################################################## +[futabaMDM166A] +# futabaMDM166A driver +# This is an driver module for Futaba MDM166A VFD displays. +# The VFD is built-in in Targa HTPC cases and connected to USB port. +# Default size: 96 x 16 +Driver=futabaMDM166A + +#Width=96 +#Height=16 +#UpsideDown=no +#Invert=no +#Brightness=50 +#RefreshDisplay=1000 -- cgit v1.2.3 From 994019efd59985df5345973149155a5153144965 Mon Sep 17 00:00:00 2001 From: andreas 'randy' weinberger Date: Tue, 5 Oct 2010 21:11:05 +0200 Subject: added some more Device sample entries for serdisp/usb --- graphlcd.conf | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/graphlcd.conf b/graphlcd.conf index 2aa61a2..9809ebf 100644 --- a/graphlcd.conf +++ b/graphlcd.conf @@ -429,6 +429,8 @@ Driver=serdisp #Controller=nokia7110 #Controller=sed1335 Controller=optrex323 +#Controller=l4m132c +#Controller=l4m320t # Options # Pass display specific options @@ -465,6 +467,9 @@ Controller=optrex323 Device=/dev/parport0 #Port=0x378 +#Device=HID:/dev/usb/hiddev0 +#Device=HID:/dev/hiddev0 +#Device=USB:USB:4243/ee20 # Linux4Media 320T TouchLCD #UpsideDown=no #Invert=no Contrast=5 -- cgit v1.2.3 From d983dcdf6867b915af7e7c0772ce4ba52d8d3451 Mon Sep 17 00:00:00 2001 From: andreas 'randy' weinberger Date: Tue, 2 Nov 2010 21:16:02 +0100 Subject: release of version 0.1.7 --- HISTORY | 8 ++++++++ README | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/HISTORY b/HISTORY index 6835f2e..45ba00b 100644 --- a/HISTORY +++ b/HISTORY @@ -1,6 +1,14 @@ GraphLCD base package Revision History -------------------------------------- +2010-11-02: version 0.1.7 +- added futuba MDM166A driver from andreas brachold: http://projects.vdr-developer.org/issues/351 +- fixed compiler warnings: http://projects.vdr-developer.org/issues/352 +- added new attribute 'valign' (vertical alignment) for text objects. +- text-object: fix to avoid stumbling scrolling +- text-object: added support for alternative text / alternative condition +- glcdskin: bugfixing and improvements + 2010-04-23: version 0.1.6_1 - added additional wiring for GU256x64-372 driver (thanks to mentox, http://www.vdr-portal.de/board/thread.php?postid=895721#post895721) diff --git a/README b/README index a4dc5c8..0a69458 100644 --- a/README +++ b/README @@ -65,7 +65,7 @@ Installation and Configuration: ------------------------------- 1. Unpack the tarball to an arbitrary directory. - tar xzf graphlcd-base-0.1.2.tgz + tar xzf graphlcd-base-0.1.7.tgz 2. Configure if you want FreeType2 support by commenting/uncommenting HAVE_FREETYPE2 in Make.config. -- cgit v1.2.3 From 18e1e3c9659734afbf602b0589f24af24160875a Mon Sep 17 00:00:00 2001 From: andreas 'randy' weinberger Date: Sat, 6 Nov 2010 10:15:45 +0100 Subject: increased version number --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a659568..d41a4b8 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ # PROJECT = graphlcd-base -VERSION = 0.1.6 +VERSION = 0.1.7 ARCHIVE = $(PROJECT)-$(VERSION) PACKAGE = $(ARCHIVE) TMPDIR = /tmp -- cgit v1.2.3 From 555363f9bc97a9180b4816462c48fe8d139fde8f Mon Sep 17 00:00:00 2001 From: andreas 'randy' weinberger Date: Fri, 3 Dec 2010 21:15:38 +0100 Subject: fixed compile error see http://www.vdrportal.de/board/thread.php?postid=959952#post959952 --- Makefile | 2 +- README | 2 +- glcdgraphics/font.c | 1 + graphlcd.conf | 3 ++- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index d41a4b8..20c9062 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ # PROJECT = graphlcd-base -VERSION = 0.1.7 +VERSION = 0.1.8 ARCHIVE = $(PROJECT)-$(VERSION) PACKAGE = $(ARCHIVE) TMPDIR = /tmp diff --git a/README b/README index 0a69458..e717dbb 100644 --- a/README +++ b/README @@ -65,7 +65,7 @@ Installation and Configuration: ------------------------------- 1. Unpack the tarball to an arbitrary directory. - tar xzf graphlcd-base-0.1.7.tgz + tar xzf graphlcd-base-0.1.8.tgz 2. Configure if you want FreeType2 support by commenting/uncommenting HAVE_FREETYPE2 in Make.config. diff --git a/glcdgraphics/font.c b/glcdgraphics/font.c index 1735cf2..359e136 100644 --- a/glcdgraphics/font.c +++ b/glcdgraphics/font.c @@ -18,6 +18,7 @@ #include #include +#include #include #include "common.h" diff --git a/graphlcd.conf b/graphlcd.conf index 9809ebf..146fa57 100644 --- a/graphlcd.conf +++ b/graphlcd.conf @@ -296,6 +296,7 @@ Driver=ks0108 Device=/dev/parport0 #Port=0x378 #Width=128 +Width=192 #Height=64 #UpsideDown=no #Invert=no @@ -388,7 +389,7 @@ Device=/dev/parport0 #Height=128 #UpsideDown=no #Invert=no -#RefreshDisplay=1 +RefreshDisplay=1 # Wiring # Select the type of wiring your display is connected with. -- cgit v1.2.3 From 95eaf695028119e0f469f2d6e3f1890d7e45f458 Mon Sep 17 00:00:00 2001 From: andreas 'randy' weinberger Date: Sun, 23 Jan 2011 11:43:31 +0100 Subject: changed graphlcd.conf back http://projects.vdr-developer.org/issues/524 --- graphlcd.conf | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/graphlcd.conf b/graphlcd.conf index 146fa57..b0b989e 100644 --- a/graphlcd.conf +++ b/graphlcd.conf @@ -295,10 +295,10 @@ Driver=ks0108 Device=/dev/parport0 #Port=0x378 -#Width=128 -Width=192 +Width=128 +#Width=192 #Height=64 -#UpsideDown=no +UpsideDown=yes #Invert=no #AdjustTiming=0 #RefreshDisplay=1 @@ -389,7 +389,7 @@ Device=/dev/parport0 #Height=128 #UpsideDown=no #Invert=no -RefreshDisplay=1 +#RefreshDisplay=1 # Wiring # Select the type of wiring your display is connected with. -- cgit v1.2.3 From b40c55ddd61a52dc67e5c4a51a7da9923e26db13 Mon Sep 17 00:00:00 2001 From: andreas 'randy' weinberger Date: Sun, 23 Jan 2011 11:45:04 +0100 Subject: fixed typo --- graphlcd.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphlcd.conf b/graphlcd.conf index b0b989e..b5db6f5 100644 --- a/graphlcd.conf +++ b/graphlcd.conf @@ -298,7 +298,7 @@ Device=/dev/parport0 Width=128 #Width=192 #Height=64 -UpsideDown=yes +#UpsideDown=no #Invert=no #AdjustTiming=0 #RefreshDisplay=1 -- 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 --- glcddrivers/Makefile | 2 +- glcdgraphics/Makefile | 2 +- glcdskin/Makefile | 2 +- tools/convpic/Makefile | 2 +- tools/crtfont/Makefile | 2 +- tools/genfont/Makefile | 2 +- tools/lcdtestpattern/Makefile | 2 +- tools/showpic/Makefile | 2 +- tools/showtext/Makefile | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/glcddrivers/Makefile b/glcddrivers/Makefile index 331c829..acb1577 100644 --- a/glcddrivers/Makefile +++ b/glcddrivers/Makefile @@ -28,7 +28,7 @@ endif ### Implicit rules: %.o: %.c - $(CXX) $(CXXFLAGS) $(LDFLAGS) -c $(DEFINES) $(INCLUDES) $< + $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $< # Dependencies: diff --git a/glcdgraphics/Makefile b/glcdgraphics/Makefile index 399b3ad..7f7ff74 100644 --- a/glcdgraphics/Makefile +++ b/glcdgraphics/Makefile @@ -21,7 +21,7 @@ HEADERS = bitmap.h font.h glcd.h image.h imagefile.h pbm.h ### Implicit rules: %.o: %.c - $(CXX) $(CXXFLAGS) $(LDFLAGS) -c $(DEFINES) $(INCLUDES) $< + $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $< # Dependencies: 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 diff --git a/tools/convpic/Makefile b/tools/convpic/Makefile index f666b4e..3932e5f 100644 --- a/tools/convpic/Makefile +++ b/tools/convpic/Makefile @@ -18,7 +18,7 @@ all: $(PRGNAME) # Implicit rules: %.o: %.c - $(CXX) $(CXXFLAGS) $(LDFLAGS) -c $(DEFINES) $(INCLUDES) $< + $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $< # Dependencies: diff --git a/tools/crtfont/Makefile b/tools/crtfont/Makefile index 29f0b5e..bcd100f 100644 --- a/tools/crtfont/Makefile +++ b/tools/crtfont/Makefile @@ -17,7 +17,7 @@ all: $(PRGNAME) # Implicit rules: %.o: %.c - $(CXX) $(CXXFLAGS) $(LDFLAGS) -c $(DEFINES) $(INCLUDES) $< + $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $< # Dependencies: diff --git a/tools/genfont/Makefile b/tools/genfont/Makefile index bed4d9c..14837b0 100644 --- a/tools/genfont/Makefile +++ b/tools/genfont/Makefile @@ -20,7 +20,7 @@ all: $(PRGNAME) # Implicit rules: %.o: %.c - $(CXX) $(CXXFLAGS) $(LDFLAGS) -c $(DEFINES) $(INCLUDES) $< + $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $< # Dependencies: diff --git a/tools/lcdtestpattern/Makefile b/tools/lcdtestpattern/Makefile index da165e2..504e27c 100644 --- a/tools/lcdtestpattern/Makefile +++ b/tools/lcdtestpattern/Makefile @@ -18,7 +18,7 @@ all: $(PRGNAME) # Implicit rules: %.o: %.c - $(CXX) $(CXXFLAGS) $(LDFLAGS) -c $(DEFINES) $(INCLUDES) $< + $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $< # Dependencies: diff --git a/tools/showpic/Makefile b/tools/showpic/Makefile index 17e88d3..5d15d61 100644 --- a/tools/showpic/Makefile +++ b/tools/showpic/Makefile @@ -18,7 +18,7 @@ all: $(PRGNAME) # Implicit rules: %.o: %.c - $(CXX) $(CXXFLAGS) $(LDFLAGS) -c $(DEFINES) $(INCLUDES) $< + $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $< # Dependencies: diff --git a/tools/showtext/Makefile b/tools/showtext/Makefile index 1da8fb5..d0d963a 100644 --- a/tools/showtext/Makefile +++ b/tools/showtext/Makefile @@ -18,7 +18,7 @@ all: $(PRGNAME) # Implicit rules: %.o: %.c - $(CXX) $(CXXFLAGS) $(LDFLAGS) -c $(DEFINES) $(INCLUDES) $< + $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $< # Dependencies: -- cgit v1.2.3 From 8e6e0230a9b1f9b0fb4ee7a02e88def95367c12b Mon Sep 17 00:00:00 2001 From: andreas 'randy' weinberger Date: Sun, 13 Feb 2011 14:47:04 +0100 Subject: release of version 0.1.9 --- HISTORY | 5 +++++ Makefile | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/HISTORY b/HISTORY index 45ba00b..c22c8a9 100644 --- a/HISTORY +++ b/HISTORY @@ -1,6 +1,11 @@ GraphLCD base package Revision History -------------------------------------- +2011-02-13: version 0.1.9 +- fixed compile error. http://www.vdrportal.de/board/thread.php?postid=959952#post959952 +- changed graphlcd.conf back to original: http://projects.vdr-developer.org/issues/524 +- removed unneeded LDFLAGS: http://projects.vdr-developer.org/issues/530 + 2010-11-02: version 0.1.7 - added futuba MDM166A driver from andreas brachold: http://projects.vdr-developer.org/issues/351 - fixed compiler warnings: http://projects.vdr-developer.org/issues/352 diff --git a/Makefile b/Makefile index 20c9062..d5ffe7b 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ # PROJECT = graphlcd-base -VERSION = 0.1.8 +VERSION = 0.1.9 ARCHIVE = $(PROJECT)-$(VERSION) PACKAGE = $(ARCHIVE) TMPDIR = /tmp -- cgit v1.2.3 From c29885101605c3711d65b6f7e20e6be3dd7f9837 Mon Sep 17 00:00:00 2001 From: andreas 'randy' weinberger Date: Sun, 6 Mar 2011 10:08:49 +0100 Subject: added STRIP-option for gentoo see http://www.vdr-portal.de/board/thread.php?postid=905301#post905301 --- Make.config | 3 +++ tools/convpic/Makefile | 2 +- tools/crtfont/Makefile | 2 +- tools/genfont/Makefile | 2 +- tools/lcdtestpattern/Makefile | 2 +- tools/showpic/Makefile | 2 +- tools/showtext/Makefile | 2 +- 7 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Make.config b/Make.config index cdafd16..017f2b6 100644 --- a/Make.config +++ b/Make.config @@ -14,6 +14,9 @@ CXXFLAGS = -g -O2 -Wall -Woverloaded-virtual LDCONFIG = ldconfig +### strip binaries when installing by default, but allow easyly supressing it +STRIP ?= -s + ### The directory environment: ifndef $(DESTDIR) diff --git a/tools/convpic/Makefile b/tools/convpic/Makefile index 3932e5f..da5494b 100644 --- a/tools/convpic/Makefile +++ b/tools/convpic/Makefile @@ -36,7 +36,7 @@ $(PRGNAME): $(OBJS) install: $(PRGNAME) install -d $(BINDIR) - install -m 755 -o root -g root -s $(PRGNAME) $(BINDIR) + install -m 755 -o root -g root $(STRIP) $(PRGNAME) $(BINDIR) uninstall: rm -f $(BINDIR)/$(PRGNAME) diff --git a/tools/crtfont/Makefile b/tools/crtfont/Makefile index bcd100f..592d123 100644 --- a/tools/crtfont/Makefile +++ b/tools/crtfont/Makefile @@ -35,7 +35,7 @@ $(PRGNAME): $(OBJS) install: $(PRGNAME) install -d $(BINDIR) - install -m 755 -o root -g root -s $(PRGNAME) $(BINDIR) + install -m 755 -o root -g root $(STRIP) $(PRGNAME) $(BINDIR) uninstall: rm -f $(BINDIR)/$(PRGNAME) diff --git a/tools/genfont/Makefile b/tools/genfont/Makefile index 14837b0..e516a21 100644 --- a/tools/genfont/Makefile +++ b/tools/genfont/Makefile @@ -38,7 +38,7 @@ $(PRGNAME): $(OBJS) install: $(PRGNAME) install -d $(BINDIR) - install -m 755 -o root -g root -s $(PRGNAME) $(BINDIR) + install -m 755 -o root -g root $(STRIP) $(PRGNAME) $(BINDIR) uninstall: rm -f $(BINDIR)/$(PRGNAME) diff --git a/tools/lcdtestpattern/Makefile b/tools/lcdtestpattern/Makefile index 504e27c..51b1123 100644 --- a/tools/lcdtestpattern/Makefile +++ b/tools/lcdtestpattern/Makefile @@ -36,7 +36,7 @@ $(PRGNAME): $(OBJS) install: $(PRGNAME) install -d $(BINDIR) - install -m 755 -o root -g root -s $(PRGNAME) $(BINDIR) + install -m 755 -o root -g root $(STRIP) $(PRGNAME) $(BINDIR) uninstall: rm -f $(BINDIR)/$(PRGNAME) diff --git a/tools/showpic/Makefile b/tools/showpic/Makefile index 5d15d61..52c1850 100644 --- a/tools/showpic/Makefile +++ b/tools/showpic/Makefile @@ -36,7 +36,7 @@ $(PRGNAME): $(OBJS) install: $(PRGNAME) install -d $(BINDIR) - install -m 755 -o root -g root -s $(PRGNAME) $(BINDIR) + install -m 755 -o root -g root $(STRIP) $(PRGNAME) $(BINDIR) uninstall: rm -f $(BINDIR)/$(PRGNAME) diff --git a/tools/showtext/Makefile b/tools/showtext/Makefile index d0d963a..d43c986 100644 --- a/tools/showtext/Makefile +++ b/tools/showtext/Makefile @@ -36,7 +36,7 @@ $(PRGNAME): $(OBJS) install: $(PRGNAME) install -d $(BINDIR) - install -m 755 -o root -g root -s $(PRGNAME) $(BINDIR) + install -m 755 -o root -g root $(STRIP) $(PRGNAME) $(BINDIR) uninstall: rm -f $(BINDIR)/$(PRGNAME) -- cgit v1.2.3 From 4395e8475a82a1a83f34eb85a47d8c87de3beaba Mon Sep 17 00:00:00 2001 From: andreas 'randy' weinberger Date: Sun, 6 Mar 2011 11:27:21 +0100 Subject: debug windows wiring see http://www.vdr-portal.de/board/thread.php?postid=943119#post943119 --- glcddrivers/gu256x64-372.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/glcddrivers/gu256x64-372.c b/glcddrivers/gu256x64-372.c index 52dab2a..049253e 100644 --- a/glcddrivers/gu256x64-372.c +++ b/glcddrivers/gu256x64-372.c @@ -74,10 +74,10 @@ const unsigned char kStandardRDLO = 0x00; // const unsigned char kStandardCDHI = 0x00; // 17 / nSELECT const unsigned char kStandardCDLO = 0x08; // -const unsigned char kWindowsWRHI = 0x00; // 01 / nSTRB -const unsigned char kWindowsWRLO = 0x01; // +const unsigned char kWindowsWRHI = 0x01; // 01 / nSTRB +const unsigned char kWindowsWRLO = 0x00; // const unsigned char kWindowsRDHI = 0x00; // 14 / nLINEFEED -const unsigned char kWindowsRDLO = 0x02; // +const unsigned char kWindowsRDLO = 0x00; // const unsigned char kWindowsCDHI = 0x00; // 17 / nSELECT const unsigned char kWindowsCDLO = 0x08; // -- cgit v1.2.3 From bc1a54cc721e10dfb73fec89e367354b46a0eeb1 Mon Sep 17 00:00:00 2001 From: Lucian Muresan Date: Sun, 6 Mar 2011 23:39:43 +0100 Subject: glcddrivers/noritake800 timings fixes --- docs/DRIVER.noritake800 | 4 ++-- glcddrivers/noritake800.c | 49 ++++++++++++++++++++++++----------------------- glcddrivers/noritake800.h | 2 +- graphlcd.conf | 6 +++--- 4 files changed, 31 insertions(+), 30 deletions(-) diff --git a/docs/DRIVER.noritake800 b/docs/DRIVER.noritake800 index 1962900..410d999 100644 --- a/docs/DRIVER.noritake800 +++ b/docs/DRIVER.noritake800 @@ -93,7 +93,7 @@ Brightness Possible values: 0 <= x <= 100) Default value: 100 -AdjustTiming ---> not used in this driver (if there are problems, please report) +AdjustTiming To get a timing that is as accurate as possible, the drivers measure the time for port commands (see: benchmark in syslog). You might decrease or increase the time to wait after port commands with this @@ -101,7 +101,7 @@ AdjustTiming ---> not used in this driver (if there are problems, please report) Possible values: -50 <= x <= 50 Default value: 0 -RefreshDisplay ---> not used in this driver (if there are problems, please report) +RefreshDisplay Normally, most of the drivers do not update the whole display, but only the areas that have changed since last update. So it might be, that some faulty pixels would stay a longer time. To avoid this, the diff --git a/glcddrivers/noritake800.c b/glcddrivers/noritake800.c index 5a386a5..b1c5718 100644 --- a/glcddrivers/noritake800.c +++ b/glcddrivers/noritake800.c @@ -27,7 +27,7 @@ * This file is released under the GNU General Public License. Refer * to the COPYING file distributed with this package. * - * (c) 2004 Lucian Muresan + * (c) 2004 - 2011 Lucian Muresan */ #include @@ -270,19 +270,18 @@ int cDriverNoritake800::Init() m_pport->Claim(); syslog(LOG_DEBUG, "%s: benchmark started.\n", m_Config->name.c_str()); gettimeofday(&tv1, 0); - int nBenchFactor = 100000; - for (x = 0; x < nBenchFactor; x++) + int nBenchIterations = 10000; + for (x = 0; x < nBenchIterations; x++) { m_pport->WriteData(x % 0x100); } gettimeofday(&tv2, 0); nSleepDeInit(); - //m_nTimingAdjustCmd = ((tv2.tv_sec - tv1.tv_sec) * 10000 + (tv2.tv_usec - tv1.tv_usec)) / 1000; - m_nTimingAdjustCmd = long(double((tv2.tv_sec - tv1.tv_sec) * 1000 + (tv2.tv_usec - tv1.tv_usec)) / double(nBenchFactor)); + // calculate port command duration in nanoseconds + m_nTimingAdjustCmd = long(double((tv2.tv_sec - tv1.tv_sec) * 1000000000 + (tv2.tv_usec - tv1.tv_usec) * 1000) / double(nBenchIterations)); syslog(LOG_DEBUG, "%s: benchmark stopped. Time for Port Command: %ldns\n", m_Config->name.c_str(), m_nTimingAdjustCmd); m_pport->Release(); - // initialize display N800Cmd(Init800A); @@ -326,31 +325,34 @@ int cDriverNoritake800::Init() void cDriverNoritake800::Refresh(bool refreshAll) { - // - // for VFD displays, we can safely ignore refreshAll, as they are "sticky" - // int xb, yb; if (CheckSetup() > 0) - refreshAll = true; // we don't use it + refreshAll = true; if (!m_pVFDMem || !m_pDrawMem) return; -// // just refresh if the time needed between refreshes is up -// m_nRefreshCounter = (m_nRefreshCounter + 1) % m_Config->refreshDisplay; -// if(!m_nRefreshCounter) -// { + if (m_Config->refreshDisplay > 0) + { + m_nRefreshCounter = (m_nRefreshCounter + 1) % m_Config->refreshDisplay; + if (m_nRefreshCounter == 0) + refreshAll = true; + } + m_pport->Claim(); for (xb = 0; xb < width; ++xb) { for (yb = 0; yb < m_iSizeYb; ++yb) { - if (m_pVFDMem[xb][yb] != m_pDrawMem[xb][yb]) + // if differenet or explicitly refresh all + if ( m_pVFDMem[xb][yb] != m_pDrawMem[xb][yb] || + refreshAll ) { m_pVFDMem[xb][yb] = m_pDrawMem[xb][yb]; - // reset RefreshCounter - m_nRefreshCounter = 0; + // reset RefreshCounter if doing a full refresh + if (refreshAll) + m_nRefreshCounter = 0; // actually write to display N800WriteByte( (m_pVFDMem[xb][yb]) ^ ((m_Config->invert != 0) ? 0xff : 0x00), @@ -361,7 +363,6 @@ void cDriverNoritake800::Refresh(bool refreshAll) } } m_pport->Release(); -// } } void cDriverNoritake800::N800Cmd(unsigned char data) @@ -373,13 +374,13 @@ void cDriverNoritake800::N800Cmd(unsigned char data) m_pport->WriteControl(m_pWiringMaskCache[0x00]); // write to data port m_pport->WriteData(data); - //nSleep(100 + (100 * m_Config->adjustTiming) - m_nTimingAdjustCmd); + nSleep(100 + (100 * m_Config->adjustTiming) - m_nTimingAdjustCmd); // set /WR on the control port m_pport->WriteControl(m_pWiringMaskCache[VFDSGN_WR]); - //nSleep(100 + (100 * m_Config->adjustTiming) - m_nTimingAdjustCmd); + nSleep(100 + (100 * m_Config->adjustTiming) - m_nTimingAdjustCmd); // reset /WR on the control port m_pport->WriteControl(m_pWiringMaskCache[0x00]); - //nSleep(100 + (100 * m_Config->adjustTiming) - m_nTimingAdjustCmd); + nSleep(100 + (100 * m_Config->adjustTiming) - m_nTimingAdjustCmd); // set direction to "port_input" m_pport->WriteControl(LPT_CTL_HI_DIR | m_pWiringMaskCache[0x00]); } @@ -393,13 +394,13 @@ void cDriverNoritake800::N800Data(unsigned char data) m_pport->WriteControl(m_pWiringMaskCache[VFDSGN_CD]); // write to data port m_pport->WriteData(data); - //nSleep(100 + (100 * m_Config->adjustTiming) - m_nTimingAdjustCmd); + nSleep(100 + (100 * m_Config->adjustTiming) - m_nTimingAdjustCmd); // set /WR on the control port m_pport->WriteControl(m_pWiringMaskCache[VFDSGN_CD | VFDSGN_WR]); - //nSleep(100 + (100 * m_Config->adjustTiming) - m_nTimingAdjustCmd); + nSleep(100 + (100 * m_Config->adjustTiming) - m_nTimingAdjustCmd); // reset /WR on the control port m_pport->WriteControl(m_pWiringMaskCache[VFDSGN_CD]); - //nSleep(100 + (100 * m_Config->adjustTiming) - m_nTimingAdjustCmd); + nSleep(100 + (100 * m_Config->adjustTiming) - m_nTimingAdjustCmd); // set direction to "port_input" m_pport->WriteControl(LPT_CTL_HI_DIR | m_pWiringMaskCache[0x00]); } diff --git a/glcddrivers/noritake800.h b/glcddrivers/noritake800.h index cb2dfb0..f34c476 100644 --- a/glcddrivers/noritake800.h +++ b/glcddrivers/noritake800.h @@ -27,7 +27,7 @@ * This file is released under the GNU General Public License. Refer * to the COPYING file distributed with this package. * - * (c) 2004 Lucian Muresan + * (c) 2004 - 2011 Lucian Muresan */ #ifndef _GLCDDRIVERS_NORITAKE800_H_ diff --git a/graphlcd.conf b/graphlcd.conf index b5db6f5..4c0ea52 100644 --- a/graphlcd.conf +++ b/graphlcd.conf @@ -99,7 +99,7 @@ WaitPriority=0 # decrease or increase the time to wait after port commands with this # parameter. Normally, there is no need to change this parameter. # (used by gu140x32f, gu256x64-372, gu256x64-3900, hd61830, ks0108, -# sed1330, sed1520, gu126x64D-K610A4) +# sed1330, sed1520, gu126x64D-K610A4, noritake800) # Possible values: -50 <= x <= 50 # Default value: 0 # @@ -497,8 +497,8 @@ Height=64 #UpsideDown=no #Invert=no Brightness=50 -#AdjustTiming=0 # not used -#RefreshDisplay=0 # not used +AdjustTiming=50 +RefreshDisplay=50 # Wiring # Select the type of wiring your display is connected with. -- cgit v1.2.3 From 686e1855f3d31bdf94b3af537c5b8061eec438e7 Mon Sep 17 00:00:00 2001 From: Zoolooc Date: Mon, 7 Mar 2011 00:51:27 +0100 Subject: UTF8 support fixes --- glcdgraphics/bitmap.c | 31 ++++- glcdgraphics/bitmap.h | 2 +- glcdgraphics/font.c | 360 +++++++++++++++++++++++++++++--------------------- glcdgraphics/font.h | 21 ++- 4 files changed, 260 insertions(+), 154 deletions(-) diff --git a/glcdgraphics/bitmap.c b/glcdgraphics/bitmap.c index d5ba159..8570da5 100644 --- a/glcdgraphics/bitmap.c +++ b/glcdgraphics/bitmap.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "bitmap.h" #include "common.h" @@ -506,7 +507,11 @@ int cBitmap::DrawText(int x, int y, int xmax, const std::string & text, const cF int xt; int yt; int i; - char c; + int c; + int c0; + int c1; + int c2; + int c3; int start; clip(x, 0, width - 1); @@ -547,6 +552,28 @@ int cBitmap::DrawText(int x, int y, int xmax, const std::string & text, const cF for (i = start; i < (int) text.length(); i++) { c = text[i]; + c0 = text[i]; + c1 = (i+1 < text.length()) ? text[i+1] : 0; + c2 = (i+2 < text.length()) ? text[i+2] : 0; + c3 = (i+3 < text.length()) ? text[i+3] : 0; + c0 &=0xff; c1 &=0xff; c2 &=0xff; c3 &=0xff; + + if( c0 >= 0xc2 && c0 <= 0xdf && c1 >= 0x80 && c1 <= 0xbf ){ //2 byte UTF-8 sequence found + i+=1; + c = ((c0&0x1f)<<6) | (c1&0x3f); + }else if( (c0 == 0xE0 && c1 >= 0xA0 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf) + || (c0 >= 0xE1 && c1 <= 0xEC && c1 >= 0x80 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf) + || (c0 == 0xED && c1 >= 0x80 && c1 <= 0x9f && c2 >= 0x80 && c2 <= 0xbf) + || (c0 >= 0xEE && c0 <= 0xEF && c1 >= 0x80 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf) ){ //3 byte UTF-8 sequence found + c = ((c0&0x0f)<<4) | ((c1&0x3f)<<6) | (c2&0x3f); + i+=2; + }else if( (c0 == 0xF0 && c1 >= 0x90 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf && c3 >= 0x80 && c3 <= 0xbf) + || (c0 >= 0xF1 && c0 >= 0xF3 && c1 >= 0x80 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf && c3 >= 0x80 && c3 <= 0xbf) + || (c0 == 0xF4 && c1 >= 0x80 && c1 <= 0x8f && c2 >= 0x80 && c2 <= 0xbf && c3 >= 0x80 && c3 <= 0xbf) ){ //4 byte UTF-8 sequence found + c = ((c0&0x07)<<2) | ((c1&0x3f)<<4) | ((c2&0x3f)<<6) | (c3&0x3f); + i+=3; + } + if (xt > xmax) { i = text.length(); @@ -589,7 +616,7 @@ int cBitmap::DrawText(int x, int y, int xmax, const std::string & text, const cF return xt; } -int cBitmap::DrawCharacter(int x, int y, int xmax, char c, const cFont * font, +int cBitmap::DrawCharacter(int x, int y, int xmax, int c, const cFont * font, eColor color, int skipPixels) { const cBitmap * charBitmap; diff --git a/glcdgraphics/bitmap.h b/glcdgraphics/bitmap.h index b6446a0..9e5c7e6 100644 --- a/glcdgraphics/bitmap.h +++ b/glcdgraphics/bitmap.h @@ -60,7 +60,7 @@ public: void DrawBitmap(int x, int y, const cBitmap & bitmap, eColor color); int DrawText(int x, int y, int xmax, const std::string & text, const cFont * font, eColor color = clrBlack, bool proportional = true, int skipPixels = 0); - int DrawCharacter(int x, int y, int xmax, char c, const cFont * font, + int DrawCharacter(int x, int y, int xmax, int c, const cFont * font, eColor color = clrBlack, int skipPixels = 0); cBitmap * SubBitmap(int x1, int y1, int x2, int y2) const; diff --git a/glcdgraphics/font.c b/glcdgraphics/font.c index 359e136..2730b91 100644 --- a/glcdgraphics/font.c +++ b/glcdgraphics/font.c @@ -20,6 +20,7 @@ #include #include +#include #include "common.h" #include "font.h" @@ -27,7 +28,6 @@ #ifdef HAVE_FREETYPE2 #include #include FT_FREETYPE_H -#include #endif namespace GLCD @@ -56,6 +56,64 @@ static const uint32_t kCharHeaderSize = 4; //}; //#pragma pack() +#ifdef HAVE_FREETYPE2 + +class cBitmapCache +{ +private: +protected: + cBitmapCache *next; // next bitmap + cBitmap *ptr; + int charcode; +public: + cBitmapCache(); + ~cBitmapCache(); + + void PushBack(int ch, cBitmap *bitmap); + cBitmap *GetBitmap(int ch) const; +}; + +cBitmapCache::cBitmapCache() +: next(NULL), + ptr(NULL), + charcode(0) +{ +} + +cBitmapCache::~cBitmapCache() +{ + delete ptr; + delete next; +} + +void cBitmapCache::PushBack(int ch, cBitmap *bitmap) +{ + if (!ptr) + { + charcode = ch; + ptr = bitmap; + } + else if (!next) + { + next = new cBitmapCache(); + next->ptr = bitmap; + next->charcode = ch; + } else + next->PushBack(ch, bitmap); +} + +cBitmap *cBitmapCache::GetBitmap(int ch) const +{ + if (ptr && charcode==ch) + return ptr; + else if (next) + return next->GetBitmap(ch); + else + return NULL; +} + +#endif + cFont::cFont() { Init(); @@ -70,6 +128,7 @@ bool cFont::LoadFNT(const std::string & fileName) { // cleanup if we already had a loaded font Unload(); + loadedFontType = lftFNT; //original fonts FILE * fontFile; int i; @@ -186,6 +245,7 @@ bool cFont::LoadFT2(const std::string & fileName, const std::string & encoding, { // cleanup if we already had a loaded font Unload(); + loadedFontType = lftFT2; // ft2 fonts #ifdef HAVE_FREETYPE2 if (access(fileName.c_str(), F_OK) != 0) { @@ -195,7 +255,6 @@ bool cFont::LoadFT2(const std::string & fileName, const std::string & encoding, // file exists FT_Library library; FT_Face face; - FT_GlyphSlot slot; int error = FT_Init_FreeType(&library); if (error) @@ -224,140 +283,20 @@ bool cFont::LoadFT2(const std::string & fileName, const std::string & encoding, return false; } - // set slot - slot = face->glyph; - // set Size FT_Set_Char_Size(face, 0, size * 64, 0, 0); - wchar_t utf_buff[256]; - if (dingBats) - { -/* - FT_CharMap charmap = 0; - for (int n = 0; n < face->num_charmaps; n++) - { - if (face->charmaps[n]->platform_id == 3 && - face->charmaps[n]->encoding_id == 0) - { - charmap = face->charmaps[n]; - //break; - } - } - if (charmap) - syslog(LOG_ERR, "cFont::LoadFT2: platform_id: %d, encoding_id: %d", charmap->platform_id, charmap->encoding_id); - error = FT_Set_Charmap(_face, charmap); - if (error) - { - syslog(LOG_ERR, "cFont::LoadFT2: FT_Select_Charmap encoding not supported: %d", charmap->encoding_id); - } -*/ - } - else - { - iconv_t cd; - if ((cd = iconv_open("WCHAR_T", encoding.c_str())) == (iconv_t) -1) - { - syslog(LOG_ERR, "cFont::LoadFT2: Iconv encoding not supported: %s", encoding.c_str()); - error = FT_Done_Face(face); - syslog(LOG_ERR, "cFont::LoadFT2: FT_Done_Face(..) returned (%d)", error); - error = FT_Done_FreeType(library); - syslog(LOG_ERR, "cFont::LoadFT2: FT_Done_FreeType(..) returned (%d)", error); - return false; - } - for (int c = 0; c < 256; c++) - { - char char_buff = c; - wchar_t wchar_buff; - char * in_buff,* out_buff; - size_t in_len, out_len, count; - - in_len = 1; - out_len = 4; - in_buff = (char *) &char_buff; - out_buff = (char *) &wchar_buff; - count = iconv(cd, &in_buff, &in_len, &out_buff, &out_len); - if ((size_t) -1 == count) - { - utf_buff[c] = 0; - } - utf_buff[c] = wchar_buff; - } - iconv_close(cd); - } - // get some global parameters - totalHeight = (face->size->metrics.ascender >> 6) - (face->size->metrics.descender >> 6); - totalWidth = face->size->metrics.max_advance >> 6; - totalAscent = face->size->metrics.ascender >> 6; - lineHeight = face->size->metrics.height >> 6; - spaceBetween = 0; -#if 0 - syslog(LOG_DEBUG, "cFont::LoadFT2: totalHeight = %d", totalHeight); - syslog(LOG_DEBUG, "cFont::LoadFT2: totalWidth = %d", totalWidth); - syslog(LOG_DEBUG, "cFont::LoadFT2: totalAscent = %d", totalAscent); - syslog(LOG_DEBUG, "cFont::LoadFT2: lineHeight = %d", lineHeight); - syslog(LOG_DEBUG, "cFont::LoadFT2: spaceBetween = %d", spaceBetween); -#endif - // render glyphs for ASCII codes 0 to 255 in our bitmap class - FT_UInt glyph_index; - int num_char; - - for (num_char = 0; num_char < 256; num_char++) - { - if (dingBats) - { - //Get FT char index & load the char - error = FT_Load_Char(face, num_char, FT_LOAD_DEFAULT); - } - else - { - //Get FT char index - glyph_index = FT_Get_Char_Index(face, utf_buff[num_char]); - //Load the char - error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); - } - if (error) - { - syslog(LOG_ERR, "cFont::LoadFT2: ERROR when calling FT_Load_Glyph: %x", error); - } + SetTotalHeight( (face->size->metrics.ascender >> 6) - (face->size->metrics.descender >> 6) ); + SetTotalWidth ( face->size->metrics.max_advance >> 6 ); + SetTotalAscent( face->size->metrics.ascender >> 6 ); + SetLineHeight ( face->size->metrics.height >> 6 ); + SetSpaceBetween( 0 ); - // convert to a mono bitmap - error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_MONO); - if (error) - { - syslog(LOG_ERR, "cFont::LoadFT2: ERROR when calling FT_Render_Glyph: %x", error); - } + ft2_library = library; + ft2_face = face; - // now, fill our pixel data - cBitmap * charBitmap = new cBitmap(face->glyph->advance.x >> 6, totalHeight); - charBitmap->Clear(); - unsigned char * bufPtr = face->glyph->bitmap.buffer; - unsigned char pixel; - for (int y = 0; y < face->glyph->bitmap.rows; y++) - { - for (int x = 0; x < face->glyph->bitmap.width; x++) - { - pixel = (bufPtr[x / 8] >> (7 - x % 8)) & 1; - if (pixel) - charBitmap->DrawPixel((face->glyph->metrics.horiBearingX >> 6) + x, - (face->size->metrics.ascender >> 6) - (face->glyph->metrics.horiBearingY >> 6) + y, - GLCD::clrBlack); - } - bufPtr += face->glyph->bitmap.pitch; - } - SetCharacter((char) num_char, charBitmap); - } - error = FT_Done_Face(face); - if (error) - { - syslog(LOG_ERR, "cFont::LoadFT2: FT_Done_Face(..) returned (%d)", error); - } - error = FT_Done_FreeType(library); - if (error) - { - syslog(LOG_ERR, "cFont::LoadFT2: FT_Done_FreeType(..) returned (%d)", error); - } + characters_cache=new cBitmapCache(); return true; #else syslog(LOG_ERR, "cFont::LoadFT2: glcdgraphics was compiled without FreeType2 support!!!"); @@ -365,10 +304,11 @@ bool cFont::LoadFT2(const std::string & fileName, const std::string & encoding, #endif } -int cFont::Width(char ch) const +int cFont::Width(int ch) const { - if (characters[(unsigned char) ch]) - return characters[(unsigned char) ch]->Width(); + const cBitmap *bitmap = GetCharacter(ch); + if (bitmap) + return bitmap->Width(); else return 0; } @@ -377,15 +317,36 @@ int cFont::Width(const std::string & str) const { unsigned int i; int sum = 0; + int c,c0,c1,c2,c3,symcount=0; for (i = 0; i < str.length(); i++) { - sum += Width(str[i]); - } - if (str.length() > 1) - { - sum += spaceBetween * (str.length() - 1); + c = str[i]; + c0 = str[i]; + c1 = (i+1 < str.length()) ? str[i+1] : 0; + c2 = (i+2 < str.length()) ? str[i+2] : 0; + c3 = (i+3 < str.length()) ? str[i+3] : 0; + c0 &=0xff; c1 &=0xff; c2 &=0xff; c3 &=0xff; + + if( c0 >= 0xc2 && c0 <= 0xdf && c1 >= 0x80 && c1 <= 0xbf ){ //2 byte UTF-8 sequence found + i+=1; + c = ((c0&0x1f)<<6) | (c1&0x3f); + }else if( (c0 == 0xE0 && c1 >= 0xA0 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf) + || (c0 >= 0xE1 && c1 <= 0xEC && c1 >= 0x80 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf) + || (c0 == 0xED && c1 >= 0x80 && c1 <= 0x9f && c2 >= 0x80 && c2 <= 0xbf) + || (c0 >= 0xEE && c0 <= 0xEF && c1 >= 0x80 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf) ){ //3 byte UTF-8 sequence found + c = ((c0&0x0f)<<4) | ((c1&0x3f)<<6) | (c2&0x3f); + i+=2; + }else if( (c0 == 0xF0 && c1 >= 0x90 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf && c3 >= 0x80 && c3 <= 0xbf) + || (c0 >= 0xF1 && c0 >= 0xF3 && c1 >= 0x80 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf && c3 >= 0x80 && c3 <= 0xbf) + || (c0 == 0xF4 && c1 >= 0x80 && c1 <= 0x8f && c2 >= 0x80 && c2 <= 0xbf && c3 >= 0x80 && c3 <= 0xbf) ){ //4 byte UTF-8 sequence found + c = ((c0&0x07)<<2) | ((c1&0x3f)<<4) | ((c2&0x3f)<<6) | (c3&0x3f); + i+=3; + } + symcount++; + sum += Width(c); } + sum += spaceBetween * (symcount - 1); return sum; } @@ -394,21 +355,45 @@ int cFont::Width(const std::string & str, unsigned int len) const unsigned int i; int sum = 0; - for (i = 0; i < str.length() && i < len; i++) - { - sum += Width(str[i]); - } - if (std::min(str.length(), (size_t) len) > 1) + int c,c0,c1,c2,c3,symcount=0; + + for (i = 0; i < str.length() && symcount < len; i++) { - sum += spaceBetween * (std::min(str.length(), (size_t) len) - 1); + c = str[i]; + c0 = str[i]; + c1 = (i+1 < str.length()) ? str[i+1] : 0; + c2 = (i+2 < str.length()) ? str[i+2] : 0; + c3 = (i+3 < str.length()) ? str[i+3] : 0; + c0 &=0xff; c1 &=0xff; c2 &=0xff; c3 &=0xff; + + if( c0 >= 0xc2 && c0 <= 0xdf && c1 >= 0x80 && c1 <= 0xbf ){ //2 byte UTF-8 sequence found + i+=1; + c = ((c0&0x1f)<<6) | (c1&0x3f); + }else if( (c0 == 0xE0 && c1 >= 0xA0 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf) + || (c0 >= 0xE1 && c1 <= 0xEC && c1 >= 0x80 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf) + || (c0 == 0xED && c1 >= 0x80 && c1 <= 0x9f && c2 >= 0x80 && c2 <= 0xbf) + || (c0 >= 0xEE && c0 <= 0xEF && c1 >= 0x80 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf) ){ //3 byte UTF-8 sequence found + c = ((c0&0x0f)<<4) | ((c1&0x3f)<<6) | (c2&0x3f); + i+=2; + }else if( (c0 == 0xF0 && c1 >= 0x90 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf && c3 >= 0x80 && c3 <= 0xbf) + || (c0 >= 0xF1 && c0 >= 0xF3 && c1 >= 0x80 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf && c3 >= 0x80 && c3 <= 0xbf) + || (c0 == 0xF4 && c1 >= 0x80 && c1 <= 0x8f && c2 >= 0x80 && c2 <= 0xbf && c3 >= 0x80 && c3 <= 0xbf) ){ //4 byte UTF-8 sequence found + c = ((c0&0x07)<<2) | ((c1&0x3f)<<4) | ((c2&0x3f)<<6) | (c3&0x3f); + i+=3; + } + symcount++; + sum += Width(c); } + sum += spaceBetween * (symcount - 1); + return sum; } -int cFont::Height(char ch) const +int cFont::Height(int ch) const { - if (characters[(unsigned char) ch]) - return characters[(unsigned char) ch]->Height(); + const cBitmap *bitmap = GetCharacter(ch); + if (bitmap) + return bitmap->Height(); else return 0; } @@ -433,13 +418,79 @@ int cFont::Height(const std::string & str, unsigned int len) const return sum; } -const cBitmap * cFont::GetCharacter(char ch) const +const cBitmap * cFont::GetCharacter(int ch) const { +#ifdef HAVE_FREETYPE2 + if ( loadedFontType == lftFT2 ) { + //lookup in cache + cBitmap *ptr=characters_cache->GetBitmap(ch); + if (ptr) + return ptr; + + FT_Face face = (FT_Face) ft2_face; + FT_UInt glyph_index; + //Get FT char index + glyph_index = FT_Get_Char_Index(face, ch); + + //Load the char + int error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); + if (error) + { + syslog(LOG_ERR, "cFont::LoadFT2: ERROR when calling FT_Load_Glyph: %x", error); + return NULL; + } + + FT_Render_Mode rmode = FT_RENDER_MODE_MONO; +#if ( (FREETYPE_MAJOR == 2 && FREETYPE_MINOR == 1 && FREETYPE_PATCH >= 7) || (FREETYPE_MAJOR == 2 && FREETYPE_MINOR == 2 && FREETYPE_PATCH <= 1) ) + if (ch == 32) rmode = FT_RENDER_MODE_NORMAL; +#endif + + // convert to a mono bitmap + error = FT_Render_Glyph(face->glyph, rmode); + if (error) + { + syslog(LOG_ERR, "cFont::LoadFT2: ERROR when calling FT_Render_Glyph: %x", error); + return NULL; + } else { + // now, fill our pixel data + cBitmap *charBitmap = new cBitmap(face->glyph->advance.x >> 6, TotalHeight()); + charBitmap->Clear(); + unsigned char * bufPtr = face->glyph->bitmap.buffer; + unsigned char pixel; + for (int y = 0; y < face->glyph->bitmap.rows; y++) + { + for (int x = 0; x < face->glyph->bitmap.width; x++) + { + pixel = (bufPtr[x / 8] >> (7 - x % 8)) & 1; + if (pixel) + charBitmap->DrawPixel((face->glyph->metrics.horiBearingX >> 6) + x, + (face->size->metrics.ascender >> 6) - (face->glyph->metrics.horiBearingY >> 6) + y, + GLCD::clrBlack); + } + bufPtr += face->glyph->bitmap.pitch; + } + + // adjust maxwidth if necessary + //if (totalWidth < charBitmap->Width()) + // totalWidth = charBitmap->Width(); + + characters_cache->PushBack(ch, charBitmap); + return charBitmap; + } + return NULL; // if any + } // else +#endif return characters[(unsigned char) ch]; } void cFont::SetCharacter(char ch, cBitmap * bitmapChar) { +#ifdef HAVE_FREETYPE2 + if ( loadedFontType == lftFT2 ) { + syslog(LOG_ERR, "cFont::SetCharacter: is not supported with FreeType2 fonts!!!"); + return; + } +#endif // adjust maxwidth if necessary if (totalWidth < bitmapChar->Width()) totalWidth = bitmapChar->Width(); @@ -463,6 +514,12 @@ void cFont::Init() { characters[i] = NULL; } + loadedFontType = lftFNT; +#ifdef HAVE_FREETYPE2 + ft2_library = NULL; + ft2_face = NULL; + characters_cache = NULL; +#endif } void cFont::Unload() @@ -475,6 +532,13 @@ void cFont::Unload() delete characters[i]; } } +#ifdef HAVE_FREETYPE2 + delete characters_cache; + if (ft2_face) + FT_Done_Face((FT_Face)ft2_face); + if (ft2_library) + FT_Done_FreeType((FT_Library)ft2_library); +#endif // re-init Init(); } diff --git a/glcdgraphics/font.h b/glcdgraphics/font.h index b36d5ac..6bf72f5 100644 --- a/glcdgraphics/font.h +++ b/glcdgraphics/font.h @@ -23,8 +23,18 @@ namespace GLCD { +class cBitmapCache; + class cFont { +public: + enum eLoadedFntType + { + // native glcd font loaded + lftFNT, + // freetype2 font loaded + lftFT2 + }; private: int totalWidth; int totalHeight; @@ -33,6 +43,11 @@ private: int lineHeight; cBitmap * characters[256]; + eLoadedFntType loadedFontType; + + cBitmapCache *characters_cache; + void *ft2_library; //FT_Library + void *ft2_face; //FT_Face protected: void Init(); void Unload(); @@ -56,14 +71,14 @@ public: void SetSpaceBetween(int width) { spaceBetween = width; }; void SetLineHeight(int height) { lineHeight = height; }; - int Width(char ch) const; + int Width(int ch) const; int Width(const std::string & str) const; int Width(const std::string & str, unsigned int len) const; - int Height(char ch) const; + int Height(int ch) const; int Height(const std::string & str) const; int Height(const std::string & str, unsigned int len) const; - const cBitmap * GetCharacter(char ch) const; + const cBitmap * GetCharacter(int ch) const; void SetCharacter(char ch, cBitmap * bitmapChar); void WrapText(int Width, int Height, std::string & Text, -- cgit v1.2.3 From 379c2fefdeb4ae8d55add2d9ae44ea274cb7937b Mon Sep 17 00:00:00 2001 From: Zoolooc Date: Mon, 7 Mar 2011 14:35:38 +0100 Subject: memory cleanups --- glcddrivers/image.c | 7 +++++++ glcddrivers/noritake800.c | 4 ++-- tools/showpic/showpic.c | 1 + tools/showtext/showtext.c | 1 + 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/glcddrivers/image.c b/glcddrivers/image.c index 9c71006..a07ce54 100644 --- a/glcddrivers/image.c +++ b/glcddrivers/image.c @@ -30,6 +30,7 @@ cDriverImage::cDriverImage(cDriverConfig * config) cDriverImage::~cDriverImage() { + DeInit(); delete oldConfig; } @@ -71,9 +72,15 @@ int cDriverImage::Init() int cDriverImage::DeInit() { if (newLCD) + { delete[] newLCD; + newLCD = 0; + } if (oldLCD) + { delete[] oldLCD; + oldLCD = 0; + } return 0; } diff --git a/glcddrivers/noritake800.c b/glcddrivers/noritake800.c index b1c5718..89ae898 100644 --- a/glcddrivers/noritake800.c +++ b/glcddrivers/noritake800.c @@ -170,13 +170,13 @@ cDriverNoritake800::~cDriverNoritake800() int x; if (m_pVFDMem) - for (x = 0; x < (width + 7) / 8; x++) + for (x = 0; x < width; x++) { delete[] m_pVFDMem[x]; } delete[] m_pVFDMem; if (m_pDrawMem) - for (x = 0; x < (width + 7) / 8; x++) + for (x = 0; x < width; x++) { delete[] m_pDrawMem[x]; } diff --git a/tools/showpic/showpic.c b/tools/showpic/showpic.c index f17f361..ebeb73f 100644 --- a/tools/showpic/showpic.c +++ b/tools/showpic/showpic.c @@ -219,6 +219,7 @@ int main(int argc, char *argv[]) if (glcd.Load(image, picFile) == false) { fprintf(stderr, "ERROR: Failed loading file %s\n", picFile.c_str()); + delete lcd; return 8; } diff --git a/tools/showtext/showtext.c b/tools/showtext/showtext.c index 2621db1..333d9e3 100644 --- a/tools/showtext/showtext.c +++ b/tools/showtext/showtext.c @@ -274,6 +274,7 @@ int main(int argc, char *argv[]) lcd->DeInit(); delete lcd; + delete bitmap; return 0; } -- cgit v1.2.3 From aacb78d4335e498417835d518c64b33acb58c749 Mon Sep 17 00:00:00 2001 From: Zoolooc Date: Mon, 7 Mar 2011 22:12:13 +0100 Subject: consolidate Uf8 sequence detection in Utf8CodeAdjustCounter --- glcdgraphics/bitmap.c | 30 +++--------------------------- glcdgraphics/font.c | 49 +++++++++++++++++++------------------------------ glcdgraphics/font.h | 2 ++ 3 files changed, 24 insertions(+), 57 deletions(-) diff --git a/glcdgraphics/bitmap.c b/glcdgraphics/bitmap.c index 8570da5..fe4b497 100644 --- a/glcdgraphics/bitmap.c +++ b/glcdgraphics/bitmap.c @@ -506,12 +506,8 @@ int cBitmap::DrawText(int x, int y, int xmax, const std::string & text, const cF { int xt; int yt; - int i; + unsigned int i; int c; - int c0; - int c1; - int c2; - int c3; int start; clip(x, 0, width - 1); @@ -551,28 +547,7 @@ int cBitmap::DrawText(int x, int y, int xmax, const std::string & text, const cF } for (i = start; i < (int) text.length(); i++) { - c = text[i]; - c0 = text[i]; - c1 = (i+1 < text.length()) ? text[i+1] : 0; - c2 = (i+2 < text.length()) ? text[i+2] : 0; - c3 = (i+3 < text.length()) ? text[i+3] : 0; - c0 &=0xff; c1 &=0xff; c2 &=0xff; c3 &=0xff; - - if( c0 >= 0xc2 && c0 <= 0xdf && c1 >= 0x80 && c1 <= 0xbf ){ //2 byte UTF-8 sequence found - i+=1; - c = ((c0&0x1f)<<6) | (c1&0x3f); - }else if( (c0 == 0xE0 && c1 >= 0xA0 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf) - || (c0 >= 0xE1 && c1 <= 0xEC && c1 >= 0x80 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf) - || (c0 == 0xED && c1 >= 0x80 && c1 <= 0x9f && c2 >= 0x80 && c2 <= 0xbf) - || (c0 >= 0xEE && c0 <= 0xEF && c1 >= 0x80 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf) ){ //3 byte UTF-8 sequence found - c = ((c0&0x0f)<<4) | ((c1&0x3f)<<6) | (c2&0x3f); - i+=2; - }else if( (c0 == 0xF0 && c1 >= 0x90 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf && c3 >= 0x80 && c3 <= 0xbf) - || (c0 >= 0xF1 && c0 >= 0xF3 && c1 >= 0x80 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf && c3 >= 0x80 && c3 <= 0xbf) - || (c0 == 0xF4 && c1 >= 0x80 && c1 <= 0x8f && c2 >= 0x80 && c2 <= 0xbf && c3 >= 0x80 && c3 <= 0xbf) ){ //4 byte UTF-8 sequence found - c = ((c0&0x07)<<2) | ((c1&0x3f)<<4) | ((c2&0x3f)<<6) | (c3&0x3f); - i+=3; - } + cFont::Utf8CodeAdjustCounter(text, c, i); if (xt > xmax) { @@ -832,3 +807,4 @@ void cBitmap::SavePBM(const std::string & fileName) } } // end of namespace + diff --git a/glcdgraphics/font.c b/glcdgraphics/font.c index 2730b91..3b71247 100644 --- a/glcdgraphics/font.c +++ b/glcdgraphics/font.c @@ -313,13 +313,10 @@ int cFont::Width(int ch) const return 0; } -int cFont::Width(const std::string & str) const +void cFont::Utf8CodeAdjustCounter(const std::string & str, int & c, unsigned int & i) { - unsigned int i; - int sum = 0; - int c,c0,c1,c2,c3,symcount=0; - - for (i = 0; i < str.length(); i++) + int c0,c1,c2,c3; + if (i < str.length()) { c = str[i]; c0 = str[i]; @@ -343,6 +340,19 @@ int cFont::Width(const std::string & str) const c = ((c0&0x07)<<2) | ((c1&0x3f)<<4) | ((c2&0x3f)<<6) | (c3&0x3f); i+=3; } + } +} + +int cFont::Width(const std::string & str) const +{ + unsigned int i; + int sum = 0; + int symcount=0; + int c; + + for (i = 0; i < str.length(); i++) + { + Utf8CodeAdjustCounter(str, c, i); symcount++; sum += Width(c); } @@ -354,33 +364,12 @@ int cFont::Width(const std::string & str, unsigned int len) const { unsigned int i; int sum = 0; - - int c,c0,c1,c2,c3,symcount=0; + int symcount=0; + int c; for (i = 0; i < str.length() && symcount < len; i++) { - c = str[i]; - c0 = str[i]; - c1 = (i+1 < str.length()) ? str[i+1] : 0; - c2 = (i+2 < str.length()) ? str[i+2] : 0; - c3 = (i+3 < str.length()) ? str[i+3] : 0; - c0 &=0xff; c1 &=0xff; c2 &=0xff; c3 &=0xff; - - if( c0 >= 0xc2 && c0 <= 0xdf && c1 >= 0x80 && c1 <= 0xbf ){ //2 byte UTF-8 sequence found - i+=1; - c = ((c0&0x1f)<<6) | (c1&0x3f); - }else if( (c0 == 0xE0 && c1 >= 0xA0 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf) - || (c0 >= 0xE1 && c1 <= 0xEC && c1 >= 0x80 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf) - || (c0 == 0xED && c1 >= 0x80 && c1 <= 0x9f && c2 >= 0x80 && c2 <= 0xbf) - || (c0 >= 0xEE && c0 <= 0xEF && c1 >= 0x80 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf) ){ //3 byte UTF-8 sequence found - c = ((c0&0x0f)<<4) | ((c1&0x3f)<<6) | (c2&0x3f); - i+=2; - }else if( (c0 == 0xF0 && c1 >= 0x90 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf && c3 >= 0x80 && c3 <= 0xbf) - || (c0 >= 0xF1 && c0 >= 0xF3 && c1 >= 0x80 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf && c3 >= 0x80 && c3 <= 0xbf) - || (c0 == 0xF4 && c1 >= 0x80 && c1 <= 0x8f && c2 >= 0x80 && c2 <= 0xbf && c3 >= 0x80 && c3 <= 0xbf) ){ //4 byte UTF-8 sequence found - c = ((c0&0x07)<<2) | ((c1&0x3f)<<4) | ((c2&0x3f)<<6) | (c3&0x3f); - i+=3; - } + Utf8CodeAdjustCounter(str, c, i); symcount++; sum += Width(c); } diff --git a/glcdgraphics/font.h b/glcdgraphics/font.h index 6bf72f5..f3427d5 100644 --- a/glcdgraphics/font.h +++ b/glcdgraphics/font.h @@ -83,6 +83,8 @@ public: void WrapText(int Width, int Height, std::string & Text, std::vector & Lines, int * TextWidth = NULL) const; + + static void Utf8CodeAdjustCounter(const std::string & str, int & c, unsigned int & i); }; } // end of namespace -- cgit v1.2.3