Example #1
0
uiDrawPath *uiDrawNewPath(uiDrawFillMode fillmode)
{
	uiDrawPath *p;
	HRESULT hr;

	p = uiNew(uiDrawPath);
	hr = ID2D1Factory_CreatePathGeometry(d2dfactory,
		&(p->path));
	if (hr != S_OK)
		logHRESULT("error creating path in uiDrawNewPath()", hr);
	hr = ID2D1PathGeometry_Open(p->path,
		&(p->sink));
	if (hr != S_OK)
		logHRESULT("error opening path in uiDrawNewPath()", hr);
	switch (fillmode) {
	case uiDrawFillModeWinding:
		ID2D1GeometrySink_SetFillMode(p->sink,
			D2D1_FILL_MODE_WINDING);
		break;
	case uiDrawFillModeAlternate:
		ID2D1GeometrySink_SetFillMode(p->sink,
			D2D1_FILL_MODE_ALTERNATE);
		break;
	}
	return p;
}
Example #2
0
static void familyChanged(struct fontDialog *f)
{
	LRESULT pos;
	BOOL selected;
	IDWriteFontFamily *family;
	IDWriteFont *font, *matchFont;
	DWRITE_FONT_WEIGHT weight;
	DWRITE_FONT_STYLE style;
	DWRITE_FONT_STRETCH stretch;
	UINT32 i, n;
	UINT32 matching;
	WCHAR *label;
	HRESULT hr;

	selected = cbGetCurSel(f->familyCombobox, &pos);
	if (!selected)		// on deselect, do nothing
		return;
	f->curFamily = pos;

	family = (IDWriteFontFamily *) cbGetItemData(f->familyCombobox, (WPARAM) (f->curFamily));

	// for the nearest style match
	// when we select a new family, we want the nearest style to the previously selected one to be chosen
	// this is how the Choose Font sample does it
	hr = family->GetFirstMatchingFont(
		f->weight,
		f->stretch,
		f->style,
		&matchFont);
	if (hr != S_OK)
		logHRESULT(L"error finding first matching font to previous style in font dialog", hr);
	// we can't just compare pointers; a "newly created" object comes out
	// the Choose Font sample appears to do this instead
	weight = matchFont->GetWeight();
	style = matchFont->GetStyle();
	stretch = matchFont->GetStretch();
	matchFont->Release();

	// TODO test mutliple streteches; all the fonts I have have only one stretch value?
	wipeStylesBox(f);
	n = family->GetFontCount();
	matching = 0;			// a safe/suitable default just in case
	for (i = 0; i < n; i++) {
		hr = family->GetFont(i, &font);
		if (hr != S_OK)
			logHRESULT(L"error getting font for filling styles box", hr);
		label = fontStyleName(f->fc, font);
		pos = cbAddString(f->styleCombobox, label);
		uiFree(label);
		cbSetItemData(f->styleCombobox, (WPARAM) pos, (LPARAM) font);
		if (font->GetWeight() == weight &&
			font->GetStyle() == style &&
			font->GetStretch() == stretch)
			matching = i;
	}

	// and now, load the match
	cbSetCurSel(f->styleCombobox, (WPARAM) matching);
	styleChanged(f);
}
Example #3
0
// once again, this is based on the Microsoft sample above
static void drawOpacitySlider(struct colorDialog *c, ID2D1RenderTarget *rt)
{
	D2D1_SIZE_F size;
	D2D1_RECT_F rect;
	D2D1_GRADIENT_STOP stops[2];
	ID2D1GradientStopCollection *collection;
	D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES lprop;
	D2D1_BRUSH_PROPERTIES bprop;
	ID2D1LinearGradientBrush *brush;
	double hypot;
	D2D1_POINT_2F center;
	HRESULT hr;

	size = realGetSize(rt);
	rect.left = 0;
	rect.top = 0;
	rect.right = size.width;
	rect.bottom = size.height * (5.0 / 6.0);		// bottommost sixth for arrow

	drawGrid(rt, &rect);

	stops[0].position = 0.0;
	stops[0].color.r = 0.0;
	stops[0].color.g = 0.0;
	stops[0].color.b = 0.0;
	stops[0].color.a = 1.0;
	stops[1].position = 1.0;
	stops[1].color.r = 1.0;		// this is the XAML color Transparent, as in the source
	stops[1].color.g = 1.0;
	stops[1].color.b = 1.0;
	stops[1].color.a = 0.0;
	hr = rt->CreateGradientStopCollection(stops, 2,
		// note that in this case this gamma is explicitly specified by the original
		D2D1_GAMMA_2_2, D2D1_EXTEND_MODE_CLAMP,
		&collection);
	if (hr != S_OK)
		logHRESULT(L"error creating stop collection for opacity slider gradient", hr);
	ZeroMemory(&lprop, sizeof (D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES));
	lprop.startPoint.x = 0;
	lprop.startPoint.y = (rect.bottom - rect.top) / 2;
	lprop.endPoint.x = size.width;
	lprop.endPoint.y = (rect.bottom - rect.top) / 2;
	ZeroMemory(&bprop, sizeof (D2D1_BRUSH_PROPERTIES));
	bprop.opacity = 1.0;
	bprop.transform._11 = 1;
	bprop.transform._22 = 1;
	hr = rt->CreateLinearGradientBrush(&lprop, &bprop,
		collection, &brush);
	if (hr != S_OK)
		logHRESULT(L"error creating gradient brush for opacity slider", hr);
	rt->FillRectangle(&rect, brush);
	brush->Release();
	collection->Release();

	// now draw a black arrow
	center.x = (1 - c->a) * size.width;
	center.y = size.height;
	hypot = size.height - rect.bottom;
	drawArrow(rt, center, hypot);
}
Example #4
0
// TODO run again when the DPI or the theme changes
// TODO properly clean things up here
// TODO properly destroy the old lists here too
HRESULT uiprivUpdateImageListSize(uiTable *t)
{
	HDC dc;
	int cxList, cyList;
	HTHEME theme;
	SIZE sizeCheck;
	HRESULT hr;

	dc = GetDC(t->hwnd);
	if (dc == NULL) {
		logLastError(L"GetDC()");
		return E_FAIL;
	}

	cxList = GetSystemMetrics(SM_CXSMICON);
	cyList = GetSystemMetrics(SM_CYSMICON);
	sizeCheck.cx = cxList;
	sizeCheck.cy = cyList;
	theme = OpenThemeData(t->hwnd, L"button");
	if (theme != NULL) {
		hr = GetThemePartSize(theme, dc,
			BP_CHECKBOX, CBS_UNCHECKEDNORMAL,
			NULL, TS_DRAW, &sizeCheck);
		if (hr != S_OK) {
			logHRESULT(L"GetThemePartSize()", hr);
			return hr;			// TODO fall back?
		}
		// make sure these checkmarks fit
		// unthemed checkmarks will by the code above be smaller than cxList/cyList here
		if (cxList < sizeCheck.cx)
			cxList = sizeCheck.cx;
		if (cyList < sizeCheck.cy)
			cyList = sizeCheck.cy;
		hr = CloseThemeData(theme);
		if (hr != S_OK) {
			logHRESULT(L"CloseThemeData()", hr);
			return hr;
		}
	}

	// TODO handle errors
	t->imagelist = ImageList_Create(cxList, cyList,
		ILC_COLOR32,
		1, 1);
	if (t->imagelist == NULL) {
		logLastError(L"ImageList_Create()");
		return E_FAIL;
	}
	// TODO will this return NULL here because it's an initial state?
	SendMessageW(t->hwnd, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM) (t->imagelist));

	if (ReleaseDC(t->hwnd, dc) == 0) {
		logLastError(L"ReleaseDC()");
		return E_FAIL;
	}
	return S_OK;
}
Example #5
0
static ID2D1Brush *makeRadialBrush(uiDrawBrush *b, ID2D1RenderTarget *rt, D2D1_BRUSH_PROPERTIES *props)
{
	ID2D1RadialGradientBrush *brush;
	D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES gprops;
	ID2D1GradientStopCollection *stops;
	HRESULT hr;

	ZeroMemory(&gprops, sizeof (D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES));
	gprops.gradientOriginOffset.x = b->X0 - b->X1;
	gprops.gradientOriginOffset.y = b->Y0 - b->Y1;
	gprops.center.x = b->X1;
	gprops.center.y = b->Y1;
	gprops.radiusX = b->OuterRadius;
	gprops.radiusY = b->OuterRadius;

	stops = mkstops(b, rt);

	hr = ID2D1RenderTarget_CreateRadialGradientBrush(rt,
		&gprops,
		props,
		stops,
		&brush);
	if (hr != S_OK)
		logHRESULT("error creating gradient brush in makeRadialBrush()", hr);

	ID2D1GradientStopCollection_Release(stops);
	return (ID2D1Brush *) brush;
}
Example #6
0
static ID2D1Brush *makeLinearBrush(uiDrawBrush *b, ID2D1RenderTarget *rt, D2D1_BRUSH_PROPERTIES *props)
{
	ID2D1LinearGradientBrush *brush;
	D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES gprops;
	ID2D1GradientStopCollection *stops;
	HRESULT hr;

	ZeroMemory(&gprops, sizeof (D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES));
	gprops.startPoint.x = b->X0;
	gprops.startPoint.y = b->Y0;
	gprops.endPoint.x = b->X1;
	gprops.endPoint.y = b->Y1;

	stops = mkstops(b, rt);

	hr = ID2D1RenderTarget_CreateLinearGradientBrush(rt,
		&gprops,
		props,
		stops,
		&brush);
	if (hr != S_OK)
		logHRESULT("error creating gradient brush in makeLinearBrush()", hr);

	// the example at https://msdn.microsoft.com/en-us/library/windows/desktop/dd756682%28v=vs.85%29.aspx says this is safe to do now
	ID2D1GradientStopCollection_Release(stops);
	return (ID2D1Brush *) brush;
}
Example #7
0
static void drawPreview(struct colorDialog *c, ID2D1RenderTarget *rt)
{
	D2D1_SIZE_F size;
	D2D1_RECT_F rect;
	double r, g, b;
	D2D1_COLOR_F color;
	D2D1_BRUSH_PROPERTIES bprop;
	ID2D1SolidColorBrush *brush;
	HRESULT hr;

	size = realGetSize(rt);
	rect.left = 0;
	rect.top = 0;
	rect.right = size.width;
	rect.bottom = size.height;

	drawGrid(rt, &rect);

	hsv2RGB(c->h, c->s, c->v, &r, &g, &b);
	color.r = r;
	color.g = g;
	color.b = b;
	color.a = c->a;
	ZeroMemory(&bprop, sizeof (D2D1_BRUSH_PROPERTIES));
	bprop.opacity = 1.0;
	bprop.transform._11 = 1;
	bprop.transform._22 = 1;
	hr = rt->CreateSolidColorBrush(&color, &bprop, &brush);
	if (hr != S_OK)
		logHRESULT(L"error creating brush for preview", hr);
	rt->FillRectangle(&rect, brush);
	brush->Release();
}
Example #8
0
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;
}
Example #9
0
static HRESULT drawCheckboxPart(HRESULT hr, struct drawState *s)
{
	uiTableValue *value;
	int checked, enabled;
	HTHEME theme;

	if (hr != S_OK)
		return hr;
	if (s->p->checkboxModelColumn == -1)
		return S_OK;

	value = uiprivTableModelCellValue(s->model, s->iItem, s->p->checkboxModelColumn);
	checked = uiTableValueInt(value);
	uiFreeTableValue(value);
	enabled = uiprivTableModelCellEditable(s->model, s->iItem, s->p->checkboxEditableModelColumn);

	theme = OpenThemeData(s->t->hwnd, L"button");
	if (theme != NULL) {
		hr = drawThemedCheckbox(s, theme, checked, enabled);
		if (hr != S_OK)
			return hr;
		hr = CloseThemeData(theme);
		if (hr != S_OK) {
			logHRESULT(L"CloseThemeData()", hr);
			return hr;
		}
	} else {
		hr = drawUnthemedCheckbox(s, checked, enabled);
		if (hr != S_OK)
			return hr;
	}
	return S_OK;
}
Example #10
0
// TODO for this, stroke, and fill, make sure that an open path causes error state
void uiDrawClip(uiDrawContext *c, uiDrawPath *path)
{
	ID2D1PathGeometry *newPath;
	ID2D1GeometrySink *newSink;
	HRESULT hr;

	// if there's no current clip, borrow the path
	if (c->currentClip == NULL) {
		c->currentClip = path->path;
		// we have to take our own reference to that clip
		ID2D1PathGeometry_AddRef(c->currentClip);
		return;
	}

	// otherwise we have to intersect the current path with the new one
	// we do that into a new path, and then replace c->currentClip with that new path
	hr = ID2D1Factory_CreatePathGeometry(d2dfactory,
		&newPath);
	if (hr != S_OK)
		logHRESULT("error creating new path in uiDrawClip()", hr);
	hr = ID2D1PathGeometry_Open(newPath,
		&newSink);
	if (hr != S_OK)
		logHRESULT("error opening new path in uiDrawClip()", hr);
	// TODO BUG IN MINGW
	// the macro is supposed to take 6 parameters
	hr = (*(c->currentClip->lpVtbl->Base.CombineWithGeometry))(
		(ID2D1Geometry *) (c->currentClip),
		(ID2D1Geometry *) (path->path),
		D2D1_COMBINE_MODE_INTERSECT,
		NULL,
		// TODO is this correct or can this be set per target?
		D2D1_DEFAULT_FLATTENING_TOLERANCE,
		(ID2D1SimplifiedGeometrySink *) newSink);
	if (hr != S_OK)
		logHRESULT("error intersecting old path with new path in uiDrawClip()", hr);
	hr = ID2D1GeometrySink_Close(newSink);
	if (hr != S_OK)
		logHRESULT("error closing new path in uiDrawClip()", hr);
	ID2D1GeometrySink_Release(newSink);

	// okay we have the new clip; we just need to replace the old one with it
	ID2D1PathGeometry_Release(c->currentClip);
	c->currentClip = newPath;
	// we have a reference already; no need for another
}
Example #11
0
static IDWriteFontFamily *tryFindFamily(IDWriteFontCollection *fc, const WCHAR *name)
{
	UINT32 index;
	BOOL exists;
	IDWriteFontFamily *family;
	HRESULT hr;

	hr = fc->FindFamilyName(name, &index, &exists);
	if (hr != S_OK)
		logHRESULT(L"error finding font family for font dialog", hr);
	if (!exists)
		return NULL;
	hr = fc->GetFontFamily(index, &family);
	if (hr != S_OK)
		logHRESULT(L"error extracting found font family for font dialog", hr);
	return family;
}
Example #12
0
void loadInitialFontDialogParams(struct fontDialogParams *params)
{
	struct fontCollection *fc;
	IDWriteFontFamily *family;
	IDWriteFont *font;
	HRESULT hr;

	// Our preferred font is Arial 10 Regular.
	// 10 comes from the official font dialog.
	// Arial Regular is a reasonable, if arbitrary, default; it's similar to the defaults on other systems.
	// If Arial isn't found, we'll use Helvetica and then MS Sans Serif as fallbacks, and if not, we'll just grab the first font family in the collection.

	// We need the correct localized name for Regular (and possibly Arial too? let's say yes to be safe), so let's grab the strings from DirectWrite instead of hardcoding them.
	fc = loadFontCollection();
	family = tryFindFamily(fc->fonts, L"Arial");
	if (family == NULL) {
		family = tryFindFamily(fc->fonts, L"Helvetica");
		if (family == NULL) {
			family = tryFindFamily(fc->fonts, L"MS Sans Serif");
			if (family == NULL) {
				hr = fc->fonts->GetFontFamily(0, &family);
				if (hr != S_OK)
					logHRESULT(L"error getting first font out of font collection (worst case scenario)", hr);
			}
		}
	}

	// next part is simple: just get the closest match to regular
	hr = family->GetFirstMatchingFont(
		DWRITE_FONT_WEIGHT_NORMAL,
		DWRITE_FONT_STRETCH_NORMAL,
		DWRITE_FONT_STYLE_NORMAL,
		&font);
	if (hr != S_OK)
		logHRESULT(L"error getting Regular font from Arial", hr);

	params->font = font;
	params->size = 10;
	params->familyName = fontCollectionFamilyName(fc, family);
	params->styleName = fontStyleName(fc, font);

	// don't release font; we still need it
	family->Release();
	fontCollectionFree(fc);
}
Example #13
0
IDWriteTypography *uiprivOpenTypeFeaturesToIDWriteTypography(const uiOpenTypeFeatures *otf)
{
	IDWriteTypography *dt;
	HRESULT hr;

	hr = dwfactory->CreateTypography(&dt);
	if (hr != S_OK)
		logHRESULT(L"error creating IDWriteTypography", hr);
	uiOpenTypeFeaturesForEach(otf, addToTypography, dt);
	return dt;
}
Example #14
0
WCHAR *uiprivFontCollectionFamilyName(fontCollection *fc, IDWriteFontFamily *family)
{
	IDWriteLocalizedStrings *names;
	WCHAR *str;
	HRESULT hr;

	hr = family->GetFamilyNames(&names);
	if (hr != S_OK)
		logHRESULT(L"error getting names of font out", hr);
	str = uiprivFontCollectionCorrectString(fc, names);
	names->Release();
	return str;
}
Example #15
0
fontCollection *uiprivLoadFontCollection(void)
{
	fontCollection *fc;
	HRESULT hr;

	fc = uiprivNew(fontCollection);
	// always get the latest available font information
	hr = dwfactory->GetSystemFontCollection(&(fc->fonts), TRUE);
	if (hr != S_OK)
		logHRESULT(L"error getting system font collection", hr);
	fc->userLocaleSuccess = GetUserDefaultLocaleName(fc->userLocale, LOCALE_NAME_MAX_LENGTH);
	return fc;
}
Example #16
0
static WCHAR *fontStyleName(struct fontCollection *fc, IDWriteFont *font)
{
	IDWriteLocalizedStrings *str;
	WCHAR *wstr;
	HRESULT hr;

	hr = font->GetFaceNames(&str);
	if (hr != S_OK)
		logHRESULT(L"error getting font style name for font dialog", hr);
	wstr = fontCollectionCorrectString(fc, str);
	str->Release();
	return wstr;
}
Example #17
0
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;
}
Example #18
0
char *commonItemDialog(HWND parent, REFCLSID clsid, REFIID iid, FILEOPENDIALOGOPTIONS optsadd)
{
	IFileDialog *d = NULL;
	FILEOPENDIALOGOPTIONS opts;
	IShellItem *result = NULL;
	WCHAR *wname = NULL;
	char *name = NULL;
	HRESULT hr;

	hr = CoCreateInstance(clsid,
		NULL, CLSCTX_INPROC_SERVER,
		iid, (LPVOID *) (&d));
	if (hr != S_OK) {
		logHRESULT(L"error creating common item dialog", hr);
		// always return NULL on error
		goto out;
	}
	hr = d->GetOptions(&opts);
	if (hr != S_OK) {
		logHRESULT(L"error getting current options", hr);
		goto out;
	}
	opts |= optsadd;
	// the other platforms don't check read-only; we won't either
	opts &= ~FOS_NOREADONLYRETURN;
	hr = d->SetOptions(opts);
	if (hr != S_OK) {
		logHRESULT(L"error setting options", hr);
		goto out;
	}
	hr = d->Show(parent);
	if (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED))
		// cancelled; return NULL like we have ready
		goto out;
	if (hr != S_OK) {
		logHRESULT(L"error showing dialog", hr);
		goto out;
	}
	hr = d->GetResult(&result);
	if (hr != S_OK) {
		logHRESULT(L"error getting dialog result", hr);
		goto out;
	}
	hr = result->GetDisplayName(SIGDN_FILESYSPATH, &wname);
	if (hr != S_OK) {
		logHRESULT(L"error getting filename", hr);
		goto out;
	}
	name = toUTF8(wname);

out:
	if (wname != NULL)
		CoTaskMemFree(wname);
	if (result != NULL)
		result->Release();
	if (d != NULL)
		d->Release();
	return name;
}
Example #19
0
static uiForEach addToTypography(const uiOpenTypeFeatures *otf, char a, char b, char c, char d, uint32_t value, void *data)
{
	IDWriteTypography *dt = (IDWriteTypography *) data;
	DWRITE_FONT_FEATURE dff;
	HRESULT hr;

	ZeroMemory(&dff, sizeof (DWRITE_FONT_FEATURE));
	// yes, the cast here is necessary (the compiler will complain otherwise)...
	dff.nameTag = (DWRITE_FONT_FEATURE_TAG) DWRITE_MAKE_OPENTYPE_TAG(a, b, c, d);
	dff.parameter = (UINT32) value;
	hr = dt->AddFontFeature(dff);
	if (hr != S_OK)
		logHRESULT(L"error adding OpenType feature to IDWriteTypography", hr);
	return uiForEachContinue;
}
Example #20
0
static HRESULT drawThemedCheckbox(struct drawState *s, HTHEME theme, int checked, int enabled)
{
	RECT r;
	SIZE size;
	int state;
	HRESULT hr;

	hr = GetThemePartSize(theme, s->dc,
		BP_CHECKBOX, CBS_UNCHECKEDNORMAL,
		NULL, TS_DRAW, &size);
	if (hr != S_OK) {
		logHRESULT(L"GetThemePartSize()", hr);
		return hr;			// TODO fall back?
	}
	r = s->m->subitemIcon;
	r.right = r.left + size.cx;
	r.bottom = r.top + size.cy;

	centerImageRect(&r, &(s->m->subitemIcon));
	if (!checked && enabled)
		state = CBS_UNCHECKEDNORMAL;
	else if (checked && enabled)
		state = CBS_CHECKEDNORMAL;
	else if (!checked && !enabled)
		state = CBS_UNCHECKEDDISABLED;
	else
		state = CBS_CHECKEDDISABLED;
	hr = DrawThemeBackground(theme, s->dc,
		BP_CHECKBOX, state,
		&r, NULL);
	if (hr != S_OK) {
		logHRESULT(L"DrawThemeBackground()", hr);
		return hr;
	}
	return S_OK;
}
Example #21
0
WCHAR *uiprivFontCollectionCorrectString(fontCollection *fc, IDWriteLocalizedStrings *names)
{
	UINT32 index;
	BOOL exists;
	UINT32 length;
	WCHAR *wname;
	HRESULT hr;

	// this is complex, but we ignore failure conditions to allow fallbacks
	// 1) If the user locale name was successfully retrieved, try it
	// 2) If the user locale name was not successfully retrieved, or that locale's string does not exist, or an error occurred, try L"en-us", the US English locale
	// 3) And if that fails, assume the first one
	// This algorithm is straight from MSDN: https://msdn.microsoft.com/en-us/library/windows/desktop/dd368214%28v=vs.85%29.aspx
	// For step 2 to work, start by setting hr to S_OK and exists to FALSE.
	// TODO does it skip step 2 entirely if step 1 fails? rewrite it to be a more pure conversion of the MSDN code?
	hr = S_OK;
	exists = FALSE;
	if (fc->userLocaleSuccess != 0)
		hr = names->FindLocaleName(fc->userLocale, &index, &exists);
	if (hr != S_OK || (hr == S_OK && !exists))
		hr = names->FindLocaleName(L"en-us", &index, &exists);
	// TODO check hr again here? or did I decide that would be redundant because COM requires output arguments to be filled regardless of return value?
	if (!exists)
		index = 0;

	hr = names->GetStringLength(index, &length);
	if (hr != S_OK)
		logHRESULT(L"error getting length of font name", hr);
	// GetStringLength() does not include the null terminator, but GetString() does
	wname = (WCHAR *) uiprivAlloc((length + 1) * sizeof (WCHAR), "WCHAR[]");
	hr = names->GetString(index, wname, length + 1);
	if (hr != S_OK)
		logHRESULT(L"error getting font name", hr);

	return wname;
}
Example #22
0
static void msgbox(HWND parent, const char *title, const char *description, TASKDIALOG_COMMON_BUTTON_FLAGS buttons, PCWSTR icon)
{
	WCHAR *wtitle, *wdescription;
	HRESULT hr;

	wtitle = toUTF16(title);
	wdescription = toUTF16(description);

	hr = TaskDialog(parent, NULL, NULL, wtitle, wdescription, buttons, icon, NULL);
	if (hr != S_OK)
		logHRESULT(L"error showing task dialog", hr);

	uiFree(wdescription);
	uiFree(wtitle);
}
Example #23
0
void uiDrawPathEnd(uiDrawPath *p)
{
	HRESULT hr;

	if (p->inFigure) {
		ID2D1GeometrySink_EndFigure(p->sink,
			D2D1_FIGURE_END_OPEN);
		// needed for uiDrawFreePath()
		p->inFigure = FALSE;
	}
	hr = ID2D1GeometrySink_Close(p->sink);
	if (hr != S_OK)
		logHRESULT("error closing path in uiDrawPathEnd()", hr);
	ID2D1GeometrySink_Release(p->sink);
	p->sink = NULL;
}
Example #24
0
static ID2D1Layer *applyClip(uiDrawContext *c)
{
	ID2D1Layer *layer;
	D2D1_LAYER_PARAMETERS params;
	HRESULT hr;

	// if no clip, don't do anything
	if (c->currentClip == NULL)
		return NULL;

	// create a layer for clipping
	// we have to explicitly make the layer because we're still targeting Windows 7
	// TODO MINGW BUG
	// this macro is supposed to take three parameters
	hr = (*(c->rt->lpVtbl->CreateLayer))(c->rt,
		NULL,
		&layer);
	if (hr != S_OK)
		logHRESULT("error creating clip layer in applyClip()", hr);

	// apply it as the clip
	ZeroMemory(&params, sizeof (D2D1_LAYER_PARAMETERS));
	// this is the equivalent of InfiniteRect() in d2d1helper.h
	params.contentBounds.left = -FLT_MAX;
	params.contentBounds.top = -FLT_MAX;
	params.contentBounds.right = FLT_MAX;
	params.contentBounds.bottom = FLT_MAX;
	params.geometricMask = (ID2D1Geometry *) (c->currentClip);
	// TODO is this correct?
	params.maskAntialiasMode = ID2D1RenderTarget_GetAntialiasMode(c->rt);
	// identity matrix
	params.maskTransform._11 = 1;
	params.maskTransform._22 = 1;
	params.opacity = 1.0;
	params.opacityBrush = NULL;
	params.layerOptions = D2D1_LAYER_OPTIONS_NONE;
	// TODO is this correct?
	if (ID2D1RenderTarget_GetTextAntialiasMode(c->rt) == D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE)
		params.layerOptions = D2D1_LAYER_OPTIONS_INITIALIZE_FOR_CLEARTYPE;
	ID2D1RenderTarget_PushLayer(c->rt,
		&params,
		layer);

	// return the layer so it can be freed later
	return layer;
}
Example #25
0
static void drawArrow(ID2D1RenderTarget *rt, D2D1_POINT_2F center, double hypot)
{
	double leg;
	D2D1_RECT_F rect;
	D2D1_MATRIX_3X2_F oldtf, rotate;
	D2D1_COLOR_F color;
	D2D1_BRUSH_PROPERTIES bprop;
	ID2D1SolidColorBrush *brush;
	HRESULT hr;

	// to avoid needing a geometry, this will just be a rotated square
	// compute the length of each side; the diagonal of the square is 2 * offset to gradient
	// a^2 + a^2 = c^2 -> 2a^2 = c^2
	// a = sqrt(c^2/2)
	hypot *= hypot;
	hypot /= 2;
	leg = sqrt(hypot);
	rect.left = center.x - leg;
	rect.top = center.y - leg;
	rect.right = center.x + leg;
	rect.bottom = center.y + leg;

	// now we need to rotate the render target 45° (either way works) about the center point
	rt->GetTransform(&oldtf);
	rotate = oldtf * D2D1::Matrix3x2F::Rotation(45, center);
	rt->SetTransform(&rotate);

	// and draw
	color.r = 0.0;
	color.g = 0.0;
	color.b = 0.0;
	color.a = 1.0;
	ZeroMemory(&bprop, sizeof (D2D1_BRUSH_PROPERTIES));
	bprop.opacity = 1.0;
	bprop.transform._11 = 1;
	bprop.transform._22 = 1;
	hr = rt->CreateSolidColorBrush(&color, &bprop, &brush);
	if (hr != S_OK)
		logHRESULT(L"error creating brush for arrow", hr);
	rt->FillRectangle(&rect, brush);
	brush->Release();

	// clean up
	rt->SetTransform(&oldtf);
}
Example #26
0
static void msgbox(const char *title, const char *description, TASKDIALOG_COMMON_BUTTON_FLAGS buttons, PCWSTR icon)
{
	WCHAR *wtitle, *wdescription;
	HWND dialogHelper;
	HRESULT hr;

	wtitle = toUTF16(title);
	wdescription = toUTF16(description);

	dialogHelper = beginDialogHelper();
	hr = TaskDialog(dialogHelper, NULL, NULL, wtitle, wdescription, buttons, icon, NULL);
	if (hr != S_OK)
		logHRESULT("error showing task dialog in msgbox()", hr);
	endDialogHelper(dialogHelper);

	uiFree(wdescription);
	uiFree(wtitle);
}
Example #27
0
ID2D1HwndRenderTarget *makeHWNDRenderTarget(HWND hwnd)
{
	D2D1_RENDER_TARGET_PROPERTIES props;
	D2D1_HWND_RENDER_TARGET_PROPERTIES hprops;
	HDC dc;
	RECT r;
	ID2D1HwndRenderTarget *rt;
	HRESULT hr;

	// we need a DC for the DPI
	// we *could* just use the screen DPI but why when we have a window handle and its DC has a DPI
	dc = GetDC(hwnd);
	if (dc == NULL)
		logLastError("error getting DC to find DPI in makeHWNDRenderTarget()");

	ZeroMemory(&props, sizeof (D2D1_RENDER_TARGET_PROPERTIES));
	props.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
	props.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
	props.pixelFormat.alphaMode = D2D1_ALPHA_MODE_UNKNOWN;
	props.dpiX = GetDeviceCaps(dc, LOGPIXELSX);
	props.dpiY = GetDeviceCaps(dc, LOGPIXELSY);
	props.usage = D2D1_RENDER_TARGET_USAGE_NONE;
	props.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;

	if (ReleaseDC(hwnd, dc) == 0)
		logLastError("error releasing DC for finding DPI in makeHWNDRenderTarget()");

	if (GetClientRect(hwnd, &r) == 0)
		logLastError("error getting current size of window in makeHWNDRenderTarget()");

	ZeroMemory(&hprops, sizeof (D2D1_HWND_RENDER_TARGET_PROPERTIES));
	hprops.hwnd = hwnd;
	hprops.pixelSize.width = r.right - r.left;
	hprops.pixelSize.height = r.bottom - r.top;
	hprops.presentOptions = D2D1_PRESENT_OPTIONS_NONE;

	hr = ID2D1Factory_CreateHwndRenderTarget(d2dfactory,
		&props,
		&hprops,
		&rt);
	if (hr != S_OK)
		logHRESULT("error creating area HWND render target in makeHWNDRenderTarget()", hr);
	return rt;
}
Example #28
0
static ID2D1Brush *makeSolidBrush(uiDrawBrush *b, ID2D1RenderTarget *rt, D2D1_BRUSH_PROPERTIES *props)
{
	D2D1_COLOR_F color;
	ID2D1SolidColorBrush *brush;
	HRESULT hr;

	color.r = b->R;
	color.g = b->G;
	color.b = b->B;
	color.a = b->A;

	hr = ID2D1RenderTarget_CreateSolidColorBrush(rt,
		&color,
		props,
		&brush);
	if (hr != S_OK)
		logHRESULT("error creating solid brush in makeSolidBrush()", hr);
	return (ID2D1Brush *) brush;
}
Example #29
0
static struct fontDialog *beginFontDialog(HWND hwnd, LPARAM lParam)
{
	struct fontDialog *f;
	UINT32 i, nFamilies;
	IDWriteFontFamily *family;
	WCHAR *wname;
	LRESULT pos;
	HWND samplePlacement;
	HRESULT hr;

	f = uiNew(struct fontDialog);
	f->hwnd = hwnd;
	f->params = (struct fontDialogParams *) lParam;

	f->familyCombobox = getDlgItem(f->hwnd, rcFontFamilyCombobox);
	f->styleCombobox = getDlgItem(f->hwnd, rcFontStyleCombobox);
	f->sizeCombobox = getDlgItem(f->hwnd, rcFontSizeCombobox);

	f->fc = loadFontCollection();
	nFamilies = f->fc->fonts->GetFontFamilyCount();
	for (i = 0; i < nFamilies; i++) {
		hr = f->fc->fonts->GetFontFamily(i, &family);
		if (hr != S_OK)
			logHRESULT(L"error getting font family", hr);
		wname = fontCollectionFamilyName(f->fc, family);
		pos = cbAddString(f->familyCombobox, wname);
		uiFree(wname);
		cbSetItemData(f->familyCombobox, (WPARAM) pos, (LPARAM) family);
	}

	for (i = 0; defaultSizes[i].text != NULL; i++)
		cbInsertString(f->sizeCombobox, defaultSizes[i].text, (WPARAM) i);

	samplePlacement = getDlgItem(f->hwnd, rcFontSamplePlacement);
	uiWindowsEnsureGetWindowRect(samplePlacement, &(f->sampleRect));
	mapWindowRect(NULL, f->hwnd, &(f->sampleRect));
	uiWindowsEnsureDestroyWindow(samplePlacement);
	f->sampleBox = newD2DScratch(f->hwnd, &(f->sampleRect), (HMENU) rcFontSamplePlacement, fontDialogSampleSubProc, (DWORD_PTR) f);

	setupInitialFontDialogState(f);
	return f;
}
Example #30
0
char *commonItemDialog(REFCLSID clsid, REFIID iid, FILEOPENDIALOGOPTIONS optsadd)
{
	IFileDialog *d;
	FILEOPENDIALOGOPTIONS opts;
	HWND dialogHelper;
	IShellItem *result;
	WCHAR *wname;
	char *name;
	HRESULT hr;

	hr = CoCreateInstance(clsid,
		NULL, CLSCTX_INPROC_SERVER,
		iid, (LPVOID *) (&d));
	if (hr != S_OK)
		logHRESULT("error creating common item dialog in commonItemDialog()", hr);
	hr = IFileDialog_GetOptions(d, &opts);
	if (hr != S_OK)
		logHRESULT("error getting current options in commonItemDialog()", hr);
	opts |= optsadd;
	hr = IFileDialog_SetOptions(d, opts);
	if (hr != S_OK)
		logHRESULT("error setting options in commonItemDialog()", hr);
	dialogHelper = beginDialogHelper();
	hr = IFileDialog_Show(d, dialogHelper);
	endDialogHelper(dialogHelper);
	if (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED)) {
		IFileDialog_Release(d);
		return NULL;
	}
	if (hr != S_OK)
		logHRESULT("error showing dialog in commonItemDialog()", hr);
	hr = IFileDialog_GetResult(d, &result);
	if (hr != S_OK)
		logHRESULT("error getting dialog result in commonItemDialog()", hr);
	hr = IShellItem_GetDisplayName(result, SIGDN_FILESYSPATH, &wname);
	if (hr != S_OK)
		logHRESULT("error getting filename in commonItemDialog()", hr);
	name = toUTF8(wname);
	CoTaskMemFree(wname);
	IShellItem_Release(result);
	IFileDialog_Release(d);
	return name;
}