From 0b8356aa927db1d536c00211a7d77fd2168d70dc Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Sat, 26 Feb 2011 12:13:59 +0100 Subject: [PATCH] Improved and cleaned up transparent text drawing --- PLUGINS/src/osddemo/osddemo.c | 8 +++++--- font.c | 15 +++------------ osd.c | 15 +++++++++------ osd.h | 26 ++++++++++++++------------ 4 files changed, 31 insertions(+), 33 deletions(-) diff --git a/PLUGINS/src/osddemo/osddemo.c b/PLUGINS/src/osddemo/osddemo.c index 87d94638..2e6a33bf 100644 --- a/PLUGINS/src/osddemo/osddemo.c +++ b/PLUGINS/src/osddemo/osddemo.c @@ -3,7 +3,7 @@ * * See the README file for copyright information and how to reach the author. * - * $Id: osddemo.c 2.2 2011/02/20 15:06:18 kls Exp $ + * $Id: osddemo.c 2.3 2011/02/26 12:08:13 kls Exp $ */ #include @@ -338,7 +338,8 @@ void cTrueColorDemo::Action(void) const int Size = Font->Width(Text) + 10; const int NumDots = 12; const int AnimFrames = NumDots; - AnimPixmap = osd->CreatePixmap(3, cRect((osd->Width() - Size) / 2, StartLine, Size, Size), cRect(0, 0, Size, Size * AnimFrames)); + // Temporarily using pixmap layer 0 to have the text alpha blended: + AnimPixmap = osd->CreatePixmap(0, cRect((osd->Width() - Size) / 2, StartLine, Size, Size), cRect(0, 0, Size, Size * AnimFrames)); if (AnimPixmap) { AnimPixmap->SetAlpha(0); AnimPixmap->Clear(); @@ -356,8 +357,9 @@ void cTrueColorDemo::Action(void) AnimPixmap->DrawEllipse(cRect(x, y, Diameter, Diameter), ArgbToColor(0xFF, Color, Color, Color)); Color -= Delta; } - AnimPixmap->DrawText(cPoint(0, Frame * Size), "Animation", clrBlack, clrTransparent, cFont::GetFont(fontSml), Size, Size, taCenter); + AnimPixmap->DrawText(cPoint(0, Frame * Size), Text, clrBlack, clrTransparent, cFont::GetFont(fontSml), Size, Size, taCenter); } + AnimPixmap->SetLayer(3); // now setting the actual pixmap layer FadeInPixmap = AnimPixmap; LOCK_THREAD; OldCursor = cursor = AnimPixmap->ViewPort().Point(); diff --git a/font.c b/font.c index 227dd63f..db1bd893 100644 --- a/font.c +++ b/font.c @@ -6,7 +6,7 @@ * * BiDi support by Osama Alrawab @2008 Tripoli-Libya. * - * $Id: font.c 2.6 2011/02/20 14:15:38 kls Exp $ + * $Id: font.c 2.7 2011/02/26 12:09:18 kls Exp $ */ #include "font.h" @@ -338,7 +338,6 @@ void cFreetypeFont::DrawText(cPixmap *Pixmap, int x, int y, const char *s, tColo s = bs; #endif bool AntiAliased = Setup.AntiAlias; - bool TransparentBackground = ColorBg == clrTransparent; uint prevSym = 0; while (*s) { int sl = Utf8CharLen(s); @@ -358,16 +357,8 @@ void cFreetypeFont::DrawText(cPixmap *Pixmap, int x, int y, const char *s, tColo for (int pitch = 0; pitch < g->Pitch(); pitch++) { uchar bt = *(buffer + (row * g->Pitch() + pitch)); if (AntiAliased) { - if (bt > 0x00) { - tColor bg; - if (bt == 0xFF || TransparentBackground) - bg = ColorFg; - else { - bg = AlphaBlend(ColorFg, ColorBg, bt); - bt = ALPHA_OPAQUE; - } - Pixmap->DrawPixel(cPoint(x + pitch + g->Left() + kerning, y + row + (height - Bottom() - g->Top())), bg, bt); - } + if (bt > 0x00) + Pixmap->DrawPixel(cPoint(x + pitch + g->Left() + kerning, y + row + (height - Bottom() - g->Top())), AlphaBlend(ColorFg, ColorBg, bt)); } else { //monochrome rendering for (int col = 0; col < 8 && col + pitch * 8 <= symWidth; col++) { diff --git a/osd.c b/osd.c index 1516bf57..aeedb721 100644 --- a/osd.c +++ b/osd.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: osd.c 2.13 2011/02/20 21:35:48 kls Exp $ + * $Id: osd.c 2.14 2011/02/26 11:36:58 kls Exp $ */ #include "osd.h" @@ -69,7 +69,7 @@ public: cInitAlphaLut initAlphaLut; -tColor AlphaBlend(tColor ColorFg, tColor ColorBg, tColor AlphaLayer) +tColor AlphaBlend(tColor ColorFg, tColor ColorBg, uint8_t AlphaLayer) { tColor Alpha = (ColorFg & 0xFF000000) >> 24; Alpha *= AlphaLayer; @@ -84,7 +84,7 @@ tColor AlphaBlend(tColor ColorFg, tColor ColorBg, tColor AlphaLayer) // Alpha blending without lookup table. // Also works fast, but doesn't return the theoretically correct result. // It's "good enough", though. -static tColor Multiply(tColor Color, tColor Alpha) +static tColor Multiply(tColor Color, uint8_t Alpha) { tColor RB = (Color & 0x00FF00FF) * Alpha; RB = ((RB + ((RB >> 8) & 0x00FF00FF) + 0x00800080) >> 8) & 0x00FF00FF; @@ -93,7 +93,7 @@ static tColor Multiply(tColor Color, tColor Alpha) return AG | RB; } -tColor AlphaBlend(tColor ColorFg, tColor ColorBg, tColor AlphaLayer) +tColor AlphaBlend(tColor ColorFg, tColor ColorBg, uint8_t AlphaLayer) { tColor Alpha = (ColorFg & 0xFF000000) >> 24; if (AlphaLayer < ALPHA_OPAQUE) { @@ -1174,12 +1174,15 @@ void cPixmapMemory::DrawImage(const cPoint &Point, int ImageHandle) Unlock(); } -void cPixmapMemory::DrawPixel(const cPoint &Point, tColor Color, tColor Alpha) +void cPixmapMemory::DrawPixel(const cPoint &Point, tColor Color) { Lock(); if (DrawPort().Size().Contains(Point)) { int p = Point.Y() * DrawPort().Width() + Point.X(); - data[p] = AlphaBlend(Color, data[p], Alpha); + if (Layer() == 0 && !IS_OPAQUE(Color)) + data[p] = AlphaBlend(Color, data[p]); + else + data[p] = Color; MarkDrawPortDirty(Point); } Unlock(); diff --git a/osd.h b/osd.h index 2bb6e0a0..86a660c5 100644 --- a/osd.h +++ b/osd.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: osd.h 2.6 2011/02/20 14:52:17 kls Exp $ + * $Id: osd.h 2.7 2011/02/26 12:13:59 kls Exp $ */ #ifndef __OSD_H @@ -24,6 +24,7 @@ #define MAXNUMCOLORS 256 #define ALPHA_TRANSPARENT 0x00 #define ALPHA_OPAQUE 0xFF +#define IS_OPAQUE(c) ((c >> 24) == ALPHA_OPAQUE) enum { //AARRGGBB @@ -73,7 +74,7 @@ tColor HsvToColor(double H, double S, double V); ///< to an RGB tColor value. The alpha value of the result is 0x00, so ///< the caller may need to set it accordingly. -tColor AlphaBlend(tColor ColorFg, tColor ColorBg, tColor AlphaLayer = ALPHA_OPAQUE); +tColor AlphaBlend(tColor ColorFg, tColor ColorBg, uint8_t AlphaLayer = ALPHA_OPAQUE); class cPalette { private: @@ -479,11 +480,13 @@ public: ///< for defining the rendering sequence. If Layer is less than zero, this ///< pixmap will not be rendered into the final OSD (it can be activated by a ///< later call to SetLayer()). The value 0 is reserved for the background - ///< pixmap and shall not be used otherwise. If there are several pixmaps with - ///< the same value of Layer, their rendering sequence within that layer is - ///< undefined. - ///< I order to allow devices that can handle only a limited number of layers, - ///< the Layer parameters must be less than 8 (MAXPIXMAPLAYERS). + ///< pixmap and shall not be used otherwise (with the sole exception of + ///< temporarily using layer 0 to have a text with transparent background + ///< rendered with alpha blending into that pixmap; see also DrawPixel()). + ///< If there are several pixmaps with the same value of Layer, their rendering + ///< sequence within that layer is undefined. + ///< In order to allow devices that can handle only a limited number of layers, + ///< the Layer parameter must be less than 8 (MAXPIXMAPLAYERS). ///< ViewPort defines the rectangle in which this pixmap will be rendered on ///< the OSD. If no DrawPort ist given, it defaults to the same size as the ///< ViewPort, with its upper left corner set to (0, 0). @@ -567,12 +570,11 @@ public: ///< the given Point. ImageHandle must be a value that has previously been ///< returned by a call to cOsdProvider::StoreImage(). If ImageHandle ///< has an invalid value, nothing happens. - virtual void DrawPixel(const cPoint &Point, tColor Color, tColor Alpha = ALPHA_OPAQUE) = 0; + virtual void DrawPixel(const cPoint &Point, tColor Color) = 0; ///< Sets the pixel at the given Point to the given Color, which is ///< a full 32 bit ARGB value. If the alpha value of Color is not 0xFF - ///< (fully opaque), the pixel is alpha blended with the existing color - ///< at the given position in this pixmap. If Alpha is less than - ///< ALPHA_OPAQUE, the alpha value of Color will be reduced accordingly. + ///< (fully opaque), and this is the background pixmap (layer 0), the pixel is + ///< alpha blended with the existing color at the given position in this pixmap. virtual void DrawBitmap(const cPoint &Point, const cBitmap &Bitmap, tColor ColorFg = 0, tColor ColorBg = 0, bool Overlay = false) = 0; ///< Sets the pixels in the OSD with the data from the given ///< Bitmap, putting the upper left corner of the Bitmap at Point. @@ -662,7 +664,7 @@ public: virtual void Fill(tColor Color); virtual void DrawImage(const cPoint &Point, const cImage &Image); virtual void DrawImage(const cPoint &Point, int ImageHandle); - virtual void DrawPixel(const cPoint &Point, tColor Color, tColor Alpha = ALPHA_OPAQUE); + virtual void DrawPixel(const cPoint &Point, tColor Color); virtual void DrawBitmap(const cPoint &Point, const cBitmap &Bitmap, tColor ColorFg = 0, tColor ColorBg = 0, bool Overlay = false); virtual void DrawText(const cPoint &Point, const char *s, tColor ColorFg, tColor ColorBg, const cFont *Font, int Width = 0, int Height = 0, int Alignment = taDefault); virtual void DrawRectangle(const cRect &Rect, tColor Color);