static ID2D1GradientStopCollection *mkstops(uiDrawBrush *b, ID2D1RenderTarget *rt) { ID2D1GradientStopCollection *s; D2D1_GRADIENT_STOP *stops; size_t i; HRESULT hr; stops = uiAlloc(b->NumStops * sizeof (D2D1_GRADIENT_STOP), "D2D1_GRADIENT_STOP[]"); for (i = 0; i < b->NumStops; i++) { stops[i].position = b->Stops[i].Pos; stops[i].color.r = b->Stops[i].R; stops[i].color.g = b->Stops[i].G; stops[i].color.b = b->Stops[i].B; stops[i].color.a = b->Stops[i].A; } // TODO BUG IN MINGW // the Microsoft headers give this all 6 parameters // the MinGW headers use the 4-parameter version hr = (*(rt->lpVtbl->CreateGradientStopCollection))(rt, stops, b->NumStops, D2D1_GAMMA_2_2, // this is the default for the C++-only overload of ID2D1RenderTarget::GradientStopCollection() D2D1_EXTEND_MODE_CLAMP, &s); if (hr != S_OK) logHRESULT("error creating stop collection in mkstops()", hr); uiFree(stops); return s; }
static const char *initerr(const char *message, const WCHAR *label, DWORD value) { WCHAR *sysmsg; BOOL hassysmsg; WCHAR *beforele; WCHAR *afterle; int n; WCHAR *wmessage; WCHAR *wstr; const char *str; if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, value, 0, (LPWSTR) (&sysmsg), 0, NULL) != 0) { hassysmsg = TRUE; beforele = L" ("; afterle = L")"; } else { hassysmsg = FALSE; sysmsg = L""; beforele = L""; afterle = L""; } wmessage = toUTF16(message); n = _scwprintf(initErrorFormat, initErrorArgs); wstr = (WCHAR *) uiAlloc((n + 1) * sizeof (WCHAR), "WCHAR[]"); snwprintf(wstr, n + 1, initErrorFormat, initErrorArgs); str = toUTF8(wstr); uiFree(wstr); if (hassysmsg) if (LocalFree(sysmsg) != NULL) logLastError("error freeing system message in loadLastError()"); uiFree(wmessage); return str; }
uiControl *uiAllocControl(size_t size, uint32_t OSsig, uint32_t typesig, const char *typenamestr) { uiControl *c; c = (uiControl *) uiAlloc(size, typenamestr); c->Signature = uiControlSignature; c->OSSignature = OSsig; c->TypeSignature = typesig; return c; }
WCHAR *fontDialogParamsToString(struct fontDialogParams *params) { WCHAR *text; // TODO dynamically allocate text = (WCHAR *) uiAlloc(512 * sizeof (WCHAR), "WCHAR[]"); _snwprintf(text, 512, L"%s %s %g", params->familyName, params->styleName, params->size); return text; }
static WCHAR *cbGetItemText(HWND cb, WPARAM item) { LRESULT len; WCHAR *text; // note: neither message includes the terminating L'\0' len = SendMessageW(cb, CB_GETLBTEXTLEN, item, 0); if (len == (LRESULT) CB_ERR) logLastError(L"error getting item text length from combobox"); text = (WCHAR *) uiAlloc((len + 1) * sizeof (WCHAR), "WCHAR[]"); if (SendMessageW(cb, CB_GETLBTEXT, item, (LPARAM) text) != len) logLastError(L"error getting item text from combobox"); return text; }
void *uiRealloc(void *p, size_t size, const char *type) { void *out; if (p == NULL) return uiAlloc(size, type); out = realloc(p, size); if (out == NULL) abort(); // TODO zero the extra memory #ifdef uiLogAllocations fprintf(stderr, "%p realloc %p\n", p, out); #endif return out; }
void *uiRealloc(void *p, size_t size, const char *type) { void *out; if (p == NULL) return uiAlloc(size, type); out = realloc(p, size); if (out == NULL) { fprintf(stderr, "memory exhausted in uiRealloc() reallocating %s\n", type); abort(); } // TODO zero the extra memory if (options.debugLogAllocations) fprintf(stderr, "%p realloc %p\n", p, out); return out; }
WCHAR *windowTextAndLen(HWND hwnd, LRESULT *len) { LRESULT n; WCHAR *text; n = SendMessageW(hwnd, WM_GETTEXTLENGTH, 0, 0); if (len != NULL) *len = n; // WM_GETTEXTLENGTH does not include the null terminator text = (WCHAR *) uiAlloc((n + 1) * sizeof (WCHAR), "WCHAR[]"); // note the comparison: the size includes the null terminator, but the return does not if (GetWindowTextW(hwnd, text, n + 1) != n) { logLastError(L"error getting window text"); // on error, return an empty string to be safe *text = L'\0'; if (len != NULL) *len = 0; } return text; }
size_t *graphemes(WCHAR *msg) { size_t len; SCRIPT_ITEM *items; int i, n; size_t *out; size_t *op; SCRIPT_LOGATTR *logattr; int j, nn; HRESULT hr; len = wcslen(msg); hr = itemize(msg, len, &items, &n); if (hr != S_OK) logHRESULT(L"error itemizing string for finding grapheme cluster boundaries", hr); // should be enough; 2 more just to be safe out = (size_t *) uiAlloc((len + 2) * sizeof (size_t), "size_t[]"); op = out; // note that there are actually n + 1 elements in items for (i = 0; i < n; i++) { nn = items[i + 1].iCharPos - items[i].iCharPos; logattr = new SCRIPT_LOGATTR[nn]; hr = ScriptBreak(msg + items[i].iCharPos, nn, &(items[i].a), logattr); if (hr != S_OK) logHRESULT(L"error breaking string for finding grapheme cluster boundaries", hr); for (j = 0; j < nn; j++) if (logattr[j].fCharStop != 0) *op++ = items[i].iCharPos + j; delete[] logattr; } // and handle the last item for the end of the string *op++ = items[i].iCharPos; delete[] items; return out; }
void uiDrawStroke(uiDrawContext *c, uiDrawPath *p, uiDrawBrush *b, uiDrawStrokeParams *sp) { ID2D1Brush *brush; ID2D1StrokeStyle *style; D2D1_STROKE_STYLE_PROPERTIES dsp; FLOAT *dashes; size_t i; ID2D1Layer *cliplayer; HRESULT hr; brush = makeBrush(b, c->rt); ZeroMemory(&dsp, sizeof (D2D1_STROKE_STYLE_PROPERTIES)); switch (sp->Cap) { case uiDrawLineCapFlat: dsp.startCap = D2D1_CAP_STYLE_FLAT; dsp.endCap = D2D1_CAP_STYLE_FLAT; dsp.dashCap = D2D1_CAP_STYLE_FLAT; break; case uiDrawLineCapRound: dsp.startCap = D2D1_CAP_STYLE_ROUND; dsp.endCap = D2D1_CAP_STYLE_ROUND; dsp.dashCap = D2D1_CAP_STYLE_ROUND; break; case uiDrawLineCapSquare: dsp.startCap = D2D1_CAP_STYLE_SQUARE; dsp.endCap = D2D1_CAP_STYLE_SQUARE; dsp.dashCap = D2D1_CAP_STYLE_SQUARE; break; } switch (sp->Join) { case uiDrawLineJoinMiter: dsp.lineJoin = D2D1_LINE_JOIN_MITER_OR_BEVEL; dsp.miterLimit = sp->MiterLimit; break; case uiDrawLineJoinRound: dsp.lineJoin = D2D1_LINE_JOIN_ROUND; break; case uiDrawLineJoinBevel: dsp.lineJoin = D2D1_LINE_JOIN_BEVEL; break; } dsp.dashStyle = D2D1_DASH_STYLE_SOLID; dashes = NULL; // note that dash widths and the dash phase are scaled up by the thickness by Direct2D // TODO be sure to formally document this if (sp->NumDashes != 0) { dsp.dashStyle = D2D1_DASH_STYLE_CUSTOM; dashes = (FLOAT *) uiAlloc(sp->NumDashes * sizeof (FLOAT), "FLOAT[]"); for (i = 0; i < sp->NumDashes; i++) dashes[i] = sp->Dashes[i] / sp->Thickness; } dsp.dashOffset = sp->DashPhase / sp->Thickness; hr = ID2D1Factory_CreateStrokeStyle(d2dfactory, &dsp, dashes, sp->NumDashes, &style); if (hr != S_OK) logHRESULT("error creating stroke style in uiDrawStroke()", hr); if (sp->NumDashes != 0) uiFree(dashes); cliplayer = applyClip(c); ID2D1RenderTarget_DrawGeometry(c->rt, (ID2D1Geometry *) (p->path), brush, sp->Thickness, style); unapplyClip(c, cliplayer); ID2D1StrokeStyle_Release(style); ID2D1Brush_Release(brush); }