2018-11-21 17:18:59 +08:00
|
|
|
|
// Copyright (c) 2016-2018 Easy2D - Nomango
|
|
|
|
|
|
//
|
|
|
|
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
|
|
|
|
// in the Software without restriction, including without limitation the rights
|
|
|
|
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
|
|
|
|
// furnished to do so, subject to the following conditions:
|
|
|
|
|
|
//
|
|
|
|
|
|
// The above copyright notice and this permission notice shall be included in
|
|
|
|
|
|
// all copies or substantial portions of the Software.
|
|
|
|
|
|
//
|
|
|
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
|
|
// THE SOFTWARE.
|
|
|
|
|
|
|
|
|
|
|
|
#include "Factory.h"
|
|
|
|
|
|
#include "logs.h"
|
|
|
|
|
|
#include "modules.h"
|
|
|
|
|
|
#include "Transform.hpp"
|
|
|
|
|
|
|
|
|
|
|
|
namespace easy2d
|
|
|
|
|
|
{
|
|
|
|
|
|
FactoryImpl::FactoryImpl()
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
FactoryImpl::~FactoryImpl()
|
|
|
|
|
|
{
|
|
|
|
|
|
E2D_LOG("Destroying device independent resources");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-11-21 19:24:18 +08:00
|
|
|
|
HRESULT FactoryImpl::Init(bool debug)
|
2018-11-21 17:18:59 +08:00
|
|
|
|
{
|
|
|
|
|
|
E2D_LOG("Creating device independent resources");
|
|
|
|
|
|
|
|
|
|
|
|
D2D1_FACTORY_OPTIONS fact_options;
|
|
|
|
|
|
fact_options.debugLevel = debug ? D2D1_DEBUG_LEVEL_INFORMATION : D2D1_DEBUG_LEVEL_NONE;
|
2018-11-21 19:24:18 +08:00
|
|
|
|
HRESULT hr = modules::DirectX().D2D1CreateFactory(
|
|
|
|
|
|
D2D1_FACTORY_TYPE_SINGLE_THREADED,
|
|
|
|
|
|
__uuidof(ID2D1Factory),
|
|
|
|
|
|
&fact_options,
|
|
|
|
|
|
reinterpret_cast<void**>(&factory_)
|
2018-11-21 17:18:59 +08:00
|
|
|
|
);
|
|
|
|
|
|
|
2018-11-21 19:24:18 +08:00
|
|
|
|
if (SUCCEEDED(hr))
|
|
|
|
|
|
{
|
2018-11-21 17:18:59 +08:00
|
|
|
|
CoCreateInstance(
|
|
|
|
|
|
CLSID_WICImagingFactory,
|
|
|
|
|
|
nullptr,
|
|
|
|
|
|
CLSCTX_INPROC_SERVER,
|
|
|
|
|
|
__uuidof(IWICImagingFactory),
|
2018-11-21 19:24:18 +08:00
|
|
|
|
reinterpret_cast<void**>(&imaging_factory_)
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
2018-11-21 17:18:59 +08:00
|
|
|
|
|
2018-11-21 19:24:18 +08:00
|
|
|
|
if (SUCCEEDED(hr))
|
|
|
|
|
|
{
|
2018-11-21 17:18:59 +08:00
|
|
|
|
modules::DirectX().DWriteCreateFactory(
|
|
|
|
|
|
DWRITE_FACTORY_TYPE_SHARED,
|
|
|
|
|
|
__uuidof(IDWriteFactory),
|
2018-11-21 19:24:18 +08:00
|
|
|
|
reinterpret_cast<IUnknown**>(&write_factory_)
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
2018-11-21 17:18:59 +08:00
|
|
|
|
|
2018-11-21 19:24:18 +08:00
|
|
|
|
if (SUCCEEDED(hr))
|
|
|
|
|
|
{
|
|
|
|
|
|
auto stroke_style = D2D1::StrokeStyleProperties(
|
|
|
|
|
|
D2D1_CAP_STYLE_FLAT,
|
|
|
|
|
|
D2D1_CAP_STYLE_FLAT,
|
|
|
|
|
|
D2D1_CAP_STYLE_FLAT,
|
|
|
|
|
|
D2D1_LINE_JOIN_MITER,
|
|
|
|
|
|
2.0f,
|
|
|
|
|
|
D2D1_DASH_STYLE_SOLID,
|
|
|
|
|
|
0.0f
|
|
|
|
|
|
);
|
2018-11-21 17:18:59 +08:00
|
|
|
|
|
2018-11-21 19:24:18 +08:00
|
|
|
|
hr = factory_->CreateStrokeStyle(
|
2018-11-21 17:18:59 +08:00
|
|
|
|
stroke_style,
|
|
|
|
|
|
nullptr,
|
|
|
|
|
|
0,
|
2018-11-21 19:24:18 +08:00
|
|
|
|
&miter_stroke_style_
|
|
|
|
|
|
);
|
2018-11-21 17:18:59 +08:00
|
|
|
|
|
2018-11-21 19:24:18 +08:00
|
|
|
|
if (SUCCEEDED(hr))
|
|
|
|
|
|
{
|
|
|
|
|
|
stroke_style.lineJoin = D2D1_LINE_JOIN_BEVEL;
|
|
|
|
|
|
hr = factory_->CreateStrokeStyle(
|
|
|
|
|
|
stroke_style,
|
|
|
|
|
|
nullptr,
|
|
|
|
|
|
0,
|
|
|
|
|
|
&bevel_stroke_style_
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
2018-11-21 17:18:59 +08:00
|
|
|
|
|
2018-11-21 19:24:18 +08:00
|
|
|
|
if (SUCCEEDED(hr))
|
|
|
|
|
|
{
|
|
|
|
|
|
stroke_style.lineJoin = D2D1_LINE_JOIN_ROUND;
|
|
|
|
|
|
hr = factory_->CreateStrokeStyle(
|
|
|
|
|
|
stroke_style,
|
|
|
|
|
|
nullptr,
|
|
|
|
|
|
0,
|
|
|
|
|
|
&round_stroke_style_
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return hr;
|
2018-11-21 17:18:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT FactoryImpl::CreateHwndRenderTarget(cpHwndRenderTarget & hwnd_render_target, D2D1_RENDER_TARGET_PROPERTIES const & properties, D2D1_HWND_RENDER_TARGET_PROPERTIES const & hwnd_rt_properties) const
|
|
|
|
|
|
{
|
2018-11-21 19:24:18 +08:00
|
|
|
|
if (!factory_)
|
2018-11-21 17:18:59 +08:00
|
|
|
|
return E_UNEXPECTED;
|
|
|
|
|
|
|
|
|
|
|
|
cpHwndRenderTarget hwnd_render_target_tmp;
|
2018-11-21 19:24:18 +08:00
|
|
|
|
HRESULT hr = factory_->CreateHwndRenderTarget(
|
2018-11-21 17:18:59 +08:00
|
|
|
|
properties,
|
|
|
|
|
|
hwnd_rt_properties,
|
|
|
|
|
|
&hwnd_render_target_tmp
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
if (SUCCEEDED(hr))
|
|
|
|
|
|
hwnd_render_target = hwnd_render_target_tmp;
|
|
|
|
|
|
return hr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT FactoryImpl::CreateTextRenderer(
|
|
|
|
|
|
cpTextRenderer& text_renderer,
|
|
|
|
|
|
cpRenderTarget const& render_target,
|
|
|
|
|
|
cpSolidColorBrush const& brush
|
|
|
|
|
|
)
|
|
|
|
|
|
{
|
2018-11-21 19:24:18 +08:00
|
|
|
|
if (!factory_)
|
2018-11-21 17:18:59 +08:00
|
|
|
|
return E_UNEXPECTED;
|
|
|
|
|
|
|
|
|
|
|
|
cpTextRenderer text_renderer_tmp;
|
|
|
|
|
|
HRESULT hr = ITextRenderer::Create(
|
|
|
|
|
|
&text_renderer_tmp,
|
2018-11-21 19:24:18 +08:00
|
|
|
|
factory_.Get(),
|
2018-11-21 17:18:59 +08:00
|
|
|
|
render_target.Get(),
|
|
|
|
|
|
brush.Get()
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
if (SUCCEEDED(hr))
|
|
|
|
|
|
text_renderer = text_renderer_tmp;
|
|
|
|
|
|
return hr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT FactoryImpl::CreateBitmapFromFile(cpBitmap & bitmap, cpRenderTarget const & rt, String const & file_path)
|
|
|
|
|
|
{
|
2018-11-21 19:24:18 +08:00
|
|
|
|
if (imaging_factory_ == nullptr)
|
2018-11-21 17:18:59 +08:00
|
|
|
|
{
|
|
|
|
|
|
return E_UNEXPECTED;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
using namespace intrusive;
|
|
|
|
|
|
|
|
|
|
|
|
SmartPointer<IWICBitmapDecoder> decoder;
|
|
|
|
|
|
SmartPointer<IWICBitmapFrameDecode> source;
|
|
|
|
|
|
SmartPointer<IWICStream> stream;
|
|
|
|
|
|
SmartPointer<IWICFormatConverter> converter;
|
|
|
|
|
|
SmartPointer<ID2D1Bitmap> bitmap_tmp;
|
|
|
|
|
|
|
2018-11-21 19:24:18 +08:00
|
|
|
|
HRESULT hr = imaging_factory_->CreateDecoderFromFilename(
|
2018-11-21 17:18:59 +08:00
|
|
|
|
file_path.c_str(),
|
|
|
|
|
|
nullptr,
|
|
|
|
|
|
GENERIC_READ,
|
|
|
|
|
|
WICDecodeMetadataCacheOnLoad,
|
|
|
|
|
|
&decoder
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
if (SUCCEEDED(hr))
|
|
|
|
|
|
{
|
|
|
|
|
|
hr = decoder->GetFrame(0, &source);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (SUCCEEDED(hr))
|
|
|
|
|
|
{
|
2018-11-21 19:24:18 +08:00
|
|
|
|
hr = imaging_factory_->CreateFormatConverter(&converter);
|
2018-11-21 17:18:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (SUCCEEDED(hr))
|
|
|
|
|
|
{
|
|
|
|
|
|
// ͼƬ<CDBC><C6AC>ʽת<CABD><D7AA><EFBFBD><EFBFBD> 32bppPBGRA
|
|
|
|
|
|
hr = converter->Initialize(
|
|
|
|
|
|
source.Get(),
|
|
|
|
|
|
GUID_WICPixelFormat32bppPBGRA,
|
|
|
|
|
|
WICBitmapDitherTypeNone,
|
|
|
|
|
|
nullptr,
|
|
|
|
|
|
0.f,
|
|
|
|
|
|
WICBitmapPaletteTypeMedianCut
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (SUCCEEDED(hr))
|
|
|
|
|
|
{
|
|
|
|
|
|
hr = rt->CreateBitmapFromWicBitmap(
|
|
|
|
|
|
converter.Get(),
|
|
|
|
|
|
nullptr,
|
|
|
|
|
|
&bitmap_tmp
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (SUCCEEDED(hr))
|
|
|
|
|
|
bitmap = bitmap_tmp;
|
|
|
|
|
|
|
|
|
|
|
|
return hr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT FactoryImpl::CreateBitmapFromResource(cpBitmap & bitmap, cpRenderTarget const & rt, Resource const & res)
|
|
|
|
|
|
{
|
2018-11-21 19:24:18 +08:00
|
|
|
|
if (imaging_factory_ == nullptr)
|
2018-11-21 17:18:59 +08:00
|
|
|
|
{
|
|
|
|
|
|
return E_UNEXPECTED;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
using namespace intrusive;
|
|
|
|
|
|
|
|
|
|
|
|
SmartPointer<IWICBitmapDecoder> decoder;
|
|
|
|
|
|
SmartPointer<IWICBitmapFrameDecode> source;
|
|
|
|
|
|
SmartPointer<IWICStream> stream;
|
|
|
|
|
|
SmartPointer<IWICFormatConverter> converter;
|
|
|
|
|
|
SmartPointer<ID2D1Bitmap> bitmap_tmp;
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ
|
|
|
|
|
|
ResourceData buffer;
|
|
|
|
|
|
HRESULT hr = res.Load(&buffer) ? S_OK : E_FAIL;
|
|
|
|
|
|
|
|
|
|
|
|
if (SUCCEEDED(hr))
|
|
|
|
|
|
{
|
2018-11-21 19:24:18 +08:00
|
|
|
|
hr = imaging_factory_->CreateStream(&stream);
|
2018-11-21 17:18:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (SUCCEEDED(hr))
|
|
|
|
|
|
{
|
|
|
|
|
|
hr = stream->InitializeFromMemory(
|
|
|
|
|
|
static_cast<WICInProcPointer>(buffer.buffer),
|
|
|
|
|
|
buffer.buffer_size
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (SUCCEEDED(hr))
|
|
|
|
|
|
{
|
2018-11-21 19:24:18 +08:00
|
|
|
|
hr = imaging_factory_->CreateDecoderFromStream(
|
2018-11-21 17:18:59 +08:00
|
|
|
|
stream.Get(),
|
|
|
|
|
|
nullptr,
|
|
|
|
|
|
WICDecodeMetadataCacheOnLoad,
|
|
|
|
|
|
&decoder
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (SUCCEEDED(hr))
|
|
|
|
|
|
{
|
|
|
|
|
|
hr = decoder->GetFrame(0, &source);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (SUCCEEDED(hr))
|
|
|
|
|
|
{
|
2018-11-21 19:24:18 +08:00
|
|
|
|
hr = imaging_factory_->CreateFormatConverter(&converter);
|
2018-11-21 17:18:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (SUCCEEDED(hr))
|
|
|
|
|
|
{
|
|
|
|
|
|
// ͼƬ<CDBC><C6AC>ʽת<CABD><D7AA><EFBFBD><EFBFBD> 32bppPBGRA
|
|
|
|
|
|
hr = converter->Initialize(
|
|
|
|
|
|
source.Get(),
|
|
|
|
|
|
GUID_WICPixelFormat32bppPBGRA,
|
|
|
|
|
|
WICBitmapDitherTypeNone,
|
|
|
|
|
|
nullptr,
|
|
|
|
|
|
0.f,
|
|
|
|
|
|
WICBitmapPaletteTypeMedianCut
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (SUCCEEDED(hr))
|
|
|
|
|
|
{
|
|
|
|
|
|
hr = rt->CreateBitmapFromWicBitmap(
|
|
|
|
|
|
converter.Get(),
|
|
|
|
|
|
nullptr,
|
|
|
|
|
|
&bitmap_tmp
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (SUCCEEDED(hr))
|
|
|
|
|
|
{
|
|
|
|
|
|
bitmap = bitmap_tmp;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return hr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT FactoryImpl::CreateRectangleGeometry(cpRectangleGeometry & geo, Rect const& rect) const
|
|
|
|
|
|
{
|
2018-11-21 19:24:18 +08:00
|
|
|
|
if (!factory_)
|
2018-11-21 17:18:59 +08:00
|
|
|
|
return E_UNEXPECTED;
|
|
|
|
|
|
|
|
|
|
|
|
cpRectangleGeometry rectangle;
|
2018-11-21 19:24:18 +08:00
|
|
|
|
HRESULT hr = factory_->CreateRectangleGeometry(
|
2018-11-21 17:18:59 +08:00
|
|
|
|
rect,
|
|
|
|
|
|
&rectangle
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
if (SUCCEEDED(hr))
|
|
|
|
|
|
geo = rectangle;
|
|
|
|
|
|
return hr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT FactoryImpl::CreateRoundedRectangleGeometry(cpRoundedRectangleGeometry & geo, Rect const & rect, float radius_x, float radius_y) const
|
|
|
|
|
|
{
|
2018-11-21 19:24:18 +08:00
|
|
|
|
if (!factory_)
|
2018-11-21 17:18:59 +08:00
|
|
|
|
return E_UNEXPECTED;
|
|
|
|
|
|
|
|
|
|
|
|
cpRoundedRectangleGeometry rounded_rect;
|
2018-11-21 19:24:18 +08:00
|
|
|
|
HRESULT hr = factory_->CreateRoundedRectangleGeometry(
|
2018-11-21 17:18:59 +08:00
|
|
|
|
D2D1::RoundedRect(
|
|
|
|
|
|
rect,
|
|
|
|
|
|
radius_x,
|
|
|
|
|
|
radius_y
|
|
|
|
|
|
),
|
|
|
|
|
|
&rounded_rect
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
if (SUCCEEDED(hr))
|
|
|
|
|
|
geo = rounded_rect;
|
|
|
|
|
|
return hr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT FactoryImpl::CreateEllipseGeometry(cpEllipseGeometry & geo, Point const & center, float radius_x, float radius_y) const
|
|
|
|
|
|
{
|
2018-11-21 19:24:18 +08:00
|
|
|
|
if (!factory_)
|
2018-11-21 17:18:59 +08:00
|
|
|
|
return E_UNEXPECTED;
|
|
|
|
|
|
|
|
|
|
|
|
cpEllipseGeometry ellipse;
|
2018-11-21 19:24:18 +08:00
|
|
|
|
HRESULT hr = factory_->CreateEllipseGeometry(
|
2018-11-21 17:18:59 +08:00
|
|
|
|
D2D1::Ellipse(
|
|
|
|
|
|
center,
|
|
|
|
|
|
radius_x,
|
|
|
|
|
|
radius_y
|
|
|
|
|
|
),
|
|
|
|
|
|
&ellipse
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
if (SUCCEEDED(hr))
|
|
|
|
|
|
geo = ellipse;
|
|
|
|
|
|
return hr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT FactoryImpl::CreateTransformedGeometry(
|
|
|
|
|
|
cpTransformedGeometry& transformed,
|
|
|
|
|
|
math::Matrix const& matrix,
|
|
|
|
|
|
cpGeometry const& geo
|
|
|
|
|
|
) const
|
|
|
|
|
|
{
|
2018-11-21 19:24:18 +08:00
|
|
|
|
if (!factory_)
|
2018-11-21 17:18:59 +08:00
|
|
|
|
return E_UNEXPECTED;
|
|
|
|
|
|
|
|
|
|
|
|
cpTransformedGeometry transformed_tmp;
|
2018-11-21 19:24:18 +08:00
|
|
|
|
HRESULT hr = factory_->CreateTransformedGeometry(
|
2018-11-21 17:18:59 +08:00
|
|
|
|
geo.Get(),
|
|
|
|
|
|
ConvertToD2DMatrix(matrix),
|
|
|
|
|
|
&transformed_tmp
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
if (SUCCEEDED(hr))
|
|
|
|
|
|
{
|
|
|
|
|
|
transformed = transformed_tmp;
|
|
|
|
|
|
}
|
|
|
|
|
|
return hr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT FactoryImpl::CreatePathGeometry(cpPathGeometry & geometry) const
|
|
|
|
|
|
{
|
2018-11-21 19:24:18 +08:00
|
|
|
|
if (!factory_)
|
2018-11-21 17:18:59 +08:00
|
|
|
|
return E_UNEXPECTED;
|
|
|
|
|
|
|
2018-11-21 19:24:18 +08:00
|
|
|
|
return factory_->CreatePathGeometry(&geometry);
|
2018-11-21 17:18:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT FactoryImpl::CreateTextFormat(cpTextFormat & text_format, Font const & font, TextStyle const & text_style) const
|
|
|
|
|
|
{
|
2018-11-21 19:24:18 +08:00
|
|
|
|
if (!write_factory_)
|
2018-11-21 17:18:59 +08:00
|
|
|
|
return E_UNEXPECTED;
|
|
|
|
|
|
|
|
|
|
|
|
cpTextFormat text_format_tmp;
|
2018-11-21 19:24:18 +08:00
|
|
|
|
HRESULT hr = write_factory_->CreateTextFormat(
|
2018-11-21 17:18:59 +08:00
|
|
|
|
font.family.c_str(),
|
|
|
|
|
|
nullptr,
|
|
|
|
|
|
DWRITE_FONT_WEIGHT(font.weight),
|
|
|
|
|
|
font.italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL,
|
|
|
|
|
|
DWRITE_FONT_STRETCH_NORMAL,
|
|
|
|
|
|
font.size,
|
|
|
|
|
|
L"",
|
|
|
|
|
|
&text_format_tmp
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
if (SUCCEEDED(hr))
|
|
|
|
|
|
{
|
|
|
|
|
|
if (text_style.line_spacing == 0.f)
|
|
|
|
|
|
{
|
|
|
|
|
|
text_format_tmp->SetLineSpacing(DWRITE_LINE_SPACING_METHOD_DEFAULT, 0, 0);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
text_format_tmp->SetLineSpacing(
|
|
|
|
|
|
DWRITE_LINE_SPACING_METHOD_UNIFORM,
|
|
|
|
|
|
text_style.line_spacing,
|
|
|
|
|
|
text_style.line_spacing * 0.8f
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
text_format_tmp->SetTextAlignment(DWRITE_TEXT_ALIGNMENT(text_style.alignment));
|
|
|
|
|
|
text_format_tmp->SetWordWrapping(text_style.wrap ? DWRITE_WORD_WRAPPING_WRAP : DWRITE_WORD_WRAPPING_NO_WRAP);
|
|
|
|
|
|
text_format = text_format_tmp;
|
|
|
|
|
|
}
|
|
|
|
|
|
return hr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT FactoryImpl::CreateTextLayout(cpTextLayout & text_layout, Size& layout_size, String const & text, cpTextFormat const& text_format, TextStyle const & text_style) const
|
|
|
|
|
|
{
|
2018-11-21 19:24:18 +08:00
|
|
|
|
if (!write_factory_)
|
2018-11-21 17:18:59 +08:00
|
|
|
|
return E_UNEXPECTED;
|
|
|
|
|
|
|
|
|
|
|
|
text_layout = nullptr;
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
cpTextLayout text_layout_tmp;
|
|
|
|
|
|
UINT32 length = static_cast<UINT32>(text.length());
|
|
|
|
|
|
|
|
|
|
|
|
if (text_style.wrap)
|
|
|
|
|
|
{
|
2018-11-21 19:24:18 +08:00
|
|
|
|
hr = write_factory_->CreateTextLayout(
|
2018-11-21 17:18:59 +08:00
|
|
|
|
text.c_str(),
|
|
|
|
|
|
length,
|
|
|
|
|
|
text_format.Get(),
|
|
|
|
|
|
text_style.wrap_width,
|
|
|
|
|
|
0,
|
|
|
|
|
|
&text_layout_tmp
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2018-11-21 19:24:18 +08:00
|
|
|
|
hr = write_factory_->CreateTextLayout(
|
2018-11-21 17:18:59 +08:00
|
|
|
|
text.c_str(),
|
|
|
|
|
|
length,
|
|
|
|
|
|
text_format.Get(),
|
|
|
|
|
|
0,
|
|
|
|
|
|
0,
|
|
|
|
|
|
&text_layout_tmp
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
DWRITE_TEXT_METRICS metrics;
|
|
|
|
|
|
text_layout_tmp->GetMetrics(&metrics);
|
|
|
|
|
|
|
|
|
|
|
|
if (SUCCEEDED(hr))
|
|
|
|
|
|
{
|
|
|
|
|
|
text_layout_tmp = nullptr;
|
2018-11-21 19:24:18 +08:00
|
|
|
|
hr = write_factory_->CreateTextLayout(
|
2018-11-21 17:18:59 +08:00
|
|
|
|
text.c_str(),
|
|
|
|
|
|
length,
|
|
|
|
|
|
text_format.Get(),
|
|
|
|
|
|
metrics.width,
|
|
|
|
|
|
0,
|
|
|
|
|
|
&text_layout_tmp
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (SUCCEEDED(hr))
|
|
|
|
|
|
{
|
|
|
|
|
|
DWRITE_TEXT_METRICS metrics;
|
|
|
|
|
|
text_layout_tmp->GetMetrics(&metrics);
|
|
|
|
|
|
|
|
|
|
|
|
if (text_style.wrap)
|
|
|
|
|
|
{
|
|
|
|
|
|
layout_size = Size(metrics.layoutWidth, metrics.height);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
layout_size = Size(metrics.width, metrics.height);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DWRITE_TEXT_RANGE range = { 0, length };
|
|
|
|
|
|
if (text_style.underline)
|
|
|
|
|
|
{
|
|
|
|
|
|
text_layout_tmp->SetUnderline(true, range);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (text_style.strikethrough)
|
|
|
|
|
|
{
|
|
|
|
|
|
text_layout_tmp->SetStrikethrough(true, range);
|
|
|
|
|
|
}
|
|
|
|
|
|
text_layout = text_layout_tmp;
|
|
|
|
|
|
}
|
|
|
|
|
|
return hr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
cpStrokeStyle const& FactoryImpl::GetStrokeStyle(StrokeStyle stroke) const
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (stroke)
|
|
|
|
|
|
{
|
|
|
|
|
|
case StrokeStyle::Miter:
|
2018-11-21 19:24:18 +08:00
|
|
|
|
return miter_stroke_style_;
|
2018-11-21 17:18:59 +08:00
|
|
|
|
break;
|
|
|
|
|
|
case StrokeStyle::Bevel:
|
2018-11-21 19:24:18 +08:00
|
|
|
|
return bevel_stroke_style_;
|
2018-11-21 17:18:59 +08:00
|
|
|
|
break;
|
|
|
|
|
|
case StrokeStyle::Round:
|
2018-11-21 19:24:18 +08:00
|
|
|
|
return round_stroke_style_;
|
2018-11-21 17:18:59 +08:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
2018-11-21 19:24:18 +08:00
|
|
|
|
return miter_stroke_style_;
|
2018-11-21 17:18:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|