Background attribute rendering on Windows

This commit is contained in:
Niklas Mischkulnig 2018-06-04 17:12:24 +02:00
parent 24d802abc5
commit e9f06c468a
3 changed files with 91 additions and 11 deletions

View File

@ -33,6 +33,7 @@ static std::hash<double> doubleHash;
class combinedEffectsAttr : public IUnknown {
ULONG refcount;
uiAttribute *colorAttr;
uiAttribute *backgroundAttr;
uiAttribute *underlineAttr;
uiAttribute *underlineColorAttr;
@ -46,6 +47,11 @@ class combinedEffectsAttr : public IUnknown {
uiprivAttributeRelease(this->colorAttr);
this->colorAttr = uiprivAttributeRetain(a);
break;
case uiAttributeTypeBackground:
if (this->backgroundAttr != NULL)
uiprivAttributeRelease(this->backgroundAttr);
this->backgroundAttr = uiprivAttributeRetain(a);
break;
case uiAttributeTypeUnderline:
if (this->underlineAttr != NULL)
uiprivAttributeRelease(this->underlineAttr);
@ -74,6 +80,7 @@ public:
{
this->refcount = 1;
this->colorAttr = NULL;
this->backgroundAttr = NULL;
this->underlineAttr = NULL;
this->underlineColorAttr = NULL;
this->setAttribute(a);
@ -83,6 +90,8 @@ public:
{
if (this->colorAttr != NULL)
uiprivAttributeRelease(this->colorAttr);
if (this->backgroundAttr != NULL)
uiprivAttributeRelease(this->backgroundAttr);
if (this->underlineAttr != NULL)
uiprivAttributeRelease(this->underlineAttr);
if (this->underlineColorAttr != NULL)
@ -124,6 +133,7 @@ public:
combinedEffectsAttr *b;
b = new combinedEffectsAttr(this->colorAttr);
b->setAttribute(this->backgroundAttr);
b->setAttribute(this->underlineAttr);
b->setAttribute(this->underlineColorAttr);
b->setAttribute(a);
@ -144,6 +154,14 @@ public:
ret ^= doubleHash(b);
ret ^= doubleHash(a);
}
if (this->backgroundAttr != NULL) {
uiAttributeBackground(this->backgroundAttr, &r, &g, &b, &a);
ret ^= doubleHash(r);
ret ^= doubleHash(g);
ret ^= doubleHash(b);
ret ^= doubleHash(a);
}
if (this->underlineAttr != NULL)
ret ^= (size_t) uiAttributeUnderline(this->underlineAttr);
if (this->underlineColorAttr != NULL) {
@ -162,6 +180,7 @@ public:
if (b == NULL)
return false;
return combinedEffectsAttr::attrEqual(this->colorAttr, b->colorAttr) &&
combinedEffectsAttr::attrEqual(this->backgroundAttr, b->backgroundAttr) &&
combinedEffectsAttr::attrEqual(this->underlineAttr, b->underlineAttr) &&
combinedEffectsAttr::attrEqual(this->underlineColorAttr, b->underlineColorAttr);
}
@ -177,6 +196,10 @@ public:
uiAttributeColor(this->colorAttr, &r, &g, &b, &a);
dea->setColor(r, g, b, a);
}
if (this->backgroundAttr != NULL) {
uiAttributeBackground(this->backgroundAttr, &r, &g, &b, &a);
dea->setBackground(r, g, b, a);
}
if (this->underlineAttr != NULL)
dea->setUnderline(uiAttributeUnderline(this->underlineAttr));
if (this->underlineColorAttr != NULL) {
@ -338,14 +361,15 @@ static uiForEach processAttribute(const uiAttributedString *s, const uiAttribute
// and fall through to set the underline style through the drawing effect
case uiAttributeTypeColor:
case uiAttributeTypeUnderlineColor:
case uiAttributeTypeBackground:
// TODO const-correct this properly
hr = addEffectAttributeToRange(p, start, end, (uiAttribute *) attr);
if (hr != S_OK)
logHRESULT(L"error applying effect (color, underline, or underline color) attribute", hr);
break;
case uiAttributeTypeBackground:
addBackgroundParams(p, start, end, attr);
break;
// case uiAttributeTypeBackground:
// addBackgroundParams(p, start, end, attr);
// break;
case uiAttributeTypeFeatures:
// only generate an attribute if not NULL
// TODO do we still need to do this or not...

View File

@ -39,6 +39,12 @@ class drawingEffectsAttr : public IUnknown {
double b;
double a;
bool hasBackground;
double br;
double bg;
double bb;
double ba;
bool hasUnderline;
uiUnderline u;
@ -56,9 +62,11 @@ public:
virtual ULONG STDMETHODCALLTYPE Release(void);
void setColor(double r, double g, double b, double a);
void setBackground(double r, double g, double b, double a);
void setUnderline(uiUnderline u);
void setUnderlineColor(double r, double g, double b, double a);
HRESULT mkColorBrush(ID2D1RenderTarget *rt, ID2D1SolidColorBrush **b);
HRESULT mkBackgroundBrush(ID2D1RenderTarget *rt, ID2D1SolidColorBrush **b);
HRESULT underline(uiUnderline *u);
HRESULT mkUnderlineBrush(ID2D1RenderTarget *rt, ID2D1SolidColorBrush **b);
};

View File

@ -143,6 +143,7 @@ drawingEffectsAttr::drawingEffectsAttr(void)
{
this->refcount = 1;
this->hasColor = false;
this->hasBackground = false;
this->hasUnderline = false;
this->hasUnderlineColor = false;
}
@ -185,6 +186,15 @@ void drawingEffectsAttr::setColor(double r, double g, double b, double a)
this->a = a;
}
void drawingEffectsAttr::setBackground(double r, double g, double b, double a)
{
this->hasBackground = true;
this->br = r;
this->bg = g;
this->bb = b;
this->ba = a;
}
void drawingEffectsAttr::setUnderline(uiUnderline u)
{
this->hasUnderline = true;
@ -209,6 +219,15 @@ HRESULT drawingEffectsAttr::mkColorBrush(ID2D1RenderTarget *rt, ID2D1SolidColorB
return mkSolidBrush(rt, this->r, this->g, this->b, this->a, b);
}
HRESULT drawingEffectsAttr::mkBackgroundBrush(ID2D1RenderTarget *rt, ID2D1SolidColorBrush **b)
{
if (!this->hasBackground) {
*b = NULL;
return S_OK;
}
return mkSolidBrush(rt, this->br, this->bg, this->bb, this->ba, b);
}
HRESULT drawingEffectsAttr::underline(uiUnderline *u)
{
if (u == NULL)
@ -316,28 +335,57 @@ public:
{
D2D1_POINT_2F baseline;
drawingEffectsAttr *dea = (drawingEffectsAttr *) clientDrawingEffect;
ID2D1SolidColorBrush *brush;
ID2D1SolidColorBrush *foregroundBrush;
ID2D1SolidColorBrush *backgroundBrush;
baseline.x = baselineOriginX;
baseline.y = baselineOriginY;
brush = NULL;
foregroundBrush = NULL;
backgroundBrush = NULL;
if (dea != NULL) {
HRESULT hr;
hr = dea->mkColorBrush(this->rt, &brush);
hr = dea->mkColorBrush(this->rt, &foregroundBrush);
if (hr != S_OK)
return hr;
hr = dea->mkBackgroundBrush(this->rt, &backgroundBrush);
if (hr != S_OK)
return hr;
}
if (brush == NULL) {
brush = this->black;
brush->AddRef();
if (foregroundBrush == NULL) {
foregroundBrush = this->black;
foregroundBrush->AddRef();
}
if (backgroundBrush != nullptr) {
// Get width of text
float totalWidth = 0;
for (UINT32 index = 0; index < glyphRun->glyphCount; index++)
{
totalWidth += glyphRun->glyphAdvances[index];
}
// Get height of text
DWRITE_FONT_METRICS fontMetrics;
glyphRun->fontFace->GetMetrics(&fontMetrics);
float adjust = glyphRun->fontEmSize / fontMetrics.designUnitsPerEm;
float ascent = adjust * fontMetrics.ascent;
float descent = adjust * fontMetrics.descent;
D2D1_RECT_F rect = D2D1::RectF(baselineOriginX,
baselineOriginY - ascent,
baselineOriginX + totalWidth,
baselineOriginY + descent);
// Fill Rectangle
this->rt->FillRectangle(rect, backgroundBrush);
}
this->rt->DrawGlyphRun(
baseline,
glyphRun,
brush,
foregroundBrush,
measuringMode);
brush->Release();
foregroundBrush->Release();
return S_OK;
}