[Fabric] Merge ISurfaceBrush and ICompositionDrawingSurface into a single object (#12097)
* [Fabric] Remove runtime classes in CompositionSwitcher * fix * Change files * Merge ISurfaceBrush and ICompositionDrawingSurface * Change files * desktop fix * format
This commit is contained in:
Родитель
f859b4ccfa
Коммит
ffeafc3f72
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"type": "prerelease",
|
||||
"comment": "[Fabric] Merge ISurfaceBrush and ICompositionDrawingSurface into a single object",
|
||||
"packageName": "react-native-windows",
|
||||
"email": "30809111+acoates-ms@users.noreply.github.com",
|
||||
"dependentChangeType": "patch"
|
||||
}
|
|
@ -25,7 +25,7 @@ namespace Microsoft.ReactNative.Composition
|
|||
static COMP_NAMESPACE.Visual InnerVisual(IVisual visual);
|
||||
static COMP_NAMESPACE.DropShadow InnerDropShadow(IDropShadow shadow);
|
||||
static COMP_NAMESPACE.CompositionBrush InnerBrush(IBrush brush);
|
||||
static COMP_NAMESPACE.ICompositionSurface InnerSurface(ICompositionDrawingSurface surface);
|
||||
static COMP_NAMESPACE.ICompositionSurface InnerSurface(IDrawingSurfaceBrush surface);
|
||||
}
|
||||
|
||||
} // namespace Microsoft.ReactNative.Composition
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace Microsoft.ReactNative.Composition
|
|||
|
||||
[webhosthidden]
|
||||
[experimental]
|
||||
interface ISurfaceBrush requires IBrush
|
||||
interface IDrawingSurfaceBrush requires IBrush
|
||||
{
|
||||
void HorizontalAlignmentRatio(Single value);
|
||||
void VerticalAlignmentRatio(Single value);
|
||||
|
@ -99,14 +99,6 @@ namespace Microsoft.ReactNative.Composition
|
|||
void updateColor(Windows.UI.Color color);
|
||||
}
|
||||
|
||||
[webhosthidden]
|
||||
[uuid("a74bfffc-7f2d-432f-8291-654782ab0d52")] // uuid needed for empty interfaces
|
||||
[version(0)]
|
||||
[experimental]
|
||||
interface ICompositionDrawingSurface
|
||||
{
|
||||
}
|
||||
|
||||
[webhosthidden]
|
||||
[experimental]
|
||||
interface ICaretVisual
|
||||
|
@ -130,10 +122,6 @@ namespace Microsoft.ReactNative.Composition
|
|||
[experimental]
|
||||
interface ICompositionContext
|
||||
{
|
||||
ICompositionDrawingSurface CreateDrawingSurface(Windows.Foundation.Size surfaceSize,
|
||||
Windows.Graphics.DirectX.DirectXPixelFormat pixelFormat,
|
||||
Windows.Graphics.DirectX.DirectXAlphaMode alphaMode);
|
||||
|
||||
ISpriteVisual CreateSpriteVisual();
|
||||
IScrollVisual CreateScrollerVisual();
|
||||
IActivityVisual CreateActivityVisual();
|
||||
|
@ -141,7 +129,9 @@ namespace Microsoft.ReactNative.Composition
|
|||
IFocusVisual CreateFocusVisual();
|
||||
IDropShadow CreateDropShadow();
|
||||
IBrush CreateColorBrush(Windows.UI.Color color);
|
||||
ISurfaceBrush CreateSurfaceBrush(ICompositionDrawingSurface surface);
|
||||
IDrawingSurfaceBrush CreateDrawingSurfaceBrush(Windows.Foundation.Size surfaceSize,
|
||||
Windows.Graphics.DirectX.DirectXPixelFormat pixelFormat,
|
||||
Windows.Graphics.DirectX.DirectXAlphaMode alphaMode);
|
||||
|
||||
// TODO Add and hook up to rootnode - to notify the tree
|
||||
// event Windows.Foundation.EventHandler<RenderingDeviceReplacedArgs> RenderingDeviceReplaced;
|
||||
|
|
|
@ -35,33 +35,6 @@ struct GeometrySource : public winrt::implements<
|
|||
winrt::com_ptr<ID2D1Geometry> m_geometry;
|
||||
};
|
||||
|
||||
struct CompositionDrawingSurface : public winrt::implements<
|
||||
CompositionDrawingSurface,
|
||||
winrt::Microsoft::ReactNative::Composition::ICompositionDrawingSurface,
|
||||
ICompositionDrawingSurfaceInterop,
|
||||
ICompositionDrawingSurfaceInner> {
|
||||
CompositionDrawingSurface(winrt::Windows::UI::Composition::CompositionDrawingSurface const &drawingSurface) {
|
||||
drawingSurface.as(m_drawingSurfaceInterop);
|
||||
}
|
||||
|
||||
HRESULT BeginDraw(ID2D1DeviceContext **deviceContextOut, POINT *offset) noexcept {
|
||||
return m_drawingSurfaceInterop->BeginDraw(nullptr, __uuidof(ID2D1DeviceContext), (void **)deviceContextOut, offset);
|
||||
}
|
||||
|
||||
HRESULT EndDraw() noexcept {
|
||||
return m_drawingSurfaceInterop->EndDraw();
|
||||
}
|
||||
|
||||
winrt::Windows::UI::Composition::ICompositionSurface Inner() const noexcept {
|
||||
winrt::Windows::UI::Composition::ICompositionSurface surface;
|
||||
m_drawingSurfaceInterop.as(surface);
|
||||
return surface;
|
||||
}
|
||||
|
||||
private:
|
||||
winrt::com_ptr<ABI::Windows::UI::Composition::ICompositionDrawingSurfaceInterop> m_drawingSurfaceInterop;
|
||||
};
|
||||
|
||||
struct CompDropShadow
|
||||
: public winrt::
|
||||
implements<CompDropShadow, winrt::Microsoft::ReactNative::Composition::IDropShadow, ICompositionDropShadow> {
|
||||
|
@ -103,17 +76,33 @@ struct CompBrush
|
|||
winrt::Windows::UI::Composition::CompositionBrush m_brush;
|
||||
};
|
||||
|
||||
struct CompSurfaceBrush : winrt::implements<
|
||||
CompSurfaceBrush,
|
||||
winrt::Microsoft::ReactNative::Composition::ISurfaceBrush,
|
||||
winrt::Microsoft::ReactNative::Composition::IBrush,
|
||||
ICompositionBrush> {
|
||||
CompSurfaceBrush(
|
||||
struct CompDrawingSurfaceBrush : public winrt::implements<
|
||||
CompDrawingSurfaceBrush,
|
||||
winrt::Microsoft::ReactNative::Composition::IDrawingSurfaceBrush,
|
||||
winrt::Microsoft::ReactNative::Composition::IBrush,
|
||||
Microsoft::ReactNative::Composition::ICompositionBrush,
|
||||
ICompositionDrawingSurfaceInterop,
|
||||
ICompositionDrawingSurfaceInner> {
|
||||
CompDrawingSurfaceBrush(
|
||||
const winrt::Windows::UI::Composition::Compositor &compositor,
|
||||
const winrt::Microsoft::ReactNative::Composition::ICompositionDrawingSurface &drawingSurfaceInterop)
|
||||
: m_brush(compositor.CreateSurfaceBrush(
|
||||
winrt::Microsoft::ReactNative::Composition::CompositionContextHelper::InnerSurface(
|
||||
drawingSurfaceInterop))) {}
|
||||
winrt::Windows::UI::Composition::CompositionDrawingSurface const &drawingSurface)
|
||||
: m_brush(compositor.CreateSurfaceBrush(drawingSurface)) {
|
||||
drawingSurface.as(m_drawingSurfaceInterop);
|
||||
}
|
||||
|
||||
HRESULT BeginDraw(ID2D1DeviceContext **deviceContextOut, POINT *offset) noexcept {
|
||||
return m_drawingSurfaceInterop->BeginDraw(nullptr, __uuidof(ID2D1DeviceContext), (void **)deviceContextOut, offset);
|
||||
}
|
||||
|
||||
HRESULT EndDraw() noexcept {
|
||||
return m_drawingSurfaceInterop->EndDraw();
|
||||
}
|
||||
|
||||
winrt::Windows::UI::Composition::ICompositionSurface Inner() const noexcept {
|
||||
winrt::Windows::UI::Composition::ICompositionSurface surface;
|
||||
m_drawingSurfaceInterop.as(surface);
|
||||
return surface;
|
||||
}
|
||||
|
||||
winrt::Windows::UI::Composition::CompositionBrush InnerBrush() const noexcept {
|
||||
return m_brush;
|
||||
|
@ -149,6 +138,7 @@ struct CompSurfaceBrush : winrt::implements<
|
|||
|
||||
private:
|
||||
winrt::Windows::UI::Composition::CompositionSurfaceBrush m_brush;
|
||||
winrt::com_ptr<ABI::Windows::UI::Composition::ICompositionDrawingSurfaceInterop> m_drawingSurfaceInterop;
|
||||
};
|
||||
|
||||
struct CompVisual : public winrt::implements<
|
||||
|
@ -990,14 +980,6 @@ struct CompContext : winrt::implements<
|
|||
return m_d2dDevice;
|
||||
}
|
||||
|
||||
winrt::Microsoft::ReactNative::Composition::ICompositionDrawingSurface CreateDrawingSurface(
|
||||
winrt::Windows::Foundation::Size surfaceSize,
|
||||
winrt::Windows::Graphics::DirectX::DirectXPixelFormat pixelFormat,
|
||||
winrt::Windows::Graphics::DirectX::DirectXAlphaMode alphaMode) noexcept {
|
||||
return winrt::make<Composition::CompositionDrawingSurface>(
|
||||
CompositionGraphicsDevice().CreateDrawingSurface(surfaceSize, pixelFormat, alphaMode));
|
||||
}
|
||||
|
||||
winrt::Microsoft::ReactNative::Composition::ISpriteVisual CreateSpriteVisual() noexcept {
|
||||
return winrt::make<Composition::CompSpriteVisual>(m_compositor.CreateSpriteVisual());
|
||||
}
|
||||
|
@ -1018,9 +1000,12 @@ struct CompContext : winrt::implements<
|
|||
return winrt::make<Composition::CompBrush>(m_compositor.CreateColorBrush(color));
|
||||
}
|
||||
|
||||
winrt::Microsoft::ReactNative::Composition::ISurfaceBrush CreateSurfaceBrush(
|
||||
const winrt::Microsoft::ReactNative::Composition::ICompositionDrawingSurface &surface) noexcept {
|
||||
return winrt::make<Composition::CompSurfaceBrush>(m_compositor, surface);
|
||||
winrt::Microsoft::ReactNative::Composition::IDrawingSurfaceBrush CreateDrawingSurfaceBrush(
|
||||
winrt::Windows::Foundation::Size surfaceSize,
|
||||
winrt::Windows::Graphics::DirectX::DirectXPixelFormat pixelFormat,
|
||||
winrt::Windows::Graphics::DirectX::DirectXAlphaMode alphaMode) noexcept {
|
||||
return winrt::make<Composition::CompDrawingSurfaceBrush>(
|
||||
m_compositor, CompositionGraphicsDevice().CreateDrawingSurface(surfaceSize, pixelFormat, alphaMode));
|
||||
}
|
||||
|
||||
winrt::Microsoft::ReactNative::Composition::ICaretVisual CreateCaretVisual() noexcept {
|
||||
|
@ -1102,7 +1087,7 @@ winrt::Windows::UI::Composition::CompositionBrush CompositionContextHelper::Inne
|
|||
}
|
||||
|
||||
winrt::Windows::UI::Composition::ICompositionSurface CompositionContextHelper::InnerSurface(
|
||||
ICompositionDrawingSurface surface) noexcept {
|
||||
IDrawingSurfaceBrush surface) noexcept {
|
||||
winrt::com_ptr<::Microsoft::ReactNative::Composition::ICompositionDrawingSurfaceInner> s;
|
||||
surface.as(s);
|
||||
return s ? s->Inner() : nullptr;
|
||||
|
|
|
@ -20,7 +20,7 @@ struct CompositionContextHelper : CompositionContextHelperT<CompositionContextHe
|
|||
static winrt::Windows::UI::Composition::Visual InnerVisual(IVisual visual) noexcept;
|
||||
static winrt::Windows::UI::Composition::DropShadow InnerDropShadow(IDropShadow shadow) noexcept;
|
||||
static winrt::Windows::UI::Composition::CompositionBrush InnerBrush(IBrush brush) noexcept;
|
||||
static winrt::Windows::UI::Composition::ICompositionSurface InnerSurface(ICompositionDrawingSurface surface) noexcept;
|
||||
static winrt::Windows::UI::Composition::ICompositionSurface InnerSurface(IDrawingSurfaceBrush surface) noexcept;
|
||||
};
|
||||
|
||||
} // namespace winrt::Microsoft::ReactNative::Composition::implementation
|
||||
|
|
|
@ -33,7 +33,7 @@ winrt::Windows::UI::Composition::CompositionBrush CompositionContextHelper::Inne
|
|||
}
|
||||
|
||||
winrt::Windows::UI::Composition::ICompositionSurface CompositionContextHelper::InnerSurface(
|
||||
ICompositionDrawingSurface) noexcept {
|
||||
IDrawingSurfaceBrush) noexcept {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -485,13 +485,13 @@ void SetBorderLayerPropertiesCommon(
|
|||
if ((textureRect.right - textureRect.left) <= 0 && (textureRect.bottom - textureRect.top) <= 0)
|
||||
return;
|
||||
|
||||
auto surface = compContext.CreateDrawingSurface(
|
||||
auto surface = compContext.CreateDrawingSurfaceBrush(
|
||||
{(textureRect.right - textureRect.left), (textureRect.bottom - textureRect.top)},
|
||||
winrt::Windows::Graphics::DirectX::DirectXPixelFormat::B8G8R8A8UIntNormalized,
|
||||
winrt::Windows::Graphics::DirectX::DirectXAlphaMode::Premultiplied);
|
||||
surface.as(borderTexture);
|
||||
|
||||
layer.Brush(compContext.CreateSurfaceBrush(surface));
|
||||
layer.Brush(surface);
|
||||
layer.Offset({anchorOffset.x, anchorOffset.y, 0}, {anchorPoint.x, anchorPoint.y, 0});
|
||||
layer.RelativeSizeWithOffset(size, relativeSizeAdjustment);
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <winrt/Windows.UI.Composition.h>
|
||||
#include <winrt/Windows.Web.Http.Headers.h>
|
||||
#include <winrt/Windows.Web.Http.h>
|
||||
#include "Composition/AutoDraw.h"
|
||||
#include "CompositionDynamicAutomationProvider.h"
|
||||
#include "CompositionHelpers.h"
|
||||
|
||||
|
@ -218,34 +219,32 @@ void ImageComponentView::ensureDrawingSurface() noexcept {
|
|||
drawingSurfaceSize = {drawingSurfaceSize.Width + bmpGrowth, drawingSurfaceSize.Height + bmpGrowth};
|
||||
}
|
||||
|
||||
m_drawingSurface = m_compContext.CreateDrawingSurface(
|
||||
m_drawingSurface = m_compContext.CreateDrawingSurfaceBrush(
|
||||
drawingSurfaceSize,
|
||||
winrt::Windows::Graphics::DirectX::DirectXPixelFormat::B8G8R8A8UIntNormalized,
|
||||
winrt::Windows::Graphics::DirectX::DirectXAlphaMode::Premultiplied);
|
||||
|
||||
DrawImage();
|
||||
|
||||
auto surfaceBrush = m_compContext.CreateSurfaceBrush(m_drawingSurface);
|
||||
|
||||
switch (imageProps->resizeMode) {
|
||||
case facebook::react::ImageResizeMode::Stretch:
|
||||
surfaceBrush.Stretch(winrt::Microsoft::ReactNative::Composition::CompositionStretch::Fill);
|
||||
m_drawingSurface.Stretch(winrt::Microsoft::ReactNative::Composition::CompositionStretch::Fill);
|
||||
break;
|
||||
case facebook::react::ImageResizeMode::Cover:
|
||||
surfaceBrush.Stretch(winrt::Microsoft::ReactNative::Composition::CompositionStretch::UniformToFill);
|
||||
m_drawingSurface.Stretch(winrt::Microsoft::ReactNative::Composition::CompositionStretch::UniformToFill);
|
||||
break;
|
||||
case facebook::react::ImageResizeMode::Contain:
|
||||
surfaceBrush.Stretch(winrt::Microsoft::ReactNative::Composition::CompositionStretch::Uniform);
|
||||
m_drawingSurface.Stretch(winrt::Microsoft::ReactNative::Composition::CompositionStretch::Uniform);
|
||||
break;
|
||||
case facebook::react::ImageResizeMode::Repeat:
|
||||
// TODO - set AlignmentRatio back to 0.5f when switching between resizeModes once we no longer recreate the
|
||||
// drawing surface on prop changes.
|
||||
surfaceBrush.HorizontalAlignmentRatio(0.0f);
|
||||
surfaceBrush.VerticalAlignmentRatio(0.0f);
|
||||
m_drawingSurface.HorizontalAlignmentRatio(0.0f);
|
||||
m_drawingSurface.VerticalAlignmentRatio(0.0f);
|
||||
// Repeat and Center use the same Stretch logic, so we can fallthrough here.
|
||||
[[fallthrough]];
|
||||
case facebook::react::ImageResizeMode::Center: {
|
||||
surfaceBrush.Stretch(
|
||||
m_drawingSurface.Stretch(
|
||||
(height < frame.height && width < frame.width)
|
||||
? winrt::Microsoft::ReactNative::Composition::CompositionStretch::None
|
||||
: winrt::Microsoft::ReactNative::Composition::CompositionStretch::Uniform);
|
||||
|
@ -255,7 +254,7 @@ void ImageComponentView::ensureDrawingSurface() noexcept {
|
|||
assert(false);
|
||||
}
|
||||
|
||||
m_visual.Brush(surfaceBrush);
|
||||
m_visual.Brush(m_drawingSurface);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -263,15 +262,12 @@ void ImageComponentView::DrawImage() noexcept {
|
|||
// Begin our update of the surface pixels. If this is our first update, we are required
|
||||
// to specify the entire surface, which nullptr is shorthand for (but, as it works out,
|
||||
// any time we make an update we touch the entire surface, so we always pass nullptr).
|
||||
winrt::com_ptr<ID2D1DeviceContext> d2dDeviceContext;
|
||||
POINT offset;
|
||||
|
||||
assert(m_context.UIDispatcher().HasThreadAccess());
|
||||
|
||||
winrt::com_ptr<Composition::ICompositionDrawingSurfaceInterop> drawingSurfaceInterop;
|
||||
m_drawingSurface.as(drawingSurfaceInterop);
|
||||
|
||||
if (CheckForDeviceRemoved(drawingSurfaceInterop->BeginDraw(d2dDeviceContext.put(), &offset))) {
|
||||
::Microsoft::ReactNative::Composition::AutoDrawDrawingSurface autoDraw(m_drawingSurface, &offset);
|
||||
if (auto d2dDeviceContext = autoDraw.GetRenderTarget()) {
|
||||
winrt::com_ptr<ID2D1Bitmap1> bitmap;
|
||||
winrt::check_hresult(d2dDeviceContext->CreateBitmapFromWicBitmap(m_wicbmp.get(), nullptr, bitmap.put()));
|
||||
|
||||
|
@ -355,10 +351,6 @@ void ImageComponentView::DrawImage() noexcept {
|
|||
// Restore old dpi setting
|
||||
d2dDeviceContext->SetDpi(oldDpiX, oldDpiY);
|
||||
}
|
||||
|
||||
// Our update is done. EndDraw never indicates rendering device removed, so any
|
||||
// failure here is unexpected and, therefore, fatal.
|
||||
winrt::check_hresult(drawingSurfaceInterop->EndDraw());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ struct ImageComponentView : CompositionBaseComponentView {
|
|||
|
||||
winrt::Microsoft::ReactNative::Composition::ISpriteVisual m_visual{nullptr};
|
||||
winrt::Microsoft::ReactNative::ReactContext m_context;
|
||||
winrt::Microsoft::ReactNative::Composition::ICompositionDrawingSurface m_drawingSurface;
|
||||
winrt::Microsoft::ReactNative::Composition::IDrawingSurfaceBrush m_drawingSurface;
|
||||
winrt::com_ptr<IWICBitmap> m_wicbmp;
|
||||
std::shared_ptr<WindowsImageResponseObserver> m_imageResponseObserver;
|
||||
facebook::react::ImageShadowNode::ConcreteState::Shared m_state;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <react/renderer/components/text/ParagraphState.h>
|
||||
#include <unicode.h>
|
||||
#include <winrt/Microsoft.ReactNative.Composition.h>
|
||||
#include "Composition/AutoDraw.h"
|
||||
#include "CompositionDynamicAutomationProvider.h"
|
||||
#include "CompositionHelpers.h"
|
||||
|
||||
|
@ -229,7 +230,7 @@ void ParagraphComponentView::updateVisualBrush() noexcept {
|
|||
winrt::Windows::Foundation::Size surfaceSize = {
|
||||
m_layoutMetrics.frame.size.width * m_layoutMetrics.pointScaleFactor,
|
||||
m_layoutMetrics.frame.size.height * m_layoutMetrics.pointScaleFactor};
|
||||
m_drawingSurface = m_compContext.CreateDrawingSurface(
|
||||
m_drawingSurface = m_compContext.CreateDrawingSurfaceBrush(
|
||||
surfaceSize,
|
||||
winrt::Windows::Graphics::DirectX::DirectXPixelFormat::B8G8R8A8UIntNormalized,
|
||||
winrt::Windows::Graphics::DirectX::DirectXAlphaMode::Premultiplied);
|
||||
|
@ -237,8 +238,6 @@ void ParagraphComponentView::updateVisualBrush() noexcept {
|
|||
|
||||
DrawText();
|
||||
|
||||
auto surfaceBrush = m_compContext.CreateSurfaceBrush(m_drawingSurface);
|
||||
|
||||
// The surfaceBrush's size is based on the size the text takes up, which maybe smaller than the total visual
|
||||
// So we need to align the brush within the visual to match the text alignment.
|
||||
const auto ¶graphProps = *std::static_pointer_cast<const facebook::react::ParagraphProps>(m_props);
|
||||
|
@ -268,10 +267,12 @@ void ParagraphComponentView::updateVisualBrush() noexcept {
|
|||
}
|
||||
*/
|
||||
// TODO Using brush alignment to align the text makes it blurry...
|
||||
surfaceBrush.HorizontalAlignmentRatio(horizAlignment);
|
||||
surfaceBrush.VerticalAlignmentRatio(0.f);
|
||||
surfaceBrush.Stretch(winrt::Microsoft::ReactNative::Composition::CompositionStretch::None);
|
||||
m_visual.Brush(surfaceBrush);
|
||||
if (m_drawingSurface) {
|
||||
m_drawingSurface.HorizontalAlignmentRatio(horizAlignment);
|
||||
m_drawingSurface.VerticalAlignmentRatio(0.f);
|
||||
m_drawingSurface.Stretch(winrt::Microsoft::ReactNative::Composition::CompositionStretch::None);
|
||||
}
|
||||
m_visual.Brush(m_drawingSurface);
|
||||
}
|
||||
|
||||
if (m_requireRedraw) {
|
||||
|
@ -289,189 +290,181 @@ void ParagraphComponentView::DrawText() noexcept {
|
|||
return;
|
||||
}
|
||||
|
||||
// Begin our update of the surface pixels. If this is our first update, we are required
|
||||
// to specify the entire surface, which nullptr is shorthand for (but, as it works out,
|
||||
// any time we make an update we touch the entire surface, so we always pass nullptr).
|
||||
winrt::com_ptr<ID2D1DeviceContext> d2dDeviceContext;
|
||||
POINT offset;
|
||||
{
|
||||
::Microsoft::ReactNative::Composition::AutoDrawDrawingSurface autoDraw(m_drawingSurface, &offset);
|
||||
if (auto d2dDeviceContext = autoDraw.GetRenderTarget()) {
|
||||
d2dDeviceContext->Clear(
|
||||
m_props->backgroundColor ? m_props->backgroundColor.AsD2DColor() : D2D1::ColorF(D2D1::ColorF::Black, 0.0f));
|
||||
assert(d2dDeviceContext->GetUnitMode() == D2D1_UNIT_MODE_DIPS);
|
||||
const auto dpi = m_layoutMetrics.pointScaleFactor * 96.0f;
|
||||
float oldDpiX, oldDpiY;
|
||||
d2dDeviceContext->GetDpi(&oldDpiX, &oldDpiY);
|
||||
d2dDeviceContext->SetDpi(dpi, dpi);
|
||||
|
||||
winrt::com_ptr<Composition::ICompositionDrawingSurfaceInterop> drawingSurfaceInterop;
|
||||
m_drawingSurface.as(drawingSurfaceInterop);
|
||||
float offsetX = static_cast<float>(offset.x / m_layoutMetrics.pointScaleFactor);
|
||||
float offsetY = static_cast<float>(offset.y / m_layoutMetrics.pointScaleFactor);
|
||||
|
||||
if (CheckForDeviceRemoved(drawingSurfaceInterop->BeginDraw(d2dDeviceContext.put(), &offset))) {
|
||||
d2dDeviceContext->Clear(
|
||||
m_props->backgroundColor ? m_props->backgroundColor.AsD2DColor() : D2D1::ColorF(D2D1::ColorF::Black, 0.0f));
|
||||
assert(d2dDeviceContext->GetUnitMode() == D2D1_UNIT_MODE_DIPS);
|
||||
const auto dpi = m_layoutMetrics.pointScaleFactor * 96.0f;
|
||||
float oldDpiX, oldDpiY;
|
||||
d2dDeviceContext->GetDpi(&oldDpiX, &oldDpiY);
|
||||
d2dDeviceContext->SetDpi(dpi, dpi);
|
||||
const auto ¶graphProps = *std::static_pointer_cast<const facebook::react::ParagraphProps>(m_props);
|
||||
|
||||
float offsetX = static_cast<float>(offset.x / m_layoutMetrics.pointScaleFactor);
|
||||
float offsetY = static_cast<float>(offset.y / m_layoutMetrics.pointScaleFactor);
|
||||
|
||||
const auto ¶graphProps = *std::static_pointer_cast<const facebook::react::ParagraphProps>(m_props);
|
||||
|
||||
// Create a solid color brush for the text. A more sophisticated application might want
|
||||
// to cache and reuse a brush across all text elements instead, taking care to recreate
|
||||
// it in the event of device removed.
|
||||
winrt::com_ptr<ID2D1SolidColorBrush> brush;
|
||||
if (paragraphProps.textAttributes.foregroundColor) {
|
||||
auto color = paragraphProps.textAttributes.foregroundColor.AsD2DColor();
|
||||
winrt::check_hresult(d2dDeviceContext->CreateSolidColorBrush(color, brush.put()));
|
||||
} else {
|
||||
winrt::check_hresult(
|
||||
d2dDeviceContext->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black, 1.0f), brush.put()));
|
||||
}
|
||||
|
||||
if (paragraphProps.textAttributes.textDecorationLineType) {
|
||||
DWRITE_TEXT_RANGE range = {0, std::numeric_limits<uint32_t>::max()};
|
||||
if (*(paragraphProps.textAttributes.textDecorationLineType) ==
|
||||
facebook::react::TextDecorationLineType::Underline ||
|
||||
*(paragraphProps.textAttributes.textDecorationLineType) ==
|
||||
facebook::react::TextDecorationLineType::UnderlineStrikethrough) {
|
||||
m_textLayout->SetUnderline(true, range);
|
||||
// Create a solid color brush for the text. A more sophisticated application might want
|
||||
// to cache and reuse a brush across all text elements instead, taking care to recreate
|
||||
// it in the event of device removed.
|
||||
winrt::com_ptr<ID2D1SolidColorBrush> brush;
|
||||
if (paragraphProps.textAttributes.foregroundColor) {
|
||||
auto color = paragraphProps.textAttributes.foregroundColor.AsD2DColor();
|
||||
winrt::check_hresult(d2dDeviceContext->CreateSolidColorBrush(color, brush.put()));
|
||||
} else {
|
||||
m_textLayout->SetUnderline(false, range);
|
||||
winrt::check_hresult(
|
||||
d2dDeviceContext->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black, 1.0f), brush.put()));
|
||||
}
|
||||
}
|
||||
|
||||
if (paragraphProps.textAttributes.textDecorationLineType) {
|
||||
DWRITE_TEXT_RANGE range = {0, std::numeric_limits<uint32_t>::max()};
|
||||
if (*(paragraphProps.textAttributes.textDecorationLineType) ==
|
||||
facebook::react::TextDecorationLineType::Strikethrough ||
|
||||
*(paragraphProps.textAttributes.textDecorationLineType) ==
|
||||
facebook::react::TextDecorationLineType::UnderlineStrikethrough) {
|
||||
m_textLayout->SetStrikethrough(true, range);
|
||||
} else {
|
||||
m_textLayout->SetStrikethrough(false, range);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isnan(paragraphProps.opacity)) {
|
||||
m_visual.Opacity(paragraphProps.opacity);
|
||||
}
|
||||
|
||||
// Create color effects for individual text fragments.
|
||||
unsigned int position = 0;
|
||||
unsigned int length = 0;
|
||||
for (auto fragment : m_attributedStringBox.getValue().getFragments()) {
|
||||
length = static_cast<UINT32>(fragment.string.length());
|
||||
DWRITE_TEXT_RANGE range = {position, length};
|
||||
if (fragment.textAttributes.foregroundColor &&
|
||||
(fragment.textAttributes.foregroundColor != paragraphProps.textAttributes.foregroundColor) ||
|
||||
!isnan(fragment.textAttributes.opacity)) {
|
||||
winrt::com_ptr<ID2D1SolidColorBrush> fragmentBrush;
|
||||
if (fragment.textAttributes.foregroundColor) {
|
||||
auto color = fragment.textAttributes.foregroundColor.AsD2DColor();
|
||||
winrt::check_hresult(d2dDeviceContext->CreateSolidColorBrush(color, fragmentBrush.put()));
|
||||
if (paragraphProps.textAttributes.textDecorationLineType) {
|
||||
DWRITE_TEXT_RANGE range = {0, std::numeric_limits<uint32_t>::max()};
|
||||
if (*(paragraphProps.textAttributes.textDecorationLineType) ==
|
||||
facebook::react::TextDecorationLineType::Underline ||
|
||||
*(paragraphProps.textAttributes.textDecorationLineType) ==
|
||||
facebook::react::TextDecorationLineType::UnderlineStrikethrough) {
|
||||
m_textLayout->SetUnderline(true, range);
|
||||
} else {
|
||||
winrt::check_hresult(
|
||||
d2dDeviceContext->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black, 1.0f), fragmentBrush.put()));
|
||||
}
|
||||
|
||||
if (fragment.textAttributes.textDecorationLineType) {
|
||||
if (*(fragment.textAttributes.textDecorationLineType) == facebook::react::TextDecorationLineType::Underline ||
|
||||
*(fragment.textAttributes.textDecorationLineType) ==
|
||||
facebook::react::TextDecorationLineType::UnderlineStrikethrough) {
|
||||
m_textLayout->SetUnderline(true, range);
|
||||
} else {
|
||||
m_textLayout->SetUnderline(false, range);
|
||||
}
|
||||
}
|
||||
|
||||
if (fragment.textAttributes.textDecorationLineType) {
|
||||
if (*(fragment.textAttributes.textDecorationLineType) ==
|
||||
facebook::react::TextDecorationLineType::Strikethrough ||
|
||||
*(fragment.textAttributes.textDecorationLineType) ==
|
||||
facebook::react::TextDecorationLineType::UnderlineStrikethrough) {
|
||||
m_textLayout->SetStrikethrough(true, range);
|
||||
} else {
|
||||
m_textLayout->SetStrikethrough(false, range);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isnan(fragment.textAttributes.opacity)) {
|
||||
fragmentBrush->SetOpacity(fragment.textAttributes.opacity);
|
||||
}
|
||||
m_textLayout->SetDrawingEffect(fragmentBrush.get(), range);
|
||||
|
||||
// DWrite doesn't handle background highlight colors, so we manually draw the background color for ranges
|
||||
if (facebook::react::isColorMeaningful(fragment.textAttributes.backgroundColor)) {
|
||||
UINT32 actualHitTestCount = 0;
|
||||
if (range.length > 0) {
|
||||
m_textLayout->HitTestTextRange(
|
||||
range.startPosition,
|
||||
range.length,
|
||||
0, // x
|
||||
0, // y
|
||||
NULL,
|
||||
0, // metrics count
|
||||
&actualHitTestCount);
|
||||
}
|
||||
|
||||
// Allocate enough room to return all hit-test metrics.
|
||||
std::vector<DWRITE_HIT_TEST_METRICS> hitTestMetrics(actualHitTestCount);
|
||||
if (range.length > 0) {
|
||||
m_textLayout->HitTestTextRange(
|
||||
range.startPosition,
|
||||
range.length,
|
||||
0, // x
|
||||
0, // y
|
||||
&hitTestMetrics[0],
|
||||
static_cast<UINT32>(hitTestMetrics.size()),
|
||||
&actualHitTestCount);
|
||||
}
|
||||
|
||||
// Draw the selection ranges behind the text.
|
||||
if (actualHitTestCount > 0) {
|
||||
// Note that an ideal layout will return fractional values,
|
||||
// so you may see slivers between the selection ranges due
|
||||
// to the per-primitive anti-aliasing of the edges unless
|
||||
// it is disabled (better for performance anyway).
|
||||
auto oldAliasMode = d2dDeviceContext->GetAntialiasMode();
|
||||
d2dDeviceContext->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
|
||||
|
||||
winrt::com_ptr<ID2D1SolidColorBrush> textHighlightBrush;
|
||||
winrt::check_hresult(d2dDeviceContext->CreateSolidColorBrush(
|
||||
fragment.textAttributes.backgroundColor.AsD2DColor(), textHighlightBrush.put()));
|
||||
|
||||
for (size_t i = 0; i < actualHitTestCount; ++i) {
|
||||
const DWRITE_HIT_TEST_METRICS &htm = hitTestMetrics[i];
|
||||
|
||||
const D2D1_RECT_F rect = {
|
||||
std::round(htm.left + offsetX),
|
||||
std::round(htm.top + offsetY),
|
||||
std::round(htm.left + htm.width + offsetX),
|
||||
std::round(htm.top + htm.height + offsetY)};
|
||||
|
||||
d2dDeviceContext->FillRectangle(rect, textHighlightBrush.get());
|
||||
}
|
||||
d2dDeviceContext->SetAntialiasMode(oldAliasMode);
|
||||
}
|
||||
m_textLayout->SetUnderline(false, range);
|
||||
}
|
||||
}
|
||||
|
||||
position += length;
|
||||
if (paragraphProps.textAttributes.textDecorationLineType) {
|
||||
DWRITE_TEXT_RANGE range = {0, std::numeric_limits<uint32_t>::max()};
|
||||
if (*(paragraphProps.textAttributes.textDecorationLineType) ==
|
||||
facebook::react::TextDecorationLineType::Strikethrough ||
|
||||
*(paragraphProps.textAttributes.textDecorationLineType) ==
|
||||
facebook::react::TextDecorationLineType::UnderlineStrikethrough) {
|
||||
m_textLayout->SetStrikethrough(true, range);
|
||||
} else {
|
||||
m_textLayout->SetStrikethrough(false, range);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isnan(paragraphProps.opacity)) {
|
||||
m_visual.Opacity(paragraphProps.opacity);
|
||||
}
|
||||
|
||||
// Create color effects for individual text fragments.
|
||||
unsigned int position = 0;
|
||||
unsigned int length = 0;
|
||||
for (auto fragment : m_attributedStringBox.getValue().getFragments()) {
|
||||
length = static_cast<UINT32>(fragment.string.length());
|
||||
DWRITE_TEXT_RANGE range = {position, length};
|
||||
if (fragment.textAttributes.foregroundColor &&
|
||||
(fragment.textAttributes.foregroundColor != paragraphProps.textAttributes.foregroundColor) ||
|
||||
!isnan(fragment.textAttributes.opacity)) {
|
||||
winrt::com_ptr<ID2D1SolidColorBrush> fragmentBrush;
|
||||
if (fragment.textAttributes.foregroundColor) {
|
||||
auto color = fragment.textAttributes.foregroundColor.AsD2DColor();
|
||||
winrt::check_hresult(d2dDeviceContext->CreateSolidColorBrush(color, fragmentBrush.put()));
|
||||
} else {
|
||||
winrt::check_hresult(
|
||||
d2dDeviceContext->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black, 1.0f), fragmentBrush.put()));
|
||||
}
|
||||
|
||||
if (fragment.textAttributes.textDecorationLineType) {
|
||||
if (*(fragment.textAttributes.textDecorationLineType) ==
|
||||
facebook::react::TextDecorationLineType::Underline ||
|
||||
*(fragment.textAttributes.textDecorationLineType) ==
|
||||
facebook::react::TextDecorationLineType::UnderlineStrikethrough) {
|
||||
m_textLayout->SetUnderline(true, range);
|
||||
} else {
|
||||
m_textLayout->SetUnderline(false, range);
|
||||
}
|
||||
}
|
||||
|
||||
if (fragment.textAttributes.textDecorationLineType) {
|
||||
if (*(fragment.textAttributes.textDecorationLineType) ==
|
||||
facebook::react::TextDecorationLineType::Strikethrough ||
|
||||
*(fragment.textAttributes.textDecorationLineType) ==
|
||||
facebook::react::TextDecorationLineType::UnderlineStrikethrough) {
|
||||
m_textLayout->SetStrikethrough(true, range);
|
||||
} else {
|
||||
m_textLayout->SetStrikethrough(false, range);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isnan(fragment.textAttributes.opacity)) {
|
||||
fragmentBrush->SetOpacity(fragment.textAttributes.opacity);
|
||||
}
|
||||
m_textLayout->SetDrawingEffect(fragmentBrush.get(), range);
|
||||
|
||||
// DWrite doesn't handle background highlight colors, so we manually draw the background color for ranges
|
||||
if (facebook::react::isColorMeaningful(fragment.textAttributes.backgroundColor)) {
|
||||
UINT32 actualHitTestCount = 0;
|
||||
if (range.length > 0) {
|
||||
m_textLayout->HitTestTextRange(
|
||||
range.startPosition,
|
||||
range.length,
|
||||
0, // x
|
||||
0, // y
|
||||
NULL,
|
||||
0, // metrics count
|
||||
&actualHitTestCount);
|
||||
}
|
||||
|
||||
// Allocate enough room to return all hit-test metrics.
|
||||
std::vector<DWRITE_HIT_TEST_METRICS> hitTestMetrics(actualHitTestCount);
|
||||
if (range.length > 0) {
|
||||
m_textLayout->HitTestTextRange(
|
||||
range.startPosition,
|
||||
range.length,
|
||||
0, // x
|
||||
0, // y
|
||||
&hitTestMetrics[0],
|
||||
static_cast<UINT32>(hitTestMetrics.size()),
|
||||
&actualHitTestCount);
|
||||
}
|
||||
|
||||
// Draw the selection ranges behind the text.
|
||||
if (actualHitTestCount > 0) {
|
||||
// Note that an ideal layout will return fractional values,
|
||||
// so you may see slivers between the selection ranges due
|
||||
// to the per-primitive anti-aliasing of the edges unless
|
||||
// it is disabled (better for performance anyway).
|
||||
auto oldAliasMode = d2dDeviceContext->GetAntialiasMode();
|
||||
d2dDeviceContext->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
|
||||
|
||||
winrt::com_ptr<ID2D1SolidColorBrush> textHighlightBrush;
|
||||
winrt::check_hresult(d2dDeviceContext->CreateSolidColorBrush(
|
||||
fragment.textAttributes.backgroundColor.AsD2DColor(), textHighlightBrush.put()));
|
||||
|
||||
for (size_t i = 0; i < actualHitTestCount; ++i) {
|
||||
const DWRITE_HIT_TEST_METRICS &htm = hitTestMetrics[i];
|
||||
|
||||
const D2D1_RECT_F rect = {
|
||||
std::round(htm.left + offsetX),
|
||||
std::round(htm.top + offsetY),
|
||||
std::round(htm.left + htm.width + offsetX),
|
||||
std::round(htm.top + htm.height + offsetY)};
|
||||
|
||||
d2dDeviceContext->FillRectangle(rect, textHighlightBrush.get());
|
||||
}
|
||||
d2dDeviceContext->SetAntialiasMode(oldAliasMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
position += length;
|
||||
}
|
||||
|
||||
// Draw the line of text at the specified offset, which corresponds to the top-left
|
||||
// corner of our drawing surface. Notice we don't call BeginDraw on the D2D device
|
||||
// context; this has already been done for us by the composition API.
|
||||
d2dDeviceContext->DrawTextLayout(
|
||||
D2D1::Point2F(
|
||||
static_cast<FLOAT>((offset.x + m_layoutMetrics.contentInsets.left) / m_layoutMetrics.pointScaleFactor),
|
||||
static_cast<FLOAT>((offset.y + m_layoutMetrics.contentInsets.top) / m_layoutMetrics.pointScaleFactor)),
|
||||
m_textLayout.get(),
|
||||
brush.get(),
|
||||
D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT);
|
||||
|
||||
// restore dpi to old state
|
||||
d2dDeviceContext->SetDpi(oldDpiX, oldDpiY);
|
||||
}
|
||||
|
||||
// Draw the line of text at the specified offset, which corresponds to the top-left
|
||||
// corner of our drawing surface. Notice we don't call BeginDraw on the D2D device
|
||||
// context; this has already been done for us by the composition API.
|
||||
d2dDeviceContext->DrawTextLayout(
|
||||
D2D1::Point2F(
|
||||
static_cast<FLOAT>((offset.x + m_layoutMetrics.contentInsets.left) / m_layoutMetrics.pointScaleFactor),
|
||||
static_cast<FLOAT>((offset.y + m_layoutMetrics.contentInsets.top) / m_layoutMetrics.pointScaleFactor)),
|
||||
m_textLayout.get(),
|
||||
brush.get(),
|
||||
D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT);
|
||||
|
||||
// restore dpi to old state
|
||||
d2dDeviceContext->SetDpi(oldDpiX, oldDpiY);
|
||||
|
||||
// Our update is done. EndDraw never indicates rendering device removed, so any
|
||||
// failure here is unexpected and, therefore, fatal.
|
||||
winrt::check_hresult(drawingSurfaceInterop->EndDraw());
|
||||
m_requireRedraw = false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ struct ParagraphComponentView : CompositionBaseComponentView {
|
|||
facebook::react::ParagraphAttributes m_paragraphAttributes;
|
||||
|
||||
bool m_requireRedraw{true};
|
||||
winrt::Microsoft::ReactNative::Composition::ICompositionDrawingSurface m_drawingSurface;
|
||||
winrt::Microsoft::ReactNative::Composition::IDrawingSurfaceBrush m_drawingSurface;
|
||||
};
|
||||
|
||||
} // namespace Microsoft::ReactNative
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "SwitchComponentView.h"
|
||||
#include "Composition/AutoDraw.h"
|
||||
#include "CompositionDynamicAutomationProvider.h"
|
||||
|
||||
namespace Microsoft::ReactNative {
|
||||
|
@ -92,16 +93,10 @@ void SwitchComponentView::finalizeUpdates(RNComponentViewUpdateMask updateMask)
|
|||
}
|
||||
|
||||
void SwitchComponentView::Draw() noexcept {
|
||||
// Begin our update of the surface pixels. If this is our first update, we are required
|
||||
// to specify the entire surface, which nullptr is shorthand for (but, as it works out,
|
||||
// any time we make an update we touch the entire surface, so we always pass nullptr).
|
||||
winrt::com_ptr<ID2D1DeviceContext> d2dDeviceContext;
|
||||
POINT offset;
|
||||
|
||||
winrt::com_ptr<Composition::ICompositionDrawingSurfaceInterop> drawingSurfaceInterop;
|
||||
m_drawingSurface.as(drawingSurfaceInterop);
|
||||
|
||||
if (CheckForDeviceRemoved(drawingSurfaceInterop->BeginDraw(d2dDeviceContext.put(), &offset))) {
|
||||
::Microsoft::ReactNative::Composition::AutoDrawDrawingSurface autoDraw(m_drawingSurface, &offset);
|
||||
if (auto d2dDeviceContext = autoDraw.GetRenderTarget()) {
|
||||
const auto switchProps = std::static_pointer_cast<const facebook::react::SwitchProps>(m_props);
|
||||
|
||||
d2dDeviceContext->Clear(D2D1::ColorF(D2D1::ColorF::Black, 0.0f));
|
||||
|
@ -181,10 +176,6 @@ void SwitchComponentView::Draw() noexcept {
|
|||
|
||||
// Restore old dpi setting
|
||||
d2dDeviceContext->SetDpi(oldDpiX, oldDpiY);
|
||||
|
||||
// Our update is done. EndDraw never indicates rendering device removed, so any
|
||||
// failure here is unexpected and, therefore, fatal.
|
||||
winrt::check_hresult(drawingSurfaceInterop->EndDraw());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -206,16 +197,14 @@ void SwitchComponentView::ensureDrawingSurface() noexcept {
|
|||
winrt::Windows::Foundation::Size surfaceSize = {
|
||||
m_layoutMetrics.frame.size.width * m_layoutMetrics.pointScaleFactor,
|
||||
m_layoutMetrics.frame.size.height * m_layoutMetrics.pointScaleFactor};
|
||||
m_drawingSurface = m_compContext.CreateDrawingSurface(
|
||||
m_drawingSurface = m_compContext.CreateDrawingSurfaceBrush(
|
||||
surfaceSize,
|
||||
winrt::Windows::Graphics::DirectX::DirectXPixelFormat::B8G8R8A8UIntNormalized,
|
||||
winrt::Windows::Graphics::DirectX::DirectXAlphaMode::Premultiplied);
|
||||
|
||||
Draw();
|
||||
|
||||
auto surfaceBrush = m_compContext.CreateSurfaceBrush(m_drawingSurface);
|
||||
|
||||
m_visual.Brush(surfaceBrush);
|
||||
m_visual.Brush(m_drawingSurface);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ struct SwitchComponentView : CompositionBaseComponentView {
|
|||
winrt::Microsoft::ReactNative::Composition::ISpriteVisual m_visual{nullptr};
|
||||
winrt::Microsoft::ReactNative::ReactContext m_context;
|
||||
facebook::react::SharedViewProps m_props;
|
||||
winrt::Microsoft::ReactNative::Composition::ICompositionDrawingSurface m_drawingSurface;
|
||||
winrt::Microsoft::ReactNative::Composition::IDrawingSurfaceBrush m_drawingSurface;
|
||||
};
|
||||
|
||||
} // namespace Microsoft::ReactNative
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <winrt/Windows.UI.h>
|
||||
#include "../CompositionHelpers.h"
|
||||
#include "../RootComponentView.h"
|
||||
#include "Composition/AutoDraw.h"
|
||||
#include "WindowsTextInputShadowNode.h"
|
||||
#include "WindowsTextInputState.h"
|
||||
#include "guid/msoGuid.h"
|
||||
|
@ -954,7 +955,7 @@ void WindowsTextInputComponentView::ensureDrawingSurface() noexcept {
|
|||
assert(m_context.UIDispatcher().HasThreadAccess());
|
||||
|
||||
if (!m_drawingSurface) {
|
||||
m_drawingSurface = m_compContext.CreateDrawingSurface(
|
||||
m_drawingSurface = m_compContext.CreateDrawingSurfaceBrush(
|
||||
{static_cast<float>(m_imgWidth), static_cast<float>(m_imgHeight)},
|
||||
winrt::Windows::Graphics::DirectX::DirectXPixelFormat::B8G8R8A8UIntNormalized,
|
||||
winrt::Windows::Graphics::DirectX::DirectXAlphaMode::Premultiplied);
|
||||
|
@ -968,11 +969,10 @@ void WindowsTextInputComponentView::ensureDrawingSurface() noexcept {
|
|||
|
||||
DrawText();
|
||||
|
||||
auto surfaceBrush = m_compContext.CreateSurfaceBrush(m_drawingSurface);
|
||||
surfaceBrush.HorizontalAlignmentRatio(0.f);
|
||||
surfaceBrush.VerticalAlignmentRatio(0.f);
|
||||
surfaceBrush.Stretch(winrt::Microsoft::ReactNative::Composition::CompositionStretch::None);
|
||||
m_visual.Brush(surfaceBrush);
|
||||
m_drawingSurface.HorizontalAlignmentRatio(0.f);
|
||||
m_drawingSurface.VerticalAlignmentRatio(0.f);
|
||||
m_drawingSurface.Stretch(winrt::Microsoft::ReactNative::Composition::CompositionStretch::None);
|
||||
m_visual.Brush(m_drawingSurface);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1015,88 +1015,79 @@ void WindowsTextInputComponentView::DrawText() noexcept {
|
|||
if (!m_drawingSurface || isZeroSized)
|
||||
return;
|
||||
|
||||
// Begin our update of the surface pixels. If this is our first update, we are required
|
||||
// to specify the entire surface, which nullptr is shorthand for (but, as it works out,
|
||||
// any time we make an update we touch the entire surface, so we always pass nullptr).
|
||||
winrt::com_ptr<ID2D1DeviceContext> d2dDeviceContext;
|
||||
POINT offset;
|
||||
|
||||
assert(m_context.UIDispatcher().HasThreadAccess());
|
||||
|
||||
winrt::com_ptr<Composition::ICompositionDrawingSurfaceInterop> drawingSurfaceInterop;
|
||||
m_drawingSurface.as(drawingSurfaceInterop);
|
||||
|
||||
m_drawing = true;
|
||||
if (CheckForDeviceRemoved(drawingSurfaceInterop->BeginDraw(d2dDeviceContext.put(), &offset))) {
|
||||
d2dDeviceContext->Clear(D2D1::ColorF(D2D1::ColorF::Black, 0.0f));
|
||||
assert(d2dDeviceContext->GetUnitMode() == D2D1_UNIT_MODE_DIPS);
|
||||
const auto dpi = m_layoutMetrics.pointScaleFactor * 96.0f;
|
||||
float oldDpiX, oldDpiY;
|
||||
d2dDeviceContext->GetDpi(&oldDpiX, &oldDpiY);
|
||||
d2dDeviceContext->SetDpi(dpi, dpi);
|
||||
{
|
||||
::Microsoft::ReactNative::Composition::AutoDrawDrawingSurface autoDraw(m_drawingSurface, &offset);
|
||||
if (auto d2dDeviceContext = autoDraw.GetRenderTarget()) {
|
||||
d2dDeviceContext->Clear(D2D1::ColorF(D2D1::ColorF::Black, 0.0f));
|
||||
assert(d2dDeviceContext->GetUnitMode() == D2D1_UNIT_MODE_DIPS);
|
||||
const auto dpi = m_layoutMetrics.pointScaleFactor * 96.0f;
|
||||
float oldDpiX, oldDpiY;
|
||||
d2dDeviceContext->GetDpi(&oldDpiX, &oldDpiY);
|
||||
d2dDeviceContext->SetDpi(dpi, dpi);
|
||||
|
||||
RECTL rc{
|
||||
static_cast<LONG>(offset.x),
|
||||
static_cast<LONG>(offset.y),
|
||||
static_cast<LONG>(offset.x) + static_cast<LONG>(m_imgWidth),
|
||||
static_cast<LONG>(offset.y) + static_cast<LONG>(m_imgHeight)};
|
||||
RECTL rc{
|
||||
static_cast<LONG>(offset.x),
|
||||
static_cast<LONG>(offset.y),
|
||||
static_cast<LONG>(offset.x) + static_cast<LONG>(m_imgWidth),
|
||||
static_cast<LONG>(offset.y) + static_cast<LONG>(m_imgHeight)};
|
||||
|
||||
RECT rcClient{
|
||||
static_cast<LONG>(offset.x),
|
||||
static_cast<LONG>(offset.y),
|
||||
static_cast<LONG>(offset.x) + static_cast<LONG>(m_imgWidth),
|
||||
static_cast<LONG>(offset.y) + static_cast<LONG>(m_imgHeight)};
|
||||
RECT rcClient{
|
||||
static_cast<LONG>(offset.x),
|
||||
static_cast<LONG>(offset.y),
|
||||
static_cast<LONG>(offset.x) + static_cast<LONG>(m_imgWidth),
|
||||
static_cast<LONG>(offset.y) + static_cast<LONG>(m_imgHeight)};
|
||||
|
||||
winrt::check_hresult(m_textServices->OnTxInPlaceActivate(&rcClient));
|
||||
winrt::check_hresult(m_textServices->OnTxInPlaceActivate(&rcClient));
|
||||
|
||||
if (facebook::react::isColorMeaningful(m_props->backgroundColor)) {
|
||||
auto backgroundColor = m_props->backgroundColor.AsD2DColor();
|
||||
winrt::com_ptr<ID2D1SolidColorBrush> backgroundBrush;
|
||||
winrt::check_hresult(d2dDeviceContext->CreateSolidColorBrush(backgroundColor, backgroundBrush.put()));
|
||||
const D2D1_RECT_F fillRect = {
|
||||
static_cast<float>(rcClient.left) / m_layoutMetrics.pointScaleFactor,
|
||||
static_cast<float>(rcClient.top) / m_layoutMetrics.pointScaleFactor,
|
||||
static_cast<float>(rcClient.right) / m_layoutMetrics.pointScaleFactor,
|
||||
static_cast<float>(rcClient.bottom) / m_layoutMetrics.pointScaleFactor};
|
||||
d2dDeviceContext->FillRectangle(fillRect, backgroundBrush.get());
|
||||
}
|
||||
|
||||
// TODO keep track of proper invalid rect
|
||||
auto hrDraw = m_textServices->TxDrawD2D(d2dDeviceContext.get(), &rc, nullptr, TXTVIEW_ACTIVE);
|
||||
winrt::check_hresult(hrDraw);
|
||||
|
||||
// draw placeholder text if needed
|
||||
if (!m_props->placeholder.empty() && GetTextFromRichEdit().empty()) {
|
||||
// set brush color
|
||||
winrt::com_ptr<ID2D1SolidColorBrush> brush;
|
||||
if (m_props->placeholderTextColor) {
|
||||
auto color = m_props->placeholderTextColor.AsD2DColor();
|
||||
winrt::check_hresult(d2dDeviceContext->CreateSolidColorBrush(color, brush.put()));
|
||||
} else {
|
||||
winrt::check_hresult(
|
||||
d2dDeviceContext->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Gray, 1.0f), brush.put()));
|
||||
if (facebook::react::isColorMeaningful(m_props->backgroundColor)) {
|
||||
auto backgroundColor = m_props->backgroundColor.AsD2DColor();
|
||||
winrt::com_ptr<ID2D1SolidColorBrush> backgroundBrush;
|
||||
winrt::check_hresult(d2dDeviceContext->CreateSolidColorBrush(backgroundColor, backgroundBrush.put()));
|
||||
const D2D1_RECT_F fillRect = {
|
||||
static_cast<float>(rcClient.left) / m_layoutMetrics.pointScaleFactor,
|
||||
static_cast<float>(rcClient.top) / m_layoutMetrics.pointScaleFactor,
|
||||
static_cast<float>(rcClient.right) / m_layoutMetrics.pointScaleFactor,
|
||||
static_cast<float>(rcClient.bottom) / m_layoutMetrics.pointScaleFactor};
|
||||
d2dDeviceContext->FillRectangle(fillRect, backgroundBrush.get());
|
||||
}
|
||||
|
||||
// Create placeholder text layout
|
||||
winrt::com_ptr<::IDWriteTextLayout> textLayout = CreatePlaceholderLayout();
|
||||
// TODO keep track of proper invalid rect
|
||||
auto hrDraw = m_textServices->TxDrawD2D(d2dDeviceContext, &rc, nullptr, TXTVIEW_ACTIVE);
|
||||
winrt::check_hresult(hrDraw);
|
||||
|
||||
// draw text
|
||||
d2dDeviceContext->DrawTextLayout(
|
||||
D2D1::Point2F(
|
||||
static_cast<FLOAT>((offset.x + m_layoutMetrics.contentInsets.left) / m_layoutMetrics.pointScaleFactor),
|
||||
static_cast<FLOAT>((offset.y + m_layoutMetrics.contentInsets.top) / m_layoutMetrics.pointScaleFactor)),
|
||||
textLayout.get(),
|
||||
brush.get(),
|
||||
D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT);
|
||||
// draw placeholder text if needed
|
||||
if (!m_props->placeholder.empty() && GetTextFromRichEdit().empty()) {
|
||||
// set brush color
|
||||
winrt::com_ptr<ID2D1SolidColorBrush> brush;
|
||||
if (m_props->placeholderTextColor) {
|
||||
auto color = m_props->placeholderTextColor.AsD2DColor();
|
||||
winrt::check_hresult(d2dDeviceContext->CreateSolidColorBrush(color, brush.put()));
|
||||
} else {
|
||||
winrt::check_hresult(
|
||||
d2dDeviceContext->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Gray, 1.0f), brush.put()));
|
||||
}
|
||||
|
||||
// Create placeholder text layout
|
||||
winrt::com_ptr<::IDWriteTextLayout> textLayout = CreatePlaceholderLayout();
|
||||
|
||||
// draw text
|
||||
d2dDeviceContext->DrawTextLayout(
|
||||
D2D1::Point2F(
|
||||
static_cast<FLOAT>((offset.x + m_layoutMetrics.contentInsets.left) / m_layoutMetrics.pointScaleFactor),
|
||||
static_cast<FLOAT>((offset.y + m_layoutMetrics.contentInsets.top) / m_layoutMetrics.pointScaleFactor)),
|
||||
textLayout.get(),
|
||||
brush.get(),
|
||||
D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT);
|
||||
}
|
||||
|
||||
// restore dpi state
|
||||
d2dDeviceContext->SetDpi(oldDpiX, oldDpiY);
|
||||
}
|
||||
|
||||
// restore dpi state
|
||||
d2dDeviceContext->SetDpi(oldDpiX, oldDpiY);
|
||||
|
||||
// Our update is done. EndDraw never indicates rendering device removed, so any
|
||||
// failure here is unexpected and, therefore, fatal.
|
||||
auto hrEndDraw = drawingSurfaceInterop->EndDraw();
|
||||
winrt::check_hresult(hrEndDraw);
|
||||
}
|
||||
m_drawing = false;
|
||||
m_needsRedraw = false;
|
||||
|
|
|
@ -83,7 +83,7 @@ struct WindowsTextInputComponentView : CompositionBaseComponentView {
|
|||
winrt::Microsoft::ReactNative::Composition::ISpriteVisual m_visual{nullptr};
|
||||
winrt::Microsoft::ReactNative::Composition::ICaretVisual m_caretVisual{nullptr};
|
||||
winrt::Microsoft::ReactNative::ReactContext m_context;
|
||||
winrt::Microsoft::ReactNative::Composition::ICompositionDrawingSurface m_drawingSurface{nullptr};
|
||||
winrt::Microsoft::ReactNative::Composition::IDrawingSurfaceBrush m_drawingSurface{nullptr};
|
||||
|
||||
// Used by ITextHost impl
|
||||
CHARFORMAT2W m_cf;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "UnimplementedNativeViewComponentView.h"
|
||||
|
||||
#include <Fabric/DWriteHelpers.h>
|
||||
#include "Composition/AutoDraw.h"
|
||||
#include "CompositionDynamicAutomationProvider.h"
|
||||
#include "Unicode.h"
|
||||
|
||||
|
@ -58,16 +59,15 @@ void UnimplementedNativeViewComponentView::updateLayoutMetrics(
|
|||
|
||||
winrt::Windows::Foundation::Size surfaceSize = {
|
||||
width * m_layoutMetrics.pointScaleFactor, height * m_layoutMetrics.pointScaleFactor};
|
||||
auto drawingSurface = m_compContext.CreateDrawingSurface(
|
||||
auto drawingSurface = m_compContext.CreateDrawingSurfaceBrush(
|
||||
surfaceSize,
|
||||
winrt::Windows::Graphics::DirectX::DirectXPixelFormat::B8G8R8A8UIntNormalized,
|
||||
winrt::Windows::Graphics::DirectX::DirectXAlphaMode::Premultiplied);
|
||||
|
||||
auto surfaceBrush = m_compContext.CreateSurfaceBrush(drawingSurface);
|
||||
surfaceBrush.HorizontalAlignmentRatio(0.f);
|
||||
surfaceBrush.VerticalAlignmentRatio(0.f);
|
||||
surfaceBrush.Stretch(winrt::Microsoft::ReactNative::Composition::CompositionStretch::None);
|
||||
m_visual.Brush(surfaceBrush);
|
||||
drawingSurface.HorizontalAlignmentRatio(0.f);
|
||||
drawingSurface.VerticalAlignmentRatio(0.f);
|
||||
drawingSurface.Stretch(winrt::Microsoft::ReactNative::Composition::CompositionStretch::None);
|
||||
m_visual.Brush(drawingSurface);
|
||||
m_visual.Size(surfaceSize);
|
||||
m_visual.Offset({
|
||||
layoutMetrics.frame.origin.x * layoutMetrics.pointScaleFactor,
|
||||
|
@ -75,52 +75,49 @@ void UnimplementedNativeViewComponentView::updateLayoutMetrics(
|
|||
0.0f,
|
||||
});
|
||||
|
||||
winrt::com_ptr<ID2D1DeviceContext> d2dDeviceContext;
|
||||
POINT offset;
|
||||
{
|
||||
::Microsoft::ReactNative::Composition::AutoDrawDrawingSurface autoDraw(drawingSurface, &offset);
|
||||
if (auto d2dDeviceContext = autoDraw.GetRenderTarget()) {
|
||||
d2dDeviceContext->Clear(D2D1::ColorF(D2D1::ColorF::Red, 0.3f));
|
||||
assert(d2dDeviceContext->GetUnitMode() == D2D1_UNIT_MODE_DIPS);
|
||||
const auto dpi = m_layoutMetrics.pointScaleFactor * 96.0f;
|
||||
float oldDpiX, oldDpiY;
|
||||
d2dDeviceContext->GetDpi(&oldDpiX, &oldDpiY);
|
||||
d2dDeviceContext->SetDpi(dpi, dpi);
|
||||
|
||||
winrt::com_ptr<Composition::ICompositionDrawingSurfaceInterop> drawingSurfaceInterop;
|
||||
drawingSurface.as(drawingSurfaceInterop);
|
||||
float offsetX = static_cast<float>(offset.x / m_layoutMetrics.pointScaleFactor);
|
||||
float offsetY = static_cast<float>(offset.y / m_layoutMetrics.pointScaleFactor);
|
||||
|
||||
if (CheckForDeviceRemoved(drawingSurfaceInterop->BeginDraw(d2dDeviceContext.put(), &offset))) {
|
||||
d2dDeviceContext->Clear(D2D1::ColorF(D2D1::ColorF::Red, 0.3f));
|
||||
assert(d2dDeviceContext->GetUnitMode() == D2D1_UNIT_MODE_DIPS);
|
||||
const auto dpi = m_layoutMetrics.pointScaleFactor * 96.0f;
|
||||
float oldDpiX, oldDpiY;
|
||||
d2dDeviceContext->GetDpi(&oldDpiX, &oldDpiY);
|
||||
d2dDeviceContext->SetDpi(dpi, dpi);
|
||||
winrt::com_ptr<IDWriteTextFormat> spTextFormat;
|
||||
winrt::check_hresult(Microsoft::ReactNative::DWriteFactory()->CreateTextFormat(
|
||||
L"Segoe UI",
|
||||
nullptr, // Font collection (nullptr sets it to use the system font collection).
|
||||
DWRITE_FONT_WEIGHT_REGULAR,
|
||||
DWRITE_FONT_STYLE_NORMAL,
|
||||
DWRITE_FONT_STRETCH_NORMAL,
|
||||
12,
|
||||
L"",
|
||||
spTextFormat.put()));
|
||||
|
||||
float offsetX = static_cast<float>(offset.x / m_layoutMetrics.pointScaleFactor);
|
||||
float offsetY = static_cast<float>(offset.y / m_layoutMetrics.pointScaleFactor);
|
||||
winrt::com_ptr<ID2D1SolidColorBrush> textBrush;
|
||||
winrt::check_hresult(
|
||||
d2dDeviceContext->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::White), textBrush.put()));
|
||||
|
||||
winrt::com_ptr<IDWriteTextFormat> spTextFormat;
|
||||
winrt::check_hresult(Microsoft::ReactNative::DWriteFactory()->CreateTextFormat(
|
||||
L"Segoe UI",
|
||||
nullptr, // Font collection (nullptr sets it to use the system font collection).
|
||||
DWRITE_FONT_WEIGHT_REGULAR,
|
||||
DWRITE_FONT_STYLE_NORMAL,
|
||||
DWRITE_FONT_STRETCH_NORMAL,
|
||||
12,
|
||||
L"",
|
||||
spTextFormat.put()));
|
||||
const D2D1_RECT_F rect = {
|
||||
static_cast<float>(offset.x), static_cast<float>(offset.y), width + offset.x, height + offset.y};
|
||||
// const D2D1_RECT_F rect = {0.f, 0.f, width, height};
|
||||
|
||||
winrt::com_ptr<ID2D1SolidColorBrush> textBrush;
|
||||
winrt::check_hresult(d2dDeviceContext->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::White), textBrush.put()));
|
||||
|
||||
const D2D1_RECT_F rect = {
|
||||
static_cast<float>(offset.x), static_cast<float>(offset.y), width + offset.x, height + offset.y};
|
||||
// const D2D1_RECT_F rect = {0.f, 0.f, width, height};
|
||||
|
||||
auto label = Microsoft::Common::Unicode::Utf8ToUtf16(std::string("Unimplemented component: ") + m_props->name);
|
||||
d2dDeviceContext->DrawText(
|
||||
label.c_str(),
|
||||
static_cast<UINT32>(label.length()),
|
||||
spTextFormat.get(),
|
||||
rect,
|
||||
textBrush.get(),
|
||||
D2D1_DRAW_TEXT_OPTIONS_NONE,
|
||||
DWRITE_MEASURING_MODE_NATURAL);
|
||||
|
||||
winrt::check_hresult(drawingSurfaceInterop->EndDraw());
|
||||
auto label = Microsoft::Common::Unicode::Utf8ToUtf16(std::string("Unimplemented component: ") + m_props->name);
|
||||
d2dDeviceContext->DrawText(
|
||||
label.c_str(),
|
||||
static_cast<UINT32>(label.length()),
|
||||
spTextFormat.get(),
|
||||
rect,
|
||||
textBrush.get(),
|
||||
D2D1_DRAW_TEXT_OPTIONS_NONE,
|
||||
DWRITE_MEASURING_MODE_NATURAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_layoutMetrics = layoutMetrics;
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
<file src="$nugetroot$\inc\stubs\**\*.*" target="inc" />
|
||||
|
||||
<file src="$nugetroot$\inc\Shared\AbiSafe.h" target="inc"/>
|
||||
<file src="$nugetroot$\inc\Shared\Composition\AutoDraw.h" target="inc"/>
|
||||
<file src="$nugetroot$\inc\Shared\Composition\CompositionSwitcher.interop.h" target="inc"/>
|
||||
<file src="$nugetroot$\inc\Shared\DevSettings.h" target="inc"/>
|
||||
<file src="$nugetroot$\inc\ReactWin32\INativeUIManagerLegacy.h" target="inc"/>
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include <winrt/Microsoft.ReactNative.Composition.h>
|
||||
|
||||
namespace Microsoft::ReactNative::Composition {
|
||||
|
||||
class AutoDrawDrawingSurface {
|
||||
public:
|
||||
AutoDrawDrawingSurface(
|
||||
winrt::Microsoft::ReactNative::Composition::IDrawingSurfaceBrush &drawingSurface,
|
||||
POINT *offset) noexcept {
|
||||
drawingSurface.as(m_drawingSurfaceInterop);
|
||||
m_drawingSurfaceInterop->BeginDraw(m_d2dDeviceContext.put(), offset);
|
||||
}
|
||||
|
||||
~AutoDrawDrawingSurface() noexcept {
|
||||
if (m_d2dDeviceContext) {
|
||||
m_drawingSurfaceInterop->EndDraw();
|
||||
}
|
||||
}
|
||||
|
||||
operator ID2D1DeviceContext *() noexcept {
|
||||
return m_d2dDeviceContext.get();
|
||||
}
|
||||
|
||||
ID2D1DeviceContext *GetRenderTarget() noexcept {
|
||||
return m_d2dDeviceContext.get();
|
||||
}
|
||||
|
||||
private:
|
||||
winrt::com_ptr<ICompositionDrawingSurfaceInterop> m_drawingSurfaceInterop;
|
||||
winrt::com_ptr<ID2D1DeviceContext> m_d2dDeviceContext;
|
||||
};
|
||||
|
||||
} // namespace Microsoft::ReactNative::Composition
|
Загрузка…
Ссылка в новой задаче