Background attribute rendering on Windows
This commit is contained in:
parent
24d802abc5
commit
e9f06c468a
|
@ -33,6 +33,7 @@ static std::hash<double> doubleHash;
|
||||||
class combinedEffectsAttr : public IUnknown {
|
class combinedEffectsAttr : public IUnknown {
|
||||||
ULONG refcount;
|
ULONG refcount;
|
||||||
uiAttribute *colorAttr;
|
uiAttribute *colorAttr;
|
||||||
|
uiAttribute *backgroundAttr;
|
||||||
uiAttribute *underlineAttr;
|
uiAttribute *underlineAttr;
|
||||||
uiAttribute *underlineColorAttr;
|
uiAttribute *underlineColorAttr;
|
||||||
|
|
||||||
|
@ -46,6 +47,11 @@ class combinedEffectsAttr : public IUnknown {
|
||||||
uiprivAttributeRelease(this->colorAttr);
|
uiprivAttributeRelease(this->colorAttr);
|
||||||
this->colorAttr = uiprivAttributeRetain(a);
|
this->colorAttr = uiprivAttributeRetain(a);
|
||||||
break;
|
break;
|
||||||
|
case uiAttributeTypeBackground:
|
||||||
|
if (this->backgroundAttr != NULL)
|
||||||
|
uiprivAttributeRelease(this->backgroundAttr);
|
||||||
|
this->backgroundAttr = uiprivAttributeRetain(a);
|
||||||
|
break;
|
||||||
case uiAttributeTypeUnderline:
|
case uiAttributeTypeUnderline:
|
||||||
if (this->underlineAttr != NULL)
|
if (this->underlineAttr != NULL)
|
||||||
uiprivAttributeRelease(this->underlineAttr);
|
uiprivAttributeRelease(this->underlineAttr);
|
||||||
|
@ -74,6 +80,7 @@ public:
|
||||||
{
|
{
|
||||||
this->refcount = 1;
|
this->refcount = 1;
|
||||||
this->colorAttr = NULL;
|
this->colorAttr = NULL;
|
||||||
|
this->backgroundAttr = NULL;
|
||||||
this->underlineAttr = NULL;
|
this->underlineAttr = NULL;
|
||||||
this->underlineColorAttr = NULL;
|
this->underlineColorAttr = NULL;
|
||||||
this->setAttribute(a);
|
this->setAttribute(a);
|
||||||
|
@ -83,6 +90,8 @@ public:
|
||||||
{
|
{
|
||||||
if (this->colorAttr != NULL)
|
if (this->colorAttr != NULL)
|
||||||
uiprivAttributeRelease(this->colorAttr);
|
uiprivAttributeRelease(this->colorAttr);
|
||||||
|
if (this->backgroundAttr != NULL)
|
||||||
|
uiprivAttributeRelease(this->backgroundAttr);
|
||||||
if (this->underlineAttr != NULL)
|
if (this->underlineAttr != NULL)
|
||||||
uiprivAttributeRelease(this->underlineAttr);
|
uiprivAttributeRelease(this->underlineAttr);
|
||||||
if (this->underlineColorAttr != NULL)
|
if (this->underlineColorAttr != NULL)
|
||||||
|
@ -124,6 +133,7 @@ public:
|
||||||
combinedEffectsAttr *b;
|
combinedEffectsAttr *b;
|
||||||
|
|
||||||
b = new combinedEffectsAttr(this->colorAttr);
|
b = new combinedEffectsAttr(this->colorAttr);
|
||||||
|
b->setAttribute(this->backgroundAttr);
|
||||||
b->setAttribute(this->underlineAttr);
|
b->setAttribute(this->underlineAttr);
|
||||||
b->setAttribute(this->underlineColorAttr);
|
b->setAttribute(this->underlineColorAttr);
|
||||||
b->setAttribute(a);
|
b->setAttribute(a);
|
||||||
|
@ -144,6 +154,14 @@ public:
|
||||||
ret ^= doubleHash(b);
|
ret ^= doubleHash(b);
|
||||||
ret ^= doubleHash(a);
|
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)
|
if (this->underlineAttr != NULL)
|
||||||
ret ^= (size_t) uiAttributeUnderline(this->underlineAttr);
|
ret ^= (size_t) uiAttributeUnderline(this->underlineAttr);
|
||||||
if (this->underlineColorAttr != NULL) {
|
if (this->underlineColorAttr != NULL) {
|
||||||
|
@ -162,6 +180,7 @@ public:
|
||||||
if (b == NULL)
|
if (b == NULL)
|
||||||
return false;
|
return false;
|
||||||
return combinedEffectsAttr::attrEqual(this->colorAttr, b->colorAttr) &&
|
return combinedEffectsAttr::attrEqual(this->colorAttr, b->colorAttr) &&
|
||||||
|
combinedEffectsAttr::attrEqual(this->backgroundAttr, b->backgroundAttr) &&
|
||||||
combinedEffectsAttr::attrEqual(this->underlineAttr, b->underlineAttr) &&
|
combinedEffectsAttr::attrEqual(this->underlineAttr, b->underlineAttr) &&
|
||||||
combinedEffectsAttr::attrEqual(this->underlineColorAttr, b->underlineColorAttr);
|
combinedEffectsAttr::attrEqual(this->underlineColorAttr, b->underlineColorAttr);
|
||||||
}
|
}
|
||||||
|
@ -177,6 +196,10 @@ public:
|
||||||
uiAttributeColor(this->colorAttr, &r, &g, &b, &a);
|
uiAttributeColor(this->colorAttr, &r, &g, &b, &a);
|
||||||
dea->setColor(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)
|
if (this->underlineAttr != NULL)
|
||||||
dea->setUnderline(uiAttributeUnderline(this->underlineAttr));
|
dea->setUnderline(uiAttributeUnderline(this->underlineAttr));
|
||||||
if (this->underlineColorAttr != NULL) {
|
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
|
// and fall through to set the underline style through the drawing effect
|
||||||
case uiAttributeTypeColor:
|
case uiAttributeTypeColor:
|
||||||
case uiAttributeTypeUnderlineColor:
|
case uiAttributeTypeUnderlineColor:
|
||||||
|
case uiAttributeTypeBackground:
|
||||||
// TODO const-correct this properly
|
// TODO const-correct this properly
|
||||||
hr = addEffectAttributeToRange(p, start, end, (uiAttribute *) attr);
|
hr = addEffectAttributeToRange(p, start, end, (uiAttribute *) attr);
|
||||||
if (hr != S_OK)
|
if (hr != S_OK)
|
||||||
logHRESULT(L"error applying effect (color, underline, or underline color) attribute", hr);
|
logHRESULT(L"error applying effect (color, underline, or underline color) attribute", hr);
|
||||||
break;
|
break;
|
||||||
case uiAttributeTypeBackground:
|
// case uiAttributeTypeBackground:
|
||||||
addBackgroundParams(p, start, end, attr);
|
// addBackgroundParams(p, start, end, attr);
|
||||||
break;
|
// break;
|
||||||
case uiAttributeTypeFeatures:
|
case uiAttributeTypeFeatures:
|
||||||
// only generate an attribute if not NULL
|
// only generate an attribute if not NULL
|
||||||
// TODO do we still need to do this or not...
|
// TODO do we still need to do this or not...
|
||||||
|
|
|
@ -39,6 +39,12 @@ class drawingEffectsAttr : public IUnknown {
|
||||||
double b;
|
double b;
|
||||||
double a;
|
double a;
|
||||||
|
|
||||||
|
bool hasBackground;
|
||||||
|
double br;
|
||||||
|
double bg;
|
||||||
|
double bb;
|
||||||
|
double ba;
|
||||||
|
|
||||||
bool hasUnderline;
|
bool hasUnderline;
|
||||||
uiUnderline u;
|
uiUnderline u;
|
||||||
|
|
||||||
|
@ -56,9 +62,11 @@ public:
|
||||||
virtual ULONG STDMETHODCALLTYPE Release(void);
|
virtual ULONG STDMETHODCALLTYPE Release(void);
|
||||||
|
|
||||||
void setColor(double r, double g, double b, double a);
|
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 setUnderline(uiUnderline u);
|
||||||
void setUnderlineColor(double r, double g, double b, double a);
|
void setUnderlineColor(double r, double g, double b, double a);
|
||||||
HRESULT mkColorBrush(ID2D1RenderTarget *rt, ID2D1SolidColorBrush **b);
|
HRESULT mkColorBrush(ID2D1RenderTarget *rt, ID2D1SolidColorBrush **b);
|
||||||
|
HRESULT mkBackgroundBrush(ID2D1RenderTarget *rt, ID2D1SolidColorBrush **b);
|
||||||
HRESULT underline(uiUnderline *u);
|
HRESULT underline(uiUnderline *u);
|
||||||
HRESULT mkUnderlineBrush(ID2D1RenderTarget *rt, ID2D1SolidColorBrush **b);
|
HRESULT mkUnderlineBrush(ID2D1RenderTarget *rt, ID2D1SolidColorBrush **b);
|
||||||
};
|
};
|
||||||
|
|
|
@ -143,6 +143,7 @@ drawingEffectsAttr::drawingEffectsAttr(void)
|
||||||
{
|
{
|
||||||
this->refcount = 1;
|
this->refcount = 1;
|
||||||
this->hasColor = false;
|
this->hasColor = false;
|
||||||
|
this->hasBackground = false;
|
||||||
this->hasUnderline = false;
|
this->hasUnderline = false;
|
||||||
this->hasUnderlineColor = false;
|
this->hasUnderlineColor = false;
|
||||||
}
|
}
|
||||||
|
@ -185,6 +186,15 @@ void drawingEffectsAttr::setColor(double r, double g, double b, double a)
|
||||||
this->a = 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)
|
void drawingEffectsAttr::setUnderline(uiUnderline u)
|
||||||
{
|
{
|
||||||
this->hasUnderline = true;
|
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);
|
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)
|
HRESULT drawingEffectsAttr::underline(uiUnderline *u)
|
||||||
{
|
{
|
||||||
if (u == NULL)
|
if (u == NULL)
|
||||||
|
@ -316,28 +335,57 @@ public:
|
||||||
{
|
{
|
||||||
D2D1_POINT_2F baseline;
|
D2D1_POINT_2F baseline;
|
||||||
drawingEffectsAttr *dea = (drawingEffectsAttr *) clientDrawingEffect;
|
drawingEffectsAttr *dea = (drawingEffectsAttr *) clientDrawingEffect;
|
||||||
ID2D1SolidColorBrush *brush;
|
ID2D1SolidColorBrush *foregroundBrush;
|
||||||
|
ID2D1SolidColorBrush *backgroundBrush;
|
||||||
|
|
||||||
baseline.x = baselineOriginX;
|
baseline.x = baselineOriginX;
|
||||||
baseline.y = baselineOriginY;
|
baseline.y = baselineOriginY;
|
||||||
brush = NULL;
|
foregroundBrush = NULL;
|
||||||
|
backgroundBrush = NULL;
|
||||||
if (dea != NULL) {
|
if (dea != NULL) {
|
||||||
HRESULT hr;
|
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)
|
if (hr != S_OK)
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
if (brush == NULL) {
|
if (foregroundBrush == NULL) {
|
||||||
brush = this->black;
|
foregroundBrush = this->black;
|
||||||
brush->AddRef();
|
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(
|
this->rt->DrawGlyphRun(
|
||||||
baseline,
|
baseline,
|
||||||
glyphRun,
|
glyphRun,
|
||||||
brush,
|
foregroundBrush,
|
||||||
measuringMode);
|
measuringMode);
|
||||||
brush->Release();
|
foregroundBrush->Release();
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue