Skip to content

Commit

Permalink
Text blending (#4069)
Browse files Browse the repository at this point in the history
* [Added] text blending functionality
* most of the code is taken from OpenATV.
* Credits to @jblayel

e.g. <widget source="myText" render="Label" alphatest="blend" ... />

* [Updated]  Adjust addons to respect new text blending possibilities

* [font.cpp] attempt to fix build error...

PLi compiler is old and not compatible with "register" keyword. Please revert when the compiler is updated.

error: ISO C++17 does not allow ‘register’ storage class specifier [-Werror=register]

---------

Co-authored-by: Dimitar Tsenev <[email protected]>
  • Loading branch information
2 people authored and WanWizard committed Oct 24, 2024
1 parent fa8668f commit 7bb0651
Show file tree
Hide file tree
Showing 10 changed files with 139 additions and 71 deletions.
155 changes: 98 additions & 57 deletions lib/gdi/font.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -915,7 +915,7 @@ nprint: isprintable=0;
return 0;
}

void eTextPara::blit(gDC &dc, const ePoint &offset, const gRGB &background, const gRGB &foreground, bool border)
void eTextPara::blit(gDC &dc, const ePoint &offset, const gRGB &cbackground, const gRGB &foreground, bool border)
{
if (glyphs.empty()) return;

Expand All @@ -939,6 +939,7 @@ void eTextPara::blit(gDC &dc, const ePoint &offset, const gRGB &background, cons
dc.getPixmap(target);
gUnmanagedSurface *surface = target->surface;
gRGB currentforeground = foreground;
const gRGB background = (m_blend && surface->bpp == 32) ? gRGB(currentforeground.r, currentforeground.g, currentforeground.b, 200) : cbackground;

int opcode = -1;

Expand Down Expand Up @@ -995,15 +996,16 @@ void eTextPara::blit(gDC &dc, const ePoint &offset, const gRGB &background, cons
opcode=0;
} else
opcode=1;
} else if (surface->bpp == 32)
}
else if (surface->bpp == 32)
{
opcode=3;
opcode = (m_blend) ? 4 : 3;

for (int i=0; i<16; ++i)
{
unsigned char da = background.a, dr = background.r, dg = background.g, db = background.b;
#define BLEND(y, x, a) (y + (((x-y) * a)>>8))

unsigned char da = background.a, dr = background.r, dg = background.g, db = background.b;
int sa = i * 16;
if (sa < 256)
{
Expand All @@ -1018,7 +1020,8 @@ void eTextPara::blit(gDC &dc, const ePoint &offset, const gRGB &background, cons
}
for (int i=0; i<16; ++i)
lookup32_invert[i]=lookup32_normal[i^0xF];
} else if (surface->bpp == 16)
}
else if (surface->bpp == 16)
{
opcode=2;
for (int i = 0; i != 16; ++i)
Expand All @@ -1042,7 +1045,8 @@ void eTextPara::blit(gDC &dc, const ePoint &offset, const gRGB &background, cons
}
for (int i=0; i<16; ++i)
lookup16_invert[i]=lookup16_normal[i^0xF];
} else
}
else
{
eWarning("[eTextPara] Can't render to %dbpp!", surface->bpp);
return;
Expand All @@ -1056,7 +1060,8 @@ void eTextPara::blit(gDC &dc, const ePoint &offset, const gRGB &background, cons
lookup8 = lookup8_normal;
lookup16 = lookup16_normal;
lookup32 = lookup32_normal;
} else
}
else
{
lookup8 = lookup8_invert;
lookup16 = lookup16_invert;
Expand Down Expand Up @@ -1128,77 +1133,113 @@ void eTextPara::blit(gDC &dc, const ePoint &offset, const gRGB &background, cons
{
case 0: // 4bit lookup to 8bit
{
int extra_buffer_stride = buffer_stride - sx;
__u8 *td=d;
for (int ay = 0; ay < sy; ay++)
{
int ax;

for (ax=0; ax<sx; ax++)
int extra_buffer_stride = buffer_stride - sx;
__u8 *td=d;
for (int ay = 0; ay < sy; ay++)
{
int b=(*s++)>>4;
if(b)
*td=lookup8[b];
++td;
int ax;

for (ax=0; ax<sx; ax++)
{
int b=(*s++)>>4;
if(b)
*td=lookup8[b];
++td;
}
s += extra_source_stride;
td += extra_buffer_stride;
}
s += extra_source_stride;
td += extra_buffer_stride;
}
}
break;
case 1: // 8bit direct
{
int extra_buffer_stride = buffer_stride - sx;
__u8 *td=d;
for (int ay = 0; ay < sy; ay++)
{
int ax;
for (ax=0; ax<sx; ax++)
int extra_buffer_stride = buffer_stride - sx;
__u8 *td=d;
for (int ay = 0; ay < sy; ay++)
{
int b=*s++;
*td++^=b;
int ax;
for (ax=0; ax<sx; ax++)
{
int b=*s++;
*td++^=b;
}
s += extra_source_stride;
td += extra_buffer_stride;
}
s += extra_source_stride;
td += extra_buffer_stride;
}
}
break;
case 2: // 16bit
{
int extra_buffer_stride = (buffer_stride >> 1) - sx;
__u16 *td = (__u16*)d;
for (int ay = 0; ay != sy; ay++)
{
int ax;
for (ax = 0; ax != sx; ax++)
int extra_buffer_stride = (buffer_stride >> 1) - sx;
__u16 *td = (__u16*)d;
for (int ay = 0; ay != sy; ay++)
{
int b = (*s++) >> 4;
if (b)
*td = lookup16[b];
++td;
int ax;
for (ax = 0; ax != sx; ax++)
{
int b = (*s++) >> 4;
if (b)
*td = lookup16[b];
++td;
}
s += extra_source_stride;
td += extra_buffer_stride;
}
s += extra_source_stride;
td += extra_buffer_stride;
}
}
break;
case 3: // 32bit
{
int extra_buffer_stride = (buffer_stride >> 2) - sx;
__u32 *td=(__u32*)d;
for (int ay = 0; ay < sy; ay++)
{
int ax;
for (ax=0; ax<sx; ax++)
int extra_buffer_stride = (buffer_stride >> 2) - sx;
__u32 *td=(__u32*)d;
for (int ay = 0; ay < sy; ay++)
{
int b=(*s++)>>4;
if(b)
*td=lookup32[b];
++td;
int ax;
for (ax=0; ax<sx; ax++)
{
int b=(*s++)>>4;
if(b)
*td=lookup32[b];
++td;
}
s += extra_source_stride;
td += extra_buffer_stride;
}
s += extra_source_stride;
td += extra_buffer_stride;
}
break;
case 4: // 32-bit blend
{
int extra_buffer_stride = (buffer_stride >> 2) - sx;
__u32 *td = (__u32 *)d;
for (int ay = 0; ay < sy; ay++)
{
int ax;
for (ax = 0; ax < sx; ax++)
{
int b = (*s++) >> 4;
if (b)
{
// unsigned char frame_a = (*td) >> 24 & 0xFF;
unsigned char frame_r = (*td) >> 16 & 0xFF;
unsigned char frame_g = (*td) >> 8 & 0xFF;
unsigned char frame_b = (*td) & 0xFF;

unsigned char da = lookup32[b] >> 24 & 0xFF;
unsigned char dr = lookup32[b] >> 16 & 0xFF;
unsigned char dg = lookup32[b] >> 8 & 0xFF;
unsigned char db = lookup32[b] & 0xFF;

#define BLEND(y, x, a) (y + (((x-y) * a)>>8))
frame_r = BLEND(frame_r, dr, da) & 0xFF;
frame_g = BLEND(frame_g, dg, da) & 0xFF;
frame_b = BLEND(frame_b, db, da) & 0xFF;
#undef BLEND
*td = ((currentforeground.a ^ 0xFF) << 24) | (frame_r << 16) | (frame_g << 8) | frame_b;
}
++td;
}
s += extra_source_stride;
td += extra_buffer_stride;
}
}
break;
}
Expand Down
7 changes: 5 additions & 2 deletions lib/gdi/font.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ class eTextPara: public iObject
int bboxValid;
eRect boundBox;
bool doTopBottomReordering;
bool m_blend;

int appendGlyph(Font *current_font, FT_Face current_face, FT_UInt glyphIndex, int flags, int rflags, int border, bool last,
bool activate_newcolor, unsigned long newcolor);
Expand All @@ -156,7 +157,7 @@ class eTextPara: public iObject
: current_font(0), replacement_font(0), fallback_font(0),
current_face(0), replacement_face(0), fallback_face(0),
area(area), cursor(start), maximum(0, 0), left(start.x()), charCount(0), totalheight(0),
bboxValid(0), doTopBottomReordering(false)
bboxValid(0), doTopBottomReordering(false), m_blend(false)
{
}
virtual ~eTextPara();
Expand All @@ -171,7 +172,9 @@ class eTextPara: public iObject

void clear();

void blit(gDC &dc, const ePoint &offset, const gRGB &background, const gRGB &foreground, bool border = false);
void setBlend(bool blend) { m_blend = blend; }

void blit(gDC &dc, const ePoint &offset, const gRGB &cbackground, const gRGB &foreground, bool border = false);

enum
{
Expand Down
3 changes: 3 additions & 0 deletions lib/gdi/grc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -900,6 +900,9 @@ void gDC::exec(const gOpcode *o)
int correction = o->parm.renderText->area.height() - bbox.height() - 2;
offset += ePoint(0, correction);
}

para->setBlend(flags & gPainter::RT_BLEND);

if (o->parm.renderText->border)
{
para->blit(*this, offset, m_background_color_rgb, o->parm.renderText->bordercolor, true);
Expand Down
13 changes: 13 additions & 0 deletions lib/gui/elabel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ int eLabel::event(int event, void *data, void *data2)
if (!m_nowrap)
flags |= gPainter::RT_WRAP;

if (m_blend)
flags |= gPainter::RT_BLEND;

/* if we don't have shadow, m_shadow_offset will be 0,0 */
painter.renderText(eRect(-m_shadow_offset.x(), -m_shadow_offset.y(), size().width(), size().height()), m_text, flags, m_border_color, m_border_size);

Expand Down Expand Up @@ -222,6 +225,16 @@ void eLabel::setNoWrap(int nowrap)
}
}

void eLabel::setAlphatest(int alphatest)
{
bool blend = (alphatest > 0); // blend if BT_ALPHATEST or BT_ALPHABLEND
if (m_blend != blend)
{
m_blend = blend;
invalidate();
}
}

void eLabel::clearForegroundColor()
{
if (m_have_foreground_color)
Expand Down
2 changes: 2 additions & 0 deletions lib/gui/elabel.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class eLabel: public eWidget
void setBorderColor(const gRGB &col);
void setBorderWidth(int size);
void setNoWrap(int nowrap);
void setAlphatest(int alphatest);
void clearForegroundColor();
int getNoWrap() { return m_nowrap; }

Expand All @@ -49,6 +50,7 @@ class eLabel: public eWidget
ePoint m_shadow_offset;
int m_border_size;
int m_nowrap;
bool m_blend = false;

enum eLabelEvent
{
Expand Down
17 changes: 11 additions & 6 deletions lib/gui/elistboxcontent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ void eListboxPythonStringContent::paint(gPainter &painter, eWindowStyle &style,
int border_size = 0;
int radius = 0;
int edges = 0;
bool alphablendtext = true;

/* get local listbox style, if present */
if (m_listbox)
Expand Down Expand Up @@ -309,6 +310,8 @@ void eListboxPythonStringContent::paint(gPainter &painter, eWindowStyle &style,
painter.setForegroundColor(gRGB(0x808080));

int flags = 0;
if (alphablendtext)
flags |= gPainter::RT_BLEND;
if (local_style)
{
style_text_offset = local_style->m_text_offset;
Expand Down Expand Up @@ -420,6 +423,7 @@ void eListboxPythonConfigContent::paint(gPainter &painter, eWindowStyle &style,
int border_size = 0;
int radius = 0;
int edges = 0;
bool alphablendtext = true;

painter.clip(itemrect);
style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
Expand Down Expand Up @@ -498,6 +502,7 @@ void eListboxPythonConfigContent::paint(gPainter &painter, eWindowStyle &style,

if (m_list && cursorValid)
{
int alphablendflag = (alphablendtext) ? gPainter::RT_BLEND : 0;
/* get current list item */
ePyObject item = PyList_GET_ITEM(m_list, m_cursor); // borrowed reference!
ePyObject text, value;
Expand Down Expand Up @@ -533,7 +538,7 @@ void eListboxPythonConfigContent::paint(gPainter &painter, eWindowStyle &style,
//eDebug("[CONFIGCONTENT] Go to step 1 fill line thick: %d; at pos x: %d, y: %d, w: %d, h: %d", m_sepline_thickness, offset.x() + 15, offset.y() + (m_itemsize.height() - m_sepline_thickness)/2, m_itemsize.width() - 30, m_sepline_thickness);
painter.fill(eRect(offset.x()+15, offset.y() + (m_itemsize.height() - m_sepline_thickness)/2, m_itemsize.width() - 30, m_sepline_thickness));
} else {
painter.renderText(eRect(ePoint(offset.x()+15, offset.y()), m_itemsize), string, gPainter::RT_HALIGN_LEFT | gPainter::RT_VALIGN_CENTER, border_color, border_size);
painter.renderText(eRect(ePoint(offset.x()+15, offset.y()), m_itemsize), string, alphablendflag | gPainter::RT_HALIGN_LEFT | gPainter::RT_VALIGN_CENTER, border_color, border_size);
}
Py_XDECREF(text);
if (!sep) {
Expand Down Expand Up @@ -563,7 +568,7 @@ void eListboxPythonConfigContent::paint(gPainter &painter, eWindowStyle &style,
/* check if this is really a tuple */
if (value && PyTuple_Check(value))
{
/* convert type to string */
/* convert type to string */
ePyObject type = PyTuple_GET_ITEM(value, 0);
const char *atype = (type && PyUnicode_Check(type)) ? PyUnicode_AsUTF8(type) : 0;

Expand All @@ -575,9 +580,9 @@ void eListboxPythonConfigContent::paint(gPainter &painter, eWindowStyle &style,
const char *value = (pvalue && PyUnicode_Check(pvalue)) ? PyUnicode_AsUTF8(pvalue) : "<not-a-string>";
painter.setFont(fnt2);
if (value_alignment_left)
painter.renderText(eRect(ePoint(offset.x()-15, offset.y()), m_itemsize), value, gPainter::RT_HALIGN_LEFT | gPainter::RT_VALIGN_CENTER, border_color, border_size);
painter.renderText(eRect(ePoint(offset.x()-15, offset.y()), m_itemsize), value, alphablendflag | gPainter::RT_HALIGN_LEFT | gPainter::RT_VALIGN_CENTER, border_color, border_size);
else
painter.renderText(eRect(ePoint(offset.x()-15, offset.y()), m_itemsize), value, gPainter::RT_HALIGN_RIGHT| gPainter::RT_VALIGN_CENTER, border_color, border_size);
painter.renderText(eRect(ePoint(offset.x()-15, offset.y()), m_itemsize), value, alphablendflag | gPainter::RT_HALIGN_RIGHT| gPainter::RT_VALIGN_CENTER, border_color, border_size);

/* pvalue is borrowed */
} else if (!strcmp(atype, "slider"))
Expand Down Expand Up @@ -709,9 +714,9 @@ void eListboxPythonConfigContent::paint(gPainter &painter, eWindowStyle &style,
const char *value = (ppixmap && PyUnicode_Check(ppixmap)) ? PyUnicode_AsUTF8(ppixmap) : "<not-a-string>";
painter.setFont(fnt2);
if (value_alignment_left)
painter.renderText(eRect(ePoint(offset.x()-15, offset.y()), m_itemsize), value, gPainter::RT_HALIGN_LEFT | gPainter::RT_VALIGN_CENTER, border_color, border_size);
painter.renderText(eRect(ePoint(offset.x()-15, offset.y()), m_itemsize), value, alphablendflag | gPainter::RT_HALIGN_LEFT | gPainter::RT_VALIGN_CENTER, border_color, border_size);
else
painter.renderText(eRect(ePoint(offset.x()-15, offset.y()), m_itemsize), value, gPainter::RT_HALIGN_RIGHT| gPainter::RT_VALIGN_CENTER, border_color, border_size);
painter.renderText(eRect(ePoint(offset.x()-15, offset.y()), m_itemsize), value, alphablendflag | gPainter::RT_HALIGN_RIGHT| gPainter::RT_VALIGN_CENTER, border_color, border_size);
}
else
{
Expand Down
Loading

0 comments on commit 7bb0651

Please sign in to comment.