[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:
Andrew Coates 2023-09-05 17:09:55 -07:00 коммит произвёл GitHub
Родитель f859b4ccfa
Коммит ffeafc3f72
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
18 изменённых файлов: 387 добавлений и 406 удалений

Просмотреть файл

@ -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 &paragraphProps = *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 &paragraphProps = *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 &paragraphProps = *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