From ed79c69e7a7089a2bdecde1b7f6d972340b95f46 Mon Sep 17 00:00:00 2001 From: Nomango <569629550@qq.com> Date: Thu, 15 Aug 2019 11:22:51 +0800 Subject: [PATCH] Add TextFormat && TextLayout --- appveyor.yml | 25 ++-- projects/kiwano.vcxproj | 2 + projects/kiwano.vcxproj.filters | 6 + src/kiwano/2d/Actor.cpp | 2 +- src/kiwano/2d/Canvas.cpp | 9 +- src/kiwano/2d/DebugActor.cpp | 3 +- src/kiwano/2d/Text.cpp | 165 +++------------------ src/kiwano/2d/Text.h | 67 ++------- src/kiwano/2d/TextStyle.hpp | 6 +- src/kiwano/base/Director.cpp | 2 + src/kiwano/renderer/D2DDeviceResources.cpp | 117 +++++++-------- src/kiwano/renderer/D2DDeviceResources.h | 8 +- src/kiwano/renderer/Renderer.cpp | 67 ++++++++- src/kiwano/renderer/Renderer.h | 59 +++++--- src/kiwano/renderer/TextLayout.cpp | 110 ++++++++++++++ src/kiwano/renderer/TextLayout.h | 80 ++++++++++ 16 files changed, 408 insertions(+), 320 deletions(-) create mode 100644 src/kiwano/renderer/TextLayout.cpp create mode 100644 src/kiwano/renderer/TextLayout.h diff --git a/appveyor.yml b/appveyor.yml index dc89cd0d..27df39b0 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -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 \ No newline at end of file diff --git a/projects/kiwano.vcxproj b/projects/kiwano.vcxproj index 2931f641..f7b0ef14 100644 --- a/projects/kiwano.vcxproj +++ b/projects/kiwano.vcxproj @@ -77,6 +77,7 @@ + @@ -130,6 +131,7 @@ + diff --git a/projects/kiwano.vcxproj.filters b/projects/kiwano.vcxproj.filters index 1be66a3b..ebebec18 100644 --- a/projects/kiwano.vcxproj.filters +++ b/projects/kiwano.vcxproj.filters @@ -288,6 +288,9 @@ renderer + + renderer + @@ -443,5 +446,8 @@ renderer + + renderer + \ No newline at end of file diff --git a/src/kiwano/2d/Actor.cpp b/src/kiwano/2d/Actor.cpp index 2db554b4..0d2b740d 100644 --- a/src/kiwano/2d/Actor.cpp +++ b/src/kiwano/2d/Actor.cpp @@ -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()) diff --git a/src/kiwano/2d/Canvas.cpp b/src/kiwano/2d/Canvas.cpp index c9f01d1b..61f8950a 100644 --- a/src/kiwano/2d/Canvas.cpp +++ b/src/kiwano/2d/Canvas.cpp @@ -275,21 +275,18 @@ namespace kiwano ThrowIfFailed( Renderer::GetInstance()->GetD2DDeviceResources()->CreateTextFormat( text_format_, - text_font_, - text_style_ + text_font_ ) ); } ComPtr text_layout; - Size layout_size; ThrowIfFailed( Renderer::GetInstance()->GetD2DDeviceResources()->CreateTextLayout( text_layout, - layout_size, text, - text_format_, - text_style_ + text_style_, + text_format_ ) ); diff --git a/src/kiwano/2d/DebugActor.cpp b/src/kiwano/2d/DebugActor.cpp index e7429567..0dbe72d3 100644 --- a/src/kiwano/2d/DebugActor.cpp +++ b/src/kiwano/2d/DebugActor.cpp @@ -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 }); } } diff --git a/src/kiwano/2d/Text.cpp b/src/kiwano/2d/Text.cpp index 84fae7f8..1ea74555 100644 --- a/src/kiwano/2d/Text.cpp +++ b/src/kiwano/2d/Text.cpp @@ -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(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()); + } } } diff --git a/src/kiwano/2d/Text.h b/src/kiwano/2d/Text.h index d2c07ce3..1877b711 100644 --- a/src/kiwano/2d/Text.h +++ b/src/kiwano/2d/Text.h @@ -20,9 +20,7 @@ #pragma once #include "Actor.h" -#include "Font.hpp" -#include "TextStyle.hpp" -#include +#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 text_format_; - mutable ComPtr text_layout_; }; } diff --git a/src/kiwano/2d/TextStyle.hpp b/src/kiwano/2d/TextStyle.hpp index 0cc3c51b..1e5a299d 100644 --- a/src/kiwano/2d/TextStyle.hpp +++ b/src/kiwano/2d/TextStyle.hpp @@ -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) {} }; -} \ No newline at end of file +} diff --git a/src/kiwano/base/Director.cpp b/src/kiwano/base/Director.cpp index 89ee9fe4..39d5d36e 100644 --- a/src/kiwano/base/Director.cpp +++ b/src/kiwano/base/Director.cpp @@ -146,7 +146,9 @@ namespace kiwano if (render_border_enabled_) { if (curr_scene_) + { curr_scene_->RenderBorder(); + } } } diff --git a/src/kiwano/renderer/D2DDeviceResources.cpp b/src/kiwano/renderer/D2DDeviceResources.cpp index e930829a..b94334c2 100644 --- a/src/kiwano/renderer/D2DDeviceResources.cpp +++ b/src/kiwano/renderer/D2DDeviceResources.cpp @@ -51,16 +51,14 @@ namespace kiwano HRESULT CreateTextFormat( _Out_ ComPtr& text_format, - _In_ Font const& font, - _In_ TextStyle const& text_style + _In_ Font const& font ) const override; HRESULT CreateTextLayout( _Out_ ComPtr& text_layout, - _Out_ Size& layout_size, _In_ String const& text, - _In_ ComPtr const& text_format, - _In_ TextStyle const& text_style + _In_ TextStyle const& text_style, + _In_ ComPtr const& text_format ) const override; HRESULT SetD2DDevice( @@ -460,13 +458,12 @@ namespace kiwano return hr; } - HRESULT D2DDeviceResources::CreateTextFormat(_Out_ ComPtr & text_format, - _In_ Font const & font, _In_ TextStyle const & text_style) const + HRESULT D2DDeviceResources::CreateTextFormat(_Out_ ComPtr & text_format, _In_ Font const & font) const { if (!dwrite_factory_) return E_UNEXPECTED; - ComPtr text_format_tmp; + ComPtr 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 & text_layout, - _Out_ Size& layout_size, _In_ String const & text, _In_ ComPtr const& text_format, - _In_ TextStyle const & text_style) const + HRESULT D2DDeviceResources::CreateTextLayout(_Out_ ComPtr & text_layout, _In_ String const & text, + _In_ TextStyle const & text_style, _In_ ComPtr const& text_format) const { if (!dwrite_factory_) return E_UNEXPECTED; - text_layout = nullptr; - HRESULT hr; - ComPtr text_layout_tmp; + ComPtr output; UINT32 length = static_cast(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; } diff --git a/src/kiwano/renderer/D2DDeviceResources.h b/src/kiwano/renderer/D2DDeviceResources.h index f112b3ef..a425f806 100644 --- a/src/kiwano/renderer/D2DDeviceResources.h +++ b/src/kiwano/renderer/D2DDeviceResources.h @@ -48,16 +48,14 @@ namespace kiwano virtual HRESULT CreateTextFormat( _Out_ ComPtr& text_format, - _In_ Font const& font, - _In_ TextStyle const& text_style + _In_ Font const& font ) const = 0; virtual HRESULT CreateTextLayout( _Out_ ComPtr& text_layout, - _Out_ Size& layout_size, _In_ String const& text, - _In_ ComPtr const& text_format, - _In_ TextStyle const& text_style + _In_ TextStyle const& text_style, + _In_ ComPtr const& text_format ) const = 0; virtual ID2D1StrokeStyle* GetStrokeStyle(StrokeStyle stroke) const = 0; diff --git a/src/kiwano/renderer/Renderer.cpp b/src/kiwano/renderer/Renderer.cpp index 77361827..60c365dd 100644 --- a/src/kiwano/renderer/Renderer.cpp +++ b/src/kiwano/renderer/Renderer.cpp @@ -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 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 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 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; } diff --git a/src/kiwano/renderer/Renderer.h b/src/kiwano/renderer/Renderer.h index a365a6cb..aa4b88f0 100644 --- a/src/kiwano/renderer/Renderer.h +++ b/src/kiwano/renderer/Renderer.h @@ -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& 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 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 ); diff --git a/src/kiwano/renderer/TextLayout.cpp b/src/kiwano/renderer/TextLayout.cpp new file mode 100644 index 00000000..a18247d6 --- /dev/null +++ b/src/kiwano/renderer/TextLayout.cpp @@ -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(); + } + +} diff --git a/src/kiwano/renderer/TextLayout.h b/src/kiwano/renderer/TextLayout.h new file mode 100644 index 00000000..a9aebe9c --- /dev/null +++ b/src/kiwano/renderer/TextLayout.h @@ -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 GetTextFormat() const { return text_format_; } + + inline void SetTextFormat(ComPtr format) { text_format_ = format; } + + protected: + ComPtr 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 GetTextLayout() const { return text_layout_; } + + inline void SetTextLayout(ComPtr layout) { text_layout_ = layout; } + + inline operator bool() const { return static_cast(text_layout_); } + + protected: + TextStyle style_; + TextFormat text_format_; + ComPtr text_layout_; + }; +}