Add TextFormat && TextLayout

This commit is contained in:
Nomango 2019-08-15 11:22:51 +08:00
parent d34e14b799
commit ed79c69e7a
16 changed files with 408 additions and 320 deletions

View File

@ -47,6 +47,14 @@ only_commits:
- scripts/**/*.ps1
- appveyor.yml
for:
-
branches:
except:
- master
only_commits:
message: /\[build\]/
configuration:
- Debug
- Release
@ -67,19 +75,8 @@ build:
project: projects/Kiwano.sln
verbosity: minimal
for:
-
branches:
except:
- master
only_commits:
message: /\[build\]/
-
branches:
only:
- master
after_build:
- ps: .\scripts\appveyor\wait_for_other_jobs.ps1
after_build:
- ps: .\scripts\appveyor\wait_for_other_jobs.ps1
artifacts:
- path: projects/output/**/*.lib
@ -119,6 +116,6 @@ notifications:
- provider: Email
to:
- 569629550@qq.com
on_build_success: false
on_build_success: true
on_build_failure: true
on_build_status_changed: false

View File

@ -77,6 +77,7 @@
<ClInclude Include="..\src\kiwano\renderer\Image.h" />
<ClInclude Include="..\src\kiwano\renderer\ImageCache.h" />
<ClInclude Include="..\src\kiwano\renderer\Renderer.h" />
<ClInclude Include="..\src\kiwano\renderer\TextLayout.h" />
<ClInclude Include="..\src\kiwano\renderer\TextRenderer.h" />
<ClInclude Include="..\src\kiwano\third-party\StackWalker\StackWalker.h" />
<ClInclude Include="..\src\kiwano\third-party\tinyxml2\tinyxml2.h" />
@ -130,6 +131,7 @@
<ClCompile Include="..\src\kiwano\renderer\Image.cpp" />
<ClCompile Include="..\src\kiwano\renderer\ImageCache.cpp" />
<ClCompile Include="..\src\kiwano\renderer\Renderer.cpp" />
<ClCompile Include="..\src\kiwano\renderer\TextLayout.cpp" />
<ClCompile Include="..\src\kiwano\renderer\TextRenderer.cpp" />
<ClCompile Include="..\src\kiwano\third-party\StackWalker\StackWalker.cpp" />
<ClCompile Include="..\src\kiwano\third-party\tinyxml2\tinyxml2.cpp" />

View File

@ -288,6 +288,9 @@
<ClInclude Include="..\src\kiwano\renderer\Renderer.h">
<Filter>renderer</Filter>
</ClInclude>
<ClInclude Include="..\src\kiwano\renderer\TextLayout.h">
<Filter>renderer</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\kiwano\ui\Button.cpp">
@ -443,5 +446,8 @@
<ClCompile Include="..\src\kiwano\renderer\Renderer.cpp">
<Filter>renderer</Filter>
</ClCompile>
<ClCompile Include="..\src\kiwano\renderer\TextLayout.cpp">
<Filter>renderer</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -131,7 +131,7 @@ namespace kiwano
auto renderer = Renderer::GetInstance();
renderer->SetTransform(transform_matrix_);
renderer->FillRectangle(bounds, Color(Color::Red, .4f));
renderer->DrawRectangle(bounds, Color(Color::Red, .8f), 4.f);
renderer->DrawRectangle(bounds, Color(Color::Red, .8f), 2.f);
}
for (auto child = children_.first_item(); child; child = child->next_item())

View File

@ -275,21 +275,18 @@ namespace kiwano
ThrowIfFailed(
Renderer::GetInstance()->GetD2DDeviceResources()->CreateTextFormat(
text_format_,
text_font_,
text_style_
text_font_
)
);
}
ComPtr<IDWriteTextLayout> text_layout;
Size layout_size;
ThrowIfFailed(
Renderer::GetInstance()->GetD2DDeviceResources()->CreateTextLayout(
text_layout,
layout_size,
text,
text_format_,
text_style_
text_style_,
text_format_
)
);

View File

@ -46,7 +46,6 @@ namespace kiwano
debug_text_->SetFont(font);
TextStyle style;
style.wrap = false;
style.line_spacing = 20.f;
debug_text_->SetStyle(style);
@ -98,7 +97,7 @@ namespace kiwano
ss << "Memory: " << pmc.PrivateUsage / 1024 << "kb";
debug_text_->SetText(ss.str());
SetSize(Size{ 20 + debug_text_->GetLayoutSize().x, 20 + debug_text_->GetLayoutSize().y });
SetSize(Size{ 20 + debug_text_->GetSize().x, 20 + debug_text_->GetSize().y });
}
}

View File

@ -44,6 +44,7 @@ namespace kiwano
: font_(text_default_font)
, style_(text_default_style)
, layout_dirty_(false)
, format_dirty_(false)
{
}
@ -74,96 +75,6 @@ namespace kiwano
{
}
String const& Text::GetText() const
{
return text_;
}
const Font& Text::GetFont() const
{
return font_;
}
const TextStyle& Text::GetStyle() const
{
return style_;
}
String const& Text::GetFontFamily() const
{
return font_.family;
}
float Text::GetFontSize() const
{
return font_.size;
}
unsigned int Text::GetFontWeight() const
{
return font_.weight;
}
const Color& Text::GetColor() const
{
return style_.color;
}
const Color& Text::GetOutlineColor() const
{
return style_.outline_color;
}
float Text::GetOutlineWidth() const
{
return style_.outline_width;
}
StrokeStyle Text::GetOutlineStroke() const
{
return style_.outline_stroke;
}
int Text::GetLineCount()
{
UpdateLayout();
if (text_layout_)
{
DWRITE_TEXT_METRICS metrics;
if (SUCCEEDED(text_layout_->GetMetrics(&metrics)))
{
return static_cast<int>(metrics.lineCount);
}
}
return 0;
}
Size const& Text::GetLayoutSize() const
{
UpdateLayout();
return layout_size_;
}
bool Text::IsItalic() const
{
return font_.italic;
}
bool Text::HasStrikethrough() const
{
return style_.strikethrough;
}
bool Text::HasUnderline() const
{
return style_.underline;
}
bool Text::HasOutline() const
{
return style_.outline;
}
void Text::SetText(String const& text)
{
text_ = text;
@ -179,7 +90,7 @@ namespace kiwano
void Text::SetFont(const Font & font)
{
font_ = font;
layout_dirty_ = true;
format_dirty_ = true;
}
void Text::SetFontFamily(String const& family)
@ -187,7 +98,7 @@ namespace kiwano
if (font_.family != family)
{
font_.family = family;
layout_dirty_ = true;
format_dirty_ = true;
}
}
@ -196,7 +107,7 @@ namespace kiwano
if (font_.size != size)
{
font_.size = size;
layout_dirty_ = true;
format_dirty_ = true;
}
}
@ -205,7 +116,7 @@ namespace kiwano
if (font_.weight != weight)
{
font_.weight = weight;
layout_dirty_ = true;
format_dirty_ = true;
}
}
@ -219,16 +130,7 @@ namespace kiwano
if (font_.italic != val)
{
font_.italic = val;
layout_dirty_ = true;
}
}
void Text::SetWrapEnabled(bool wrap)
{
if (style_.wrap != wrap)
{
style_.wrap = wrap;
layout_dirty_ = true;
format_dirty_ = true;
}
}
@ -236,12 +138,12 @@ namespace kiwano
{
if (style_.wrap_width != wrap_width)
{
style_.wrap_width = std::max(wrap_width, 0.f);
style_.wrap_width = wrap_width;
layout_dirty_ = true;
}
}
void Text::SetLineacingPtr(float line_spacing)
void Text::SetLineSpacing(float line_spacing)
{
if (style_.line_spacing != line_spacing)
{
@ -301,51 +203,26 @@ namespace kiwano
{
UpdateLayout();
if (text_layout_ && renderer->CheckVisibility(layout_size_, transform_matrix_))
if (text_layout_ && renderer->CheckVisibility(size_, transform_matrix_))
{
PrepareRender(renderer);
renderer->SetTextStyle(
GetDisplayedOpacity(),
style_.color,
style_.outline,
style_.outline_color,
style_.outline_width,
style_.outline_stroke
);
renderer->DrawTextLayout(text_layout_);
}
}
void Text::UpdateLayout() const
void Text::UpdateLayout()
{
if (!layout_dirty_)
return;
if (format_dirty_)
{
format_dirty_ = false;
text_layout_.Update(font_);
}
layout_dirty_ = false;
text_format_ = nullptr;
text_layout_ = nullptr;
if (text_.empty())
return;
auto renderer = Renderer::GetInstance();
ThrowIfFailed(
renderer->GetD2DDeviceResources()->CreateTextFormat(
text_format_,
font_,
style_
)
);
ThrowIfFailed(
renderer->GetD2DDeviceResources()->CreateTextLayout(
text_layout_,
layout_size_,
text_,
text_format_,
style_
)
);
if (layout_dirty_)
{
layout_dirty_ = false;
text_layout_.Update(text_, style_);
SetSize(text_layout_.GetLayoutSize());
}
}
}

View File

@ -20,9 +20,7 @@
#pragma once
#include "Actor.h"
#include "Font.hpp"
#include "TextStyle.hpp"
#include <dwrite.h>
#include "../renderer/TextLayout.h"
namespace kiwano
{
@ -56,52 +54,16 @@ namespace kiwano
virtual ~Text();
// 获取文本
String const& GetText() const;
inline String const& GetText() const { return text_; }
// 获取字体
const Font& GetFont() const;
inline Font GetFont() const { return font_; }
// 获取文本样式
const TextStyle& GetStyle() const;
inline TextStyle GetStyle() const { return style_; }
// 获取字体族
String const& GetFontFamily() const;
// 获取当前字号
float GetFontSize() const;
// 获取当前字体粗细值
unsigned int GetFontWeight() const;
// 获取文字颜色
const Color& GetColor() const;
// 获取描边颜色
const Color& GetOutlineColor() const;
// 获取描边线宽
float GetOutlineWidth() const;
// 获取描边线相交样式
StrokeStyle GetOutlineStroke() const;
// 获取文本显示行数
int GetLineCount();
// 获取文字布局大小
Size const& GetLayoutSize() const;
// 是否是斜体
bool IsItalic() const;
// 是否显示删除线
bool HasStrikethrough() const;
// 是否显示下划线
bool HasUnderline() const;
// 是否显示描边
bool HasOutline() const;
// 获取文本布局
inline TextLayout GetLayout() const { return text_layout_; }
// 设置文本
void SetText(
@ -143,18 +105,13 @@ namespace kiwano
bool val
);
// 打开或关闭文本自动换行(默认为关闭)
void SetWrapEnabled(
bool wrap
);
// 设置文本自动换行的宽度(默认为 0
void SetWrapWidth(
float wrap_width
);
// 设置行间距(默认为 0
void SetLineacingPtr(
void SetLineSpacing(
float line_spacing
);
@ -206,16 +163,14 @@ namespace kiwano
void OnRender(Renderer* renderer) override;
protected:
void UpdateLayout() const;
void UpdateLayout();
protected:
bool format_dirty_;
bool layout_dirty_;
TextLayout text_layout_;
String text_;
Font font_;
TextStyle style_;
mutable bool layout_dirty_;
mutable Size layout_size_;
mutable ComPtr<IDWriteTextFormat> text_format_;
mutable ComPtr<IDWriteTextLayout> text_layout_;
};
}

View File

@ -37,7 +37,6 @@ namespace kiwano
public:
Color color; // 颜色
TextAlign alignment; // 对齐方式
bool wrap; // 打开自动换行
float wrap_width; // 自动换行宽度
float line_spacing; // 行间距
bool underline; // 下划线
@ -51,7 +50,6 @@ namespace kiwano
TextStyle()
: color(Color::White)
, alignment(TextAlign::Left)
, wrap(false)
, wrap_width(0.f)
, line_spacing(0.f)
, underline(false)
@ -65,7 +63,6 @@ namespace kiwano
TextStyle(
Color color,
TextAlign alignment = TextAlign::Left,
bool wrap = false,
float wrap_width = 0.f,
float line_spacing = 0.f,
bool underline = false,
@ -77,7 +74,6 @@ namespace kiwano
)
: color(color)
, alignment(alignment)
, wrap(wrap)
, wrap_width(wrap_width)
, line_spacing(line_spacing)
, underline(underline)
@ -88,4 +84,4 @@ namespace kiwano
, outline_stroke(outline_stroke)
{}
};
}
}

View File

@ -146,7 +146,9 @@ namespace kiwano
if (render_border_enabled_)
{
if (curr_scene_)
{
curr_scene_->RenderBorder();
}
}
}

View File

@ -51,16 +51,14 @@ namespace kiwano
HRESULT CreateTextFormat(
_Out_ ComPtr<IDWriteTextFormat>& text_format,
_In_ Font const& font,
_In_ TextStyle const& text_style
_In_ Font const& font
) const override;
HRESULT CreateTextLayout(
_Out_ ComPtr<IDWriteTextLayout>& text_layout,
_Out_ Size& layout_size,
_In_ String const& text,
_In_ ComPtr<IDWriteTextFormat> const& text_format,
_In_ TextStyle const& text_style
_In_ TextStyle const& text_style,
_In_ ComPtr<IDWriteTextFormat> const& text_format
) const override;
HRESULT SetD2DDevice(
@ -460,13 +458,12 @@ namespace kiwano
return hr;
}
HRESULT D2DDeviceResources::CreateTextFormat(_Out_ ComPtr<IDWriteTextFormat> & text_format,
_In_ Font const & font, _In_ TextStyle const & text_style) const
HRESULT D2DDeviceResources::CreateTextFormat(_Out_ ComPtr<IDWriteTextFormat> & text_format, _In_ Font const & font) const
{
if (!dwrite_factory_)
return E_UNEXPECTED;
ComPtr<IDWriteTextFormat> text_format_tmp;
ComPtr<IDWriteTextFormat> output;
HRESULT hr = dwrite_factory_->CreateTextFormat(
font.family.c_str(),
nullptr,
@ -475,44 +472,27 @@ namespace kiwano
DWRITE_FONT_STRETCH_NORMAL,
font.size,
L"",
&text_format_tmp
&output
);
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;
text_format = output;
}
return hr;
}
HRESULT D2DDeviceResources::CreateTextLayout(_Out_ ComPtr<IDWriteTextLayout> & text_layout,
_Out_ Size& layout_size, _In_ String const & text, _In_ ComPtr<IDWriteTextFormat> const& text_format,
_In_ TextStyle const & text_style) const
HRESULT D2DDeviceResources::CreateTextLayout(_Out_ ComPtr<IDWriteTextLayout> & text_layout, _In_ String const & text,
_In_ TextStyle const & text_style, _In_ ComPtr<IDWriteTextFormat> const& text_format) const
{
if (!dwrite_factory_)
return E_UNEXPECTED;
text_layout = nullptr;
HRESULT hr;
ComPtr<IDWriteTextLayout> text_layout_tmp;
ComPtr<IDWriteTextLayout> output;
UINT32 length = static_cast<UINT32>(text.length());
if (text_style.wrap)
if (text_style.wrap_width > 0)
{
hr = dwrite_factory_->CreateTextLayout(
text.c_str(),
@ -520,7 +500,7 @@ namespace kiwano
text_format.get(),
text_style.wrap_width,
0,
&text_layout_tmp
&output
);
}
else
@ -531,53 +511,70 @@ namespace kiwano
text_format.get(),
0,
0,
&text_layout_tmp
&output
);
}
DWRITE_TEXT_METRICS metrics;
if (SUCCEEDED(hr))
if (SUCCEEDED(hr))
{
if (text_style.line_spacing == 0.f)
{
hr = text_layout_tmp->GetMetrics(&metrics);
hr = output->SetLineSpacing(DWRITE_LINE_SPACING_METHOD_DEFAULT, 0, 0);
}
if (SUCCEEDED(hr))
else
{
text_layout_tmp = nullptr;
hr = dwrite_factory_->CreateTextLayout(
text.c_str(),
length,
text_format.get(),
metrics.width,
0,
&text_layout_tmp
hr = output->SetLineSpacing(
DWRITE_LINE_SPACING_METHOD_UNIFORM,
text_style.line_spacing,
text_style.line_spacing * 0.8f
);
}
}
if (SUCCEEDED(hr))
{
DWRITE_TEXT_METRICS metrics;
text_layout_tmp->GetMetrics(&metrics);
hr = output->SetTextAlignment(DWRITE_TEXT_ALIGNMENT(text_style.alignment));
}
if (text_style.wrap)
{
layout_size = Size(metrics.layoutWidth, metrics.height);
}
else
{
layout_size = Size(metrics.width, metrics.height);
}
if (SUCCEEDED(hr))
{
hr = output->SetWordWrapping((text_style.wrap_width > 0) ? DWRITE_WORD_WRAPPING_WRAP : DWRITE_WORD_WRAPPING_NO_WRAP);
}
DWRITE_TEXT_RANGE range = { 0, length };
if (SUCCEEDED(hr))
{
if (text_style.underline)
{
text_layout_tmp->SetUnderline(true, range);
hr = output->SetUnderline(true, { 0, length });
}
}
if (SUCCEEDED(hr))
{
if (text_style.strikethrough)
{
text_layout_tmp->SetStrikethrough(true, range);
output->SetStrikethrough(true, { 0, length });
}
text_layout = text_layout_tmp;
}
if (SUCCEEDED(hr))
{
// Fix the layout width when the text does not wrap
if (!(text_style.wrap_width > 0))
{
DWRITE_TEXT_METRICS metrics;
hr = output->GetMetrics(&metrics);
if (SUCCEEDED(hr))
{
hr = output->SetMaxWidth(metrics.width);
}
}
}
if (SUCCEEDED(hr))
{
text_layout = output;
}
return hr;
}

View File

@ -48,16 +48,14 @@ namespace kiwano
virtual HRESULT CreateTextFormat(
_Out_ ComPtr<IDWriteTextFormat>& text_format,
_In_ Font const& font,
_In_ TextStyle const& text_style
_In_ Font const& font
) const = 0;
virtual HRESULT CreateTextLayout(
_Out_ ComPtr<IDWriteTextLayout>& text_layout,
_Out_ Size& layout_size,
_In_ String const& text,
_In_ ComPtr<IDWriteTextFormat> const& text_format,
_In_ TextStyle const& text_style
_In_ TextStyle const& text_style,
_In_ ComPtr<IDWriteTextFormat> const& text_format
) const = 0;
virtual ID2D1StrokeStyle* GetStrokeStyle(StrokeStyle stroke) const = 0;

View File

@ -245,6 +245,55 @@ namespace kiwano
ThrowIfFailed(hr);
}
void Renderer::CreateTextFormat(TextFormat& format, Font const& font)
{
HRESULT hr = S_OK;
if (!d2d_res_)
{
hr = E_UNEXPECTED;
}
ComPtr<IDWriteTextFormat> output;
if (SUCCEEDED(hr))
{
hr = d2d_res_->CreateTextFormat(output, font);
}
if (SUCCEEDED(hr))
{
format.SetTextFormat(output);
}
ThrowIfFailed(hr);
}
void Renderer::CreateTextLayout(TextLayout& layout, String const& text, TextStyle const& style, TextFormat const& format)
{
HRESULT hr = S_OK;
if (!d2d_res_)
{
hr = E_UNEXPECTED;
}
ComPtr<IDWriteTextLayout> output;
if (SUCCEEDED(hr))
{
hr = d2d_res_->CreateTextLayout(
output,
text,
style,
format.GetTextFormat()
);
}
if (SUCCEEDED(hr))
{
layout.SetTextLayout(output);
}
ThrowIfFailed(hr);
}
void Renderer::CreateLineGeometry(Geometry& geo, Point const& begin_pos, Point const& end_pos)
{
HRESULT hr = S_OK;
@ -500,7 +549,7 @@ namespace kiwano
ThrowIfFailed(hr);
}
void Renderer::DrawTextLayout(ComPtr<IDWriteTextLayout> const& text_layout)
void Renderer::DrawTextLayout(TextLayout const& layout)
{
HRESULT hr = S_OK;
if (!text_renderer_)
@ -510,7 +559,19 @@ namespace kiwano
if (SUCCEEDED(hr))
{
hr = text_layout->Draw(nullptr, text_renderer_.get(), 0, 0);
SetTextStyle(
opacity_,
layout.GetTextStyle().color,
layout.GetTextStyle().outline,
layout.GetTextStyle().outline_color,
layout.GetTextStyle().outline_width,
layout.GetTextStyle().outline_stroke
);
}
if (SUCCEEDED(hr))
{
hr = layout.GetTextLayout()->Draw(nullptr, text_renderer_.get(), 0, 0);
IncreasePrimitivesCount();
}
@ -676,7 +737,7 @@ namespace kiwano
)
{
HRESULT hr = S_OK;
if (!text_renderer_ || !d3d_res_)
if (!text_renderer_)
{
hr = E_UNEXPECTED;
}

View File

@ -23,11 +23,10 @@
#include "../base/Component.h"
#include "../base/Resource.h"
#include "../2d/include-forwards.h"
#include "../2d/Font.hpp"
#include "../2d/TextStyle.hpp"
#include "helper.hpp"
#include "Image.h"
#include "Geometry.h"
#include "TextLayout.h"
#include "TextRenderer.h"
#if defined(KGE_USE_DIRECTX10)
@ -51,11 +50,44 @@ namespace kiwano
{
KGE_DECLARE_SINGLETON(Renderer);
public:
// 设置清屏颜色
void SetClearColor(
Color const& clear_color
);
// 设置抗锯齿模式
void SetAntialiasMode(
bool enabled
);
// 设置文字抗锯齿模式
void SetTextAntialiasMode(
TextAntialias mode
);
// 开启或关闭垂直同步
void SetVSyncEnabled(
bool enabled
);
public:
void CreateLayer(
ComPtr<ID2D1Layer>& layer
);
void CreateTextFormat(
TextFormat& format,
Font const& font
);
void CreateTextLayout(
TextLayout& layout,
String const& text,
TextStyle const& style,
TextFormat const& format
);
void CreateLineGeometry(
Geometry& geo,
Point const& begin_pos,
@ -114,30 +146,9 @@ namespace kiwano
);
void DrawTextLayout(
ComPtr<IDWriteTextLayout> const& text_layout
TextLayout const& layout
);
// 设置清屏颜色
void SetClearColor(
Color const& clear_color
);
// 设置抗锯齿模式
void SetAntialiasMode(
bool enabled
);
// 设置文字抗锯齿模式
void SetTextAntialiasMode(
TextAntialias mode
);
// 开启或关闭垂直同步
void SetVSyncEnabled(
bool enabled
);
// 设置画笔透明度
void SetOpacity(
float opacity
);

View File

@ -0,0 +1,110 @@
// Copyright (c) 2016-2018 Kiwano - 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 "TextLayout.h"
#include "Renderer.h"
#include "../base/Logger.h"
namespace kiwano
{
//
// TextFormat
//
TextFormat::TextFormat()
{
}
TextFormat::TextFormat(Font const& font)
{
Update(font);
}
void TextFormat::Update(Font const& font)
{
Renderer::GetInstance()->CreateTextFormat(*this, font);
}
//
// TextLayout
//
TextLayout::TextLayout()
{
}
TextLayout::TextLayout(String const& text, Font const& font, TextStyle const& style)
{
Update(font);
Update(text, style);
}
void TextLayout::Update(Font const& font)
{
text_format_.Update(font);
}
void TextLayout::Update(String const& text, TextStyle const& style)
{
style_ = style;
if (text.empty())
{
text_format_.SetTextFormat(nullptr);
SetTextLayout(nullptr);
return;
}
Renderer::GetInstance()->CreateTextLayout(
*this,
text,
style,
text_format_
);
}
UINT32 TextLayout::GetLineCount()
{
if (text_layout_)
{
DWRITE_TEXT_METRICS metrics;
if (SUCCEEDED(text_layout_->GetMetrics(&metrics)))
{
return metrics.lineCount;
}
}
return 0;
}
Size TextLayout::GetLayoutSize() const
{
if (text_layout_)
{
DWRITE_TEXT_METRICS metrics;
if (SUCCEEDED(text_layout_->GetMetrics(&metrics)))
{
return (metrics.layoutWidth > 0) ? Size(metrics.layoutWidth, metrics.height) : Size(metrics.width, metrics.height);
}
}
return Size();
}
}

View File

@ -0,0 +1,80 @@
// Copyright (c) 2016-2018 Kiwano - 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.
#pragma once
#include "D2DDeviceResources.h"
#include "../2d/Font.hpp"
#include "../2d/TextStyle.hpp"
namespace kiwano
{
// Îı¾¸ñʽ»¯
class KGE_API TextFormat
{
public:
TextFormat();
TextFormat(Font const& font);
void Update(Font const& font);
public:
inline ComPtr<IDWriteTextFormat> GetTextFormat() const { return text_format_; }
inline void SetTextFormat(ComPtr<IDWriteTextFormat> format) { text_format_ = format; }
protected:
ComPtr<IDWriteTextFormat> text_format_;
};
// Îı¾²¼¾Ö
class KGE_API TextLayout
{
public:
TextLayout();
TextLayout(String const& text, Font const& font, TextStyle const& style);
void Update(Font const& font);
void Update(String const& text, TextStyle const& style);
UINT32 GetLineCount();
Size GetLayoutSize() const;
inline TextStyle const& GetTextStyle() const { return style_; }
public:
inline TextFormat GetTextFormat() const { return text_format_; }
inline ComPtr<IDWriteTextLayout> GetTextLayout() const { return text_layout_; }
inline void SetTextLayout(ComPtr<IDWriteTextLayout> layout) { text_layout_ = layout; }
inline operator bool() const { return static_cast<bool>(text_layout_); }
protected:
TextStyle style_;
TextFormat text_format_;
ComPtr<IDWriteTextLayout> text_layout_;
};
}