static bool TryGetFillOpacityMaskParameters()

in winrt/lib/drawing/CanvasDrawingSession.cpp [1279:1331]


    static bool TryGetFillOpacityMaskParameters(ID2D1Brush* opacityBrush, ID2D1DeviceContext1* deviceContext, D2D1_RECT_F const& destRect, ID2D1Bitmap** opacityBitmap, D2D1_RECT_F* opacitySourceRect)
    {
        // Is this a bitmap brush?
        auto bitmapBrush = MaybeAs<ID2D1BitmapBrush1>(opacityBrush);

        if (!bitmapBrush)
            return false;

        bitmapBrush->GetBitmap(opacityBitmap);
        
        if (!*opacityBitmap)
            return false;

        // Make sure the brush transform contains only positive scaling and translation, as other
        // transforms cannot be represented in FillOpacityMask sourceRect/destRect format.
        D2D1::Matrix3x2F brushTransform;
        bitmapBrush->GetTransform(&brushTransform);

        if (brushTransform._11 <= 0 ||
            brushTransform._22 <= 0 ||
            brushTransform._12 != 0 ||
            brushTransform._21 != 0)
        {
            return false;
        }

        // Transform the dest rect by the inverse of the brush transform, yielding a FillOpacityMask source rect.
        if (!D2D1InvertMatrix(&brushTransform))
            return false;

        auto tl = D2D1_POINT_2F{ destRect.left,  destRect.top    } * brushTransform;
        auto br = D2D1_POINT_2F{ destRect.right, destRect.bottom } * brushTransform;

        // Can't use FillOpacityMask if the source rect goes outside the bounds of the bitmap.
        if (!ArePointsInsideBitmap(*opacityBitmap, tl, br, deviceContext->GetUnitMode()))
            return false;

        // FillOpacityMask always uses default alpha and interpolation mode.
        if (bitmapBrush->GetOpacity() != 1.0f)
            return false;

        if (bitmapBrush->GetInterpolationMode1() != D2D1_BITMAP_INTERPOLATION_MODE_LINEAR)
            return false;

        // FillOpacityMask requires that antialiasing be disabled.
        if (deviceContext->GetAntialiasMode() != D2D1_ANTIALIAS_MODE_ALIASED)
            return false;

        // Ok then! FillOpacityMask is a go.
        *opacitySourceRect = D2D1_RECT_F{ tl.x, tl.y, br.x, br.y };

        return true;
    }