More migrations of attrstr.cpp and drawtext.cpp. My this is a mess :D
This commit is contained in:
parent
5314295e4c
commit
1b1d609c88
|
@ -23,7 +23,3 @@ extern BOOL showFontDialog(HWND parent, struct fontDialogParams *params);
|
|||
extern void loadInitialFontDialogParams(struct fontDialogParams *params);
|
||||
extern void destroyFontDialogParams(struct fontDialogParams *params);
|
||||
extern WCHAR *fontDialogParamsToString(struct fontDialogParams *params);
|
||||
|
||||
// attrstr.cpp
|
||||
typedef std::function<void(uiDrawContext *c, uiDrawTextLayout *layout, double x, double y)> backgroundFunc;
|
||||
extern void attrstrToIDWriteTextLayoutAttrs(uiDrawTextLayoutParams *p, IDWriteTextLayout *layout, std::vector<backgroundFunc> **backgroundFuncs);
|
||||
|
|
|
@ -4,14 +4,15 @@
|
|||
|
||||
// TODO this whole file needs cleanup
|
||||
|
||||
// we need to collect all the background blocks and add them all at once
|
||||
// we need to collect all the background parameters and add them all at once
|
||||
// TODO consider having background parameters in the drawing effects
|
||||
// TODO contextual alternates override ligatures?
|
||||
// TODO rename this struct to something that isn't exclusively foreach-ing?
|
||||
struct foreachParams {
|
||||
const uint16_t *s;
|
||||
size_t len;
|
||||
IDWriteTextLayout *layout;
|
||||
std::vector<backgroundFunc> *backgroundFuncs;
|
||||
std::vector<struct drawTextBackgroundParams *> *backgroundParams;
|
||||
};
|
||||
|
||||
static std::hash<double> doubleHash;
|
||||
|
@ -255,18 +256,15 @@ static HRESULT addEffectAttributeToRange(struct foreachParams *p, size_t start,
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
static backgroundFunc mkBackgroundFunc(size_t start, size_t end, double r, double g, double b, double a)
|
||||
static void addBackgroundParams(struct foreachParams *p, size_t start, size_t end, const uiAttribute *attr)
|
||||
{
|
||||
return [=](uiDrawContext *c, uiDrawTextLayout *layout, double x, double y) {
|
||||
uiDrawBrush brush;
|
||||
struct drawTextBackgroundParams *params;
|
||||
|
||||
brush.Type = uiDrawBrushTypeSolid;
|
||||
brush.R = r;
|
||||
brush.G = g;
|
||||
brush.B = b;
|
||||
brush.A = a;
|
||||
drawTextBackground(c, x, y, layout, start, end, &brush, 0);
|
||||
};
|
||||
params = uiprivNew(struct drawTextBackgroundParams);
|
||||
params->start = start;
|
||||
params->end = end;
|
||||
uiAttributeColor(attr, &(params->r), &(params->g), &(params->b), &(params->a));
|
||||
p->backgroundParams->push_back(params);
|
||||
}
|
||||
|
||||
static uiForEach processAttribute(const uiAttributedString *s, const uiAttribute *attr, size_t start, size_t end, void *data)
|
||||
|
@ -274,16 +272,12 @@ static uiForEach processAttribute(const uiAttributedString *s, const uiAttribute
|
|||
struct foreachParams *p = (struct foreachParams *) data;
|
||||
DWRITE_TEXT_RANGE range;
|
||||
WCHAR *wfamily;
|
||||
size_t ostart, oend;
|
||||
BOOL hasUnderline;
|
||||
IDWriteTypography *dt;
|
||||
HRESULT hr;
|
||||
|
||||
ostart = start;
|
||||
oend = end;
|
||||
// TODO fix const correctness
|
||||
start = attrstrUTF8ToUTF16((uiAttributedString *) s, start);
|
||||
end = attrstrUTF8ToUTF16((uiAttributedString *) s, end);
|
||||
start = uiprivAttributedStringUTF8ToUTF16(s, start);
|
||||
end = uiprivAttributedStringUTF8ToUTF16(s, end);
|
||||
range.startPosition = start;
|
||||
range.length = end - start;
|
||||
switch (uiAttributeGetType(attr)) {
|
||||
|
@ -340,9 +334,7 @@ static uiForEach processAttribute(const uiAttributedString *s, const uiAttribute
|
|||
logHRESULT(L"error applying effect (color, underline, or underline color) attribute", hr);
|
||||
break;
|
||||
case uiAttributeBackground:
|
||||
p->backgroundFuncs->push_back(
|
||||
mkBackgroundFunc(ostart, oend,
|
||||
spec->R, spec->G, spec->B, spec->A));
|
||||
addBackgroundParams(p, start, end, attr);
|
||||
break;
|
||||
case uiAttributeTypeFeatures:
|
||||
// only generate an attribute if not NULL
|
||||
|
@ -407,7 +399,7 @@ TODO
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
void uiprivAttributedStringApplyAttributesToDWriteTextLayout(uiDrawTextLayoutParams *p, IDWriteTextLayout *layout, std::vector<backgroundFunc> **backgroundFuncs)
|
||||
void uiprivAttributedStringApplyAttributesToDWriteTextLayout(uiDrawTextLayoutParams *p, IDWriteTextLayout *layout, std::vector<struct drawTextBackgroundParams *> **backgroundParams)
|
||||
{
|
||||
struct foreachParams fep;
|
||||
HRESULT hr;
|
||||
|
@ -415,10 +407,10 @@ void uiprivAttributedStringApplyAttributesToDWriteTextLayout(uiDrawTextLayoutPar
|
|||
fep.s = attrstrUTF16(p->String);
|
||||
fep.len = attrstrUTF16Len(p->String);
|
||||
fep.layout = layout;
|
||||
fep.backgroundFuncs = new std::vector<backgroundFunc>;
|
||||
fep.backgroundParams = new std::vector<struct drawTextBackgroundParams *>;
|
||||
uiAttributedStringForEachAttribute(p->String, processAttribute, &fep);
|
||||
hr = applyEffectsAttributes(&fep);
|
||||
if (hr != S_OK)
|
||||
logHRESULT(L"error applying effects attributes", hr);
|
||||
*backgroundFuncs = fep.backgroundFuncs;
|
||||
*backgroundParams = fep.backgroundParams;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,9 @@ extern DWRITE_FONT_STRETCH uiprivStretchToDWriteStretch(uiTextStretch s);
|
|||
extern void uiprivFontDescriptorFromIDWriteFont(IDWriteFont *font, uiFontDescriptor *uidesc);
|
||||
|
||||
// attrstr.cpp
|
||||
extern void uiprivAttributedStringApplyAttributesToDWriteTextLayout(uiDrawTextLayoutParams *p, IDWriteTextLayout *layout, std::vector<backgroundFunc> **backgroundFuncs);
|
||||
// TODO
|
||||
struct drawTextBackgroundParams;
|
||||
extern void uiprivAttributedStringApplyAttributesToDWriteTextLayout(uiDrawTextLayoutParams *p, IDWriteTextLayout *layout, std::vector<struct drawTextBackgroundParams *> **backgroundFuncs);
|
||||
|
||||
// drawtext.cpp
|
||||
class drawingEffectsAttr : public IUnknown {
|
||||
|
@ -48,3 +50,12 @@ public:
|
|||
HRESULT underline(uiUnderline *u);
|
||||
HRESULT mkUnderlineBrush(ID2D1RenderTarget *rt, ID2D1SolidColorBrush **b);
|
||||
};
|
||||
// TODO figure out where this type should *really* go in all the headers...
|
||||
struct drawTextBackgroundParams {
|
||||
size_t start;
|
||||
size_t end;
|
||||
double r;
|
||||
double g;
|
||||
double b;
|
||||
double a;
|
||||
};
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
struct uiDrawTextLayout {
|
||||
IDWriteTextFormat *format;
|
||||
IDWriteTextLayout *layout;
|
||||
std::vector<backgroundFunc> *backgroundFuncs;
|
||||
std::vector<struct drawTextBackgroundParams *> *backgroundParams;
|
||||
// for converting DirectWrite indices from/to byte offsets
|
||||
size_t *u8tou16;
|
||||
size_t nUTF8;
|
||||
|
@ -84,7 +84,7 @@ uiDrawTextLayout *uiDrawNewTextLayout(uiDrawTextLayoutParams *p)
|
|||
if (hr != S_OK)
|
||||
logHRESULT(L"error setting IDWriteTextLayout max layout width", hr);
|
||||
|
||||
attrstrToIDWriteTextLayoutAttrs(p, tl->layout, &(tl->backgroundFuncs));
|
||||
attrstrToIDWriteTextLayoutAttrs(p, tl->layout, &(tl->backgroundParams));
|
||||
|
||||
// and finally copy the UTF-8/UTF-16 index conversion tables
|
||||
tl->u8tou16 = attrstrCopyUTF8ToUTF16(p->String, &(tl->nUTF8));
|
||||
|
@ -97,12 +97,15 @@ void uiDrawFreeTextLayout(uiDrawTextLayout *tl)
|
|||
{
|
||||
uiFree(tl->u16tou8);
|
||||
uiFree(tl->u8tou16);
|
||||
delete tl->backgroundFuncs;
|
||||
for (auto p in *(tl->backgroundParams))
|
||||
uiprivFree(p);
|
||||
delete tl->backgroundParams;
|
||||
tl->layout->Release();
|
||||
tl->format->Release();
|
||||
uiFree(tl);
|
||||
}
|
||||
|
||||
// TODO make this shared code somehow
|
||||
static HRESULT mkSolidBrush(ID2D1RenderTarget *rt, double r, double g, double b, double a, ID2D1SolidColorBrush **brush)
|
||||
{
|
||||
D2D1_BRUSH_PROPERTIES props;
|
||||
|
@ -354,6 +357,7 @@ public:
|
|||
return E_UNEXPECTED;
|
||||
}
|
||||
|
||||
// TODO clean this function up
|
||||
virtual HRESULT STDMETHODCALLTYPE DrawUnderline(void *clientDrawingContext, FLOAT baselineOriginX, FLOAT baselineOriginY, const DWRITE_UNDERLINE *underline, IUnknown *clientDrawingEffect)
|
||||
{
|
||||
drawingEffectsAttr *dea = (drawingEffectsAttr *) clientDrawingEffect;
|
||||
|
@ -468,8 +472,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
$$$$ TODO continue here
|
||||
|
||||
// TODO this ignores clipping?
|
||||
void uiDrawText(uiDrawContext *c, uiDrawTextLayout *tl, double x, double y)
|
||||
{
|
||||
|
@ -478,8 +480,9 @@ void uiDrawText(uiDrawContext *c, uiDrawTextLayout *tl, double x, double y)
|
|||
textRenderer *renderer;
|
||||
HRESULT hr;
|
||||
|
||||
for (const auto &f : *(tl->backgroundFuncs))
|
||||
f(c, tl, x, y);
|
||||
for (auto p : *(tl->backgroundParams)) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
// TODO document that fully opaque black is the default text color; figure out whether this is upheld in various scenarios on other platforms
|
||||
// TODO figure out if this needs to be cleaned out
|
||||
|
@ -534,136 +537,22 @@ void uiDrawTextLayoutExtents(uiDrawTextLayout *tl, double *width, double *height
|
|||
|
||||
int uiDrawTextLayoutNumLines(uiDrawTextLayout *tl)
|
||||
{
|
||||
return 0;
|
||||
#if 0
|
||||
TODO
|
||||
return tl->nLines;
|
||||
#endif
|
||||
}
|
||||
|
||||
// DirectWrite doesn't provide a direct way to do this, so we have to do this manually
|
||||
// TODO does that comment still apply here or to the code at the top of this file?
|
||||
void uiDrawTextLayoutLineByteRange(uiDrawTextLayout *tl, int line, size_t *start, size_t *end)
|
||||
{
|
||||
#if 0
|
||||
TODO
|
||||
*start = tl->lineInfo[line].startPos;
|
||||
*start = tl->u16tou8[*start];
|
||||
*end = tl->lineInfo[line].endPos - tl->lineInfo[line].newlineCount;
|
||||
*end = tl->u16tou8[*end];
|
||||
}
|
||||
|
||||
void uiDrawTextLayoutLineGetMetrics(uiDrawTextLayout *tl, int line, uiDrawTextLayoutLineMetrics *m)
|
||||
{
|
||||
m->X = tl->lineInfo[line].x;
|
||||
m->Y = tl->lineInfo[line].y;
|
||||
m->Width = tl->lineInfo[line].width;
|
||||
m->Height = tl->lineInfo[line].height;
|
||||
|
||||
// TODO rename tl->lineInfo[line].baseline to .baselineOffset or something of the sort to make its meaning more clear
|
||||
m->BaselineY = tl->lineInfo[line].y + tl->lineInfo[line].baseline;
|
||||
m->Ascent = tl->lineInfo[line].baseline;
|
||||
m->Descent = tl->lineInfo[line].height - tl->lineInfo[line].baseline;
|
||||
m->Leading = 0; // TODO
|
||||
|
||||
m->ParagraphSpacingBefore = 0; // TODO
|
||||
m->LineHeightSpace = 0; // TODO
|
||||
m->LineSpacing = 0; // TODO
|
||||
m->ParagraphSpacing = 0; // TODO
|
||||
}
|
||||
|
||||
// this algorithm comes from Microsoft's PadWrite sample, following TextEditor::SetSelectionFromPoint()
|
||||
// TODO go back through all of these and make sure we convert coordinates properly
|
||||
// TODO same for OS X
|
||||
void uiDrawTextLayoutHitTest(uiDrawTextLayout *tl, double x, double y, size_t *pos, int *line)
|
||||
{
|
||||
DWRITE_HIT_TEST_METRICS m;
|
||||
BOOL trailing, inside;
|
||||
size_t p;
|
||||
UINT32 i;
|
||||
HRESULT hr;
|
||||
|
||||
hr = tl->layout->HitTestPoint(x, y,
|
||||
&trailing, &inside,
|
||||
&m);
|
||||
if (hr != S_OK)
|
||||
logHRESULT(L"error hit-testing IDWriteTextLayout", hr);
|
||||
p = m.textPosition;
|
||||
// on a trailing hit, align to the nearest cluster
|
||||
if (trailing) {
|
||||
DWRITE_HIT_TEST_METRICS m2;
|
||||
FLOAT x, y; // crashes if I skip these :/
|
||||
|
||||
hr = tl->layout->HitTestTextPosition(m.textPosition, trailing,
|
||||
&x, &y, &m2);
|
||||
if (hr != S_OK)
|
||||
logHRESULT(L"error aligning trailing hit to nearest cluster", hr);
|
||||
p = m2.textPosition + m2.length;
|
||||
}
|
||||
*pos = tl->u16tou8[p];
|
||||
|
||||
for (i = 0; i < tl->nLines; i++) {
|
||||
double ltop, lbottom;
|
||||
|
||||
ltop = tl->lineInfo[i].y;
|
||||
lbottom = ltop + tl->lineInfo[i].height;
|
||||
// y will already >= ltop at this point since the past lbottom should == ltop
|
||||
if (y < lbottom)
|
||||
break;
|
||||
}
|
||||
if (i == tl->nLines)
|
||||
i--;
|
||||
*line = i;
|
||||
}
|
||||
|
||||
double uiDrawTextLayoutByteLocationInLine(uiDrawTextLayout *tl, size_t pos, int line)
|
||||
{
|
||||
BOOL trailing;
|
||||
DWRITE_HIT_TEST_METRICS m;
|
||||
FLOAT x, y;
|
||||
HRESULT hr;
|
||||
|
||||
if (line < 0 || line >= tl->nLines)
|
||||
return -1;
|
||||
pos = tl->u8tou16[pos];
|
||||
// note: >, not >=, because the position at endPos is valid!
|
||||
if (pos < tl->lineInfo[line].startPos || pos > tl->lineInfo[line].endPos)
|
||||
return -1;
|
||||
// this behavior seems correct
|
||||
// there's also PadWrite's TextEditor::GetCaretRect() but that requires state...
|
||||
// TODO where does this fail?
|
||||
trailing = FALSE;
|
||||
if (pos != 0 && pos != tl->nUTF16 && pos == tl->lineInfo[line].endPos) {
|
||||
pos--;
|
||||
trailing = TRUE;
|
||||
}
|
||||
hr = tl->layout->HitTestTextPosition(pos, trailing,
|
||||
&x, &y, &m);
|
||||
if (hr != S_OK)
|
||||
logHRESULT(L"error calling IDWriteTextLayout::HitTestTextPosition()", hr);
|
||||
return x;
|
||||
}
|
||||
|
||||
void caretDrawParams(uiDrawContext *c, double height, struct caretDrawParams *p)
|
||||
{
|
||||
DWORD caretWidth;
|
||||
|
||||
// there seems to be no defined caret color
|
||||
// the best I can come up with is "inverts colors underneath" (according to https://msdn.microsoft.com/en-us/library/windows/desktop/ms648397(v=vs.85).aspx) which I have no idea how to do (TODO)
|
||||
// just return black for now
|
||||
p->r = 0.0;
|
||||
p->g = 0.0;
|
||||
p->b = 0.0;
|
||||
p->a = 1.0;
|
||||
|
||||
if (SystemParametersInfoW(SPI_GETCARETWIDTH, 0, &caretWidth, 0) == 0)
|
||||
// don't log the failure, fall back gracefully
|
||||
// the instruction to use this comes from https://msdn.microsoft.com/en-us/library/windows/desktop/ms648399(v=vs.85).aspx
|
||||
// and we have to assume GetSystemMetrics() always succeeds, so
|
||||
caretWidth = GetSystemMetrics(SM_CXBORDER);
|
||||
// TODO make this a function and split it out of areautil.cpp
|
||||
{
|
||||
FLOAT dpix, dpiy;
|
||||
|
||||
// TODO can we pass NULL for dpiy?
|
||||
c->rt->GetDpi(&dpix, &dpiy);
|
||||
// see https://msdn.microsoft.com/en-us/library/windows/desktop/dd756649%28v=vs.85%29.aspx (and others; search "direct2d mouse")
|
||||
p->width = ((double) (caretWidth * 96)) / dpix;
|
||||
}
|
||||
// and there doesn't seem to be this either... (TODO check what PadWrite does?)
|
||||
p->xoff = 0;
|
||||
#endif
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue