void MWinDeviceImpl::ClipRect( MRect inRect) { if (mClipLayer != nil) { mRenderTarget->PopLayer(); mClipLayer->Release(); } THROW_IF_HRESULT_ERROR(mRenderTarget->CreateLayer(&mClipLayer)); // Push the layer with the geometric mask. mRenderTarget->PushLayer( D2D1::LayerParameters(D2D1::RectF(inRect.x, inRect.y, inRect.x + inRect.width, inRect.y + inRect.height)), mClipLayer); }
// this interesting approach comes from http://blogs.msdn.com/b/wpfsdk/archive/2006/10/26/uncommon-dialogs--font-chooser-and-color-picker-dialogs.aspx static void drawSVChooser(struct colorDialog *c, ID2D1RenderTarget *rt) { D2D1_SIZE_F size; D2D1_RECT_F rect; double rTop, gTop, bTop; D2D1_GRADIENT_STOP stops[2]; ID2D1GradientStopCollection *collection; D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES lprop; D2D1_BRUSH_PROPERTIES bprop; ID2D1LinearGradientBrush *brush; ID2D1LinearGradientBrush *opacity; ID2D1Layer *layer; D2D1_LAYER_PARAMETERS layerparams; D2D1_ELLIPSE mparam; D2D1_COLOR_F mcolor; ID2D1SolidColorBrush *markerBrush; HRESULT hr; size = realGetSize(rt); rect.left = 0; rect.top = 0; rect.right = size.width; rect.bottom = size.height; drawGrid(rt, &rect); // first, draw a vertical gradient from the current hue at max S/V to black // the source example draws it upside down; let's do so too just to be safe hsv2RGB(c->h, 1.0, 1.0, &rTop, &gTop, &bTop); stops[0].position = 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; stops[1].color.r = rTop; stops[1].color.g = gTop; stops[1].color.b = bTop; stops[1].color.a = 1.0; hr = rt->CreateGradientStopCollection(stops, 2, D2D1_GAMMA_2_2, D2D1_EXTEND_MODE_CLAMP, &collection); if (hr != S_OK) logHRESULT(L"error making gradient stop collection for first gradient in SV chooser", hr); ZeroMemory(&lprop, sizeof (D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES)); lprop.startPoint.x = size.width / 2; lprop.startPoint.y = size.height; lprop.endPoint.x = size.width / 2; lprop.endPoint.y = 0; // TODO decide what to do about the duplication of this ZeroMemory(&bprop, sizeof (D2D1_BRUSH_PROPERTIES)); bprop.opacity = c->a; // note this part; we also use it below for the layer bprop.transform._11 = 1; bprop.transform._22 = 1; hr = rt->CreateLinearGradientBrush(&lprop, &bprop, collection, &brush); if (hr != S_OK) logHRESULT(L"error making gradient brush for first gradient in SV chooser", hr); rt->FillRectangle(&rect, brush); brush->Release(); collection->Release(); // second, create an opacity mask for the third step: a horizontal gradientthat goes from opaque to translucent stops[0].position = 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; stops[1].color.r = 0.0; stops[1].color.g = 0.0; stops[1].color.b = 0.0; stops[1].color.a = 0.0; hr = rt->CreateGradientStopCollection(stops, 2, D2D1_GAMMA_2_2, D2D1_EXTEND_MODE_CLAMP, &collection); if (hr != S_OK) logHRESULT(L"error making gradient stop collection for opacity mask gradient in SV chooser", hr); ZeroMemory(&lprop, sizeof (D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES)); lprop.startPoint.x = 0; lprop.startPoint.y = size.height / 2; lprop.endPoint.x = size.width; lprop.endPoint.y = size.height / 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, &opacity); if (hr != S_OK) logHRESULT(L"error making gradient brush for opacity mask gradient in SV chooser", hr); collection->Release(); // finally, make a vertical gradient from white at the top to black at the bottom (right side up this time) and with the previous opacity mask stops[0].position = 0; stops[0].color.r = 1.0; stops[0].color.g = 1.0; stops[0].color.b = 1.0; stops[0].color.a = 1.0; stops[1].position = 1; stops[1].color.r = 0.0; stops[1].color.g = 0.0; stops[1].color.b = 0.0; stops[1].color.a = 1.0; hr = rt->CreateGradientStopCollection(stops, 2, D2D1_GAMMA_2_2, D2D1_EXTEND_MODE_CLAMP, &collection); if (hr != S_OK) logHRESULT(L"error making gradient stop collection for second gradient in SV chooser", hr); ZeroMemory(&lprop, sizeof (D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES)); lprop.startPoint.x = size.width / 2; lprop.startPoint.y = 0; lprop.endPoint.x = size.width / 2; lprop.endPoint.y = size.height; 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 making gradient brush for second gradient in SV chooser", hr); // oh but wait we can't use FillRectangle() with an opacity mask // and we can't use FillGeometry() with both an opacity mask and a non-bitmap // layers it is! hr = rt->CreateLayer(&size, &layer); if (hr != S_OK) logHRESULT(L"error making layer for second gradient in SV chooser", hr); ZeroMemory(&layerparams, sizeof (D2D1_LAYER_PARAMETERS)); layerparams.contentBounds = rect; // TODO make sure these are right layerparams.geometricMask = NULL; layerparams.maskAntialiasMode = D2D1_ANTIALIAS_MODE_PER_PRIMITIVE; layerparams.maskTransform._11 = 1; layerparams.maskTransform._22 = 1; layerparams.opacity = c->a; // here's the other use of c->a to note layerparams.opacityBrush = opacity; layerparams.layerOptions = D2D1_LAYER_OPTIONS_NONE; rt->PushLayer(&layerparams, layer); rt->FillRectangle(&rect, brush); rt->PopLayer(); layer->Release(); brush->Release(); collection->Release(); opacity->Release(); // and now we just draw the marker ZeroMemory(&mparam, sizeof (D2D1_ELLIPSE)); mparam.point.x = c->s * size.width; mparam.point.y = (1 - c->v) * size.height; mparam.radiusX = 7; mparam.radiusY = 7; // TODO make the color contrast? mcolor.r = 1.0; mcolor.g = 1.0; mcolor.b = 1.0; mcolor.a = 1.0; bprop.opacity = 1.0; // the marker should always be opaque hr = rt->CreateSolidColorBrush(&mcolor, &bprop, &markerBrush); if (hr != S_OK) logHRESULT(L"error creating brush for SV chooser marker", hr); rt->DrawEllipse(&mparam, markerBrush, 2, NULL); markerBrush->Release(); }