Cleanup stuff in #2019
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -11,7 +11,6 @@ Source/*.Gen.*
|
|||||||
Source/*.csproj
|
Source/*.csproj
|
||||||
/Package_*/
|
/Package_*/
|
||||||
!Source/Engine/Debug
|
!Source/Engine/Debug
|
||||||
/Source/Platforms/Editor/Linux/Mono/etc/mono/registry
|
|
||||||
PackageEditor_Cert.command
|
PackageEditor_Cert.command
|
||||||
PackageEditor_Cert.bat
|
PackageEditor_Cert.bat
|
||||||
PackagePlatforms_Cert.bat
|
PackagePlatforms_Cert.bat
|
||||||
@@ -157,4 +156,3 @@ obj/
|
|||||||
.idea/
|
.idea/
|
||||||
*.code-workspace
|
*.code-workspace
|
||||||
omnisharp.json
|
omnisharp.json
|
||||||
Content/Editor/Fonts/NotoSansSC-Regular.flax
|
|
||||||
|
|||||||
BIN
Content/Editor/Fonts/NotoSansSC-Regular.flax
(Stored with Git LFS)
Normal file
BIN
Content/Editor/Fonts/NotoSansSC-Regular.flax
(Stored with Git LFS)
Normal file
Binary file not shown.
@@ -54,7 +54,10 @@ namespace FlaxEditor
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static string PrimaryFont = "Editor/Fonts/Roboto-Regular";
|
public static string PrimaryFont = "Editor/Fonts/Roboto-Regular";
|
||||||
|
|
||||||
public static string CjkFont = "Editor/Fonts/NotoSansSC-Regular";
|
/// <summary>
|
||||||
|
/// The secondary (fallback) font to use for missing characters rendering (CJK - Chinese/Japanese/Korean characters).
|
||||||
|
/// </summary>
|
||||||
|
public static string FallbackFont = "Editor/Fonts/NotoSansSC-Regular";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The Inconsolata Regular font.
|
/// The Inconsolata Regular font.
|
||||||
|
|||||||
@@ -43,9 +43,9 @@ namespace FlaxEditor.GUI
|
|||||||
{
|
{
|
||||||
Depth = -1;
|
Depth = -1;
|
||||||
|
|
||||||
var mediumHeight = Style.Current.FontMedium.GetMaxHeight();
|
var fontHeight = Style.Current.FontMedium.Height;
|
||||||
if (Height < mediumHeight)
|
if (Height < fontHeight)
|
||||||
Height = mediumHeight + 4;
|
Height = fontHeight + 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@@ -36,16 +36,16 @@ namespace FlaxEditor.GUI.Timeline.GUI
|
|||||||
string labelText;
|
string labelText;
|
||||||
switch (_timeline.TimeShowMode)
|
switch (_timeline.TimeShowMode)
|
||||||
{
|
{
|
||||||
case Timeline.TimeShowModes.Frames:
|
case Timeline.TimeShowModes.Frames:
|
||||||
labelText = _timeline.CurrentFrame.ToString("###0", CultureInfo.InvariantCulture);
|
labelText = _timeline.CurrentFrame.ToString("###0", CultureInfo.InvariantCulture);
|
||||||
break;
|
break;
|
||||||
case Timeline.TimeShowModes.Seconds:
|
case Timeline.TimeShowModes.Seconds:
|
||||||
labelText = _timeline.CurrentTime.ToString("###0.##'s'", CultureInfo.InvariantCulture);
|
labelText = _timeline.CurrentTime.ToString("###0.##'s'", CultureInfo.InvariantCulture);
|
||||||
break;
|
break;
|
||||||
case Timeline.TimeShowModes.Time:
|
case Timeline.TimeShowModes.Time:
|
||||||
labelText = TimeSpan.FromSeconds(_timeline.CurrentTime).ToString("g");
|
labelText = TimeSpan.FromSeconds(_timeline.CurrentTime).ToString("g");
|
||||||
break;
|
break;
|
||||||
default: throw new ArgumentOutOfRangeException();
|
default: throw new ArgumentOutOfRangeException();
|
||||||
}
|
}
|
||||||
var color = (_timeline.IsMovingPositionHandle ? style.ProgressNormal : style.Foreground).AlphaMultiplied(0.6f);
|
var color = (_timeline.IsMovingPositionHandle ? style.ProgressNormal : style.Foreground).AlphaMultiplied(0.6f);
|
||||||
Matrix3x3.RotationZ(Mathf.PiOverTwo, out var m1);
|
Matrix3x3.RotationZ(Mathf.PiOverTwo, out var m1);
|
||||||
|
|||||||
@@ -172,9 +172,9 @@ namespace FlaxEditor.Options
|
|||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (value == null)
|
if (value == null)
|
||||||
_outputLogFont = new FontReference(FlaxEngine.Content.LoadAsyncInternal<FontAsset>(EditorAssets.InconsolataRegularFont), 10);
|
_outputLogFont = new FontReference(ConsoleFont, 10);
|
||||||
else if (!value.Font)
|
else if (!value.Font)
|
||||||
_outputLogFont.Font = FlaxEngine.Content.LoadAsyncInternal<FontAsset>(EditorAssets.InconsolataRegularFont);
|
_outputLogFont.Font = ConsoleFont;
|
||||||
else
|
else
|
||||||
_outputLogFont = value;
|
_outputLogFont = value;
|
||||||
}
|
}
|
||||||
@@ -237,8 +237,7 @@ namespace FlaxEditor.Options
|
|||||||
public int NumberOfGameClientsToLaunch = 1;
|
public int NumberOfGameClientsToLaunch = 1;
|
||||||
|
|
||||||
private static FontAsset DefaultFont => FlaxEngine.Content.LoadAsyncInternal<FontAsset>(EditorAssets.PrimaryFont);
|
private static FontAsset DefaultFont => FlaxEngine.Content.LoadAsyncInternal<FontAsset>(EditorAssets.PrimaryFont);
|
||||||
|
private static FontAsset ConsoleFont => FlaxEngine.Content.LoadAsyncInternal<FontAsset>(EditorAssets.InconsolataRegularFont);
|
||||||
private static FontAsset ConsoleFont => FlaxEngine.Content.LoadAsyncInternal<FontAsset>(EditorAssets.PrimaryFont);
|
|
||||||
|
|
||||||
private FontReference _titleFont = new FontReference(DefaultFont, 18);
|
private FontReference _titleFont = new FontReference(DefaultFont, 18);
|
||||||
private FontReference _largeFont = new FontReference(DefaultFont, 14);
|
private FontReference _largeFont = new FontReference(DefaultFont, 14);
|
||||||
@@ -247,9 +246,10 @@ namespace FlaxEditor.Options
|
|||||||
private FontReference _outputLogFont = new FontReference(ConsoleFont, 10);
|
private FontReference _outputLogFont = new FontReference(ConsoleFont, 10);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The fallback fonts.
|
/// The list of fallback fonts to use when main text font is missing certain characters. Empty to use fonts from GraphicsSettings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public FontAsset[] Fallbacks = [FlaxEngine.Content.LoadAsyncInternal<FontAsset>(EditorAssets.CjkFont)];
|
[EditorDisplay("Fonts"), EditorOrder(650)]
|
||||||
|
public FontAsset[] FallbackFonts = [FlaxEngine.Content.LoadAsyncInternal<FontAsset>(EditorAssets.FallbackFont)];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the title font for editor UI.
|
/// Gets or sets the title font for editor UI.
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using FlaxEditor.Content.Settings;
|
using FlaxEditor.Content.Settings;
|
||||||
using FlaxEditor.Modules;
|
using FlaxEditor.Modules;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
@@ -225,11 +226,11 @@ namespace FlaxEditor.Options
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var graphicsSetttings = GameSettings.Load<GraphicsSettings>();
|
// Set fallback fonts
|
||||||
if (graphicsSetttings.EnableFontFallback && graphicsSetttings.FallbackFonts == null)
|
var fallbackFonts = Options.Interface.FallbackFonts;
|
||||||
{
|
if (fallbackFonts == null || fallbackFonts.Length == 0 || fallbackFonts.All(x => x == null))
|
||||||
Render2D.FallbackFonts = graphicsSetttings.FallbackFonts = FontFallbackList.Create(Options.Interface.Fallbacks);
|
fallbackFonts = GameSettings.Load<GraphicsSettings>().FallbackFonts;
|
||||||
}
|
Font.FallbackFonts = fallbackFonts;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -562,12 +562,12 @@ namespace FlaxEditor.Windows
|
|||||||
{
|
{
|
||||||
switch (match.Groups["level"].Value)
|
switch (match.Groups["level"].Value)
|
||||||
{
|
{
|
||||||
case "error":
|
case "error":
|
||||||
textBlock.Style = _output.ErrorStyle;
|
textBlock.Style = _output.ErrorStyle;
|
||||||
break;
|
break;
|
||||||
case "warning":
|
case "warning":
|
||||||
textBlock.Style = _output.WarningStyle;
|
textBlock.Style = _output.WarningStyle;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
textBlock.Tag = new TextBlockTag
|
textBlock.Tag = new TextBlockTag
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -258,13 +258,13 @@ void SplashScreen::OnDraw()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Title
|
// Title
|
||||||
const auto titleLength = _titleFont->MeasureTextInternal(GetTitle());
|
const auto titleLength = _titleFont->MeasureText(GetTitle());
|
||||||
TextLayoutOptions layout;
|
TextLayoutOptions layout;
|
||||||
layout.Bounds = Rectangle(10 * s, 10 * s, width - 10 * s, 50 * s);
|
layout.Bounds = Rectangle(10 * s, 10 * s, width - 10 * s, 50 * s);
|
||||||
layout.HorizontalAlignment = TextAlignment::Near;
|
layout.HorizontalAlignment = TextAlignment::Near;
|
||||||
layout.VerticalAlignment = TextAlignment::Near;
|
layout.VerticalAlignment = TextAlignment::Near;
|
||||||
layout.Scale = Math::Min((width - 20 * s) / titleLength.X, 1.0f);
|
layout.Scale = Math::Min((width - 20 * s) / titleLength.X, 1.0f);
|
||||||
Render2D::DrawTextInternal(_titleFont, GetTitle(), Color::White, layout);
|
Render2D::DrawText(_titleFont, GetTitle(), Color::White, layout);
|
||||||
|
|
||||||
// Subtitle
|
// Subtitle
|
||||||
String subtitle(_quote);
|
String subtitle(_quote);
|
||||||
@@ -279,14 +279,14 @@ void SplashScreen::OnDraw()
|
|||||||
layout.Scale = 1.0f;
|
layout.Scale = 1.0f;
|
||||||
layout.HorizontalAlignment = TextAlignment::Far;
|
layout.HorizontalAlignment = TextAlignment::Far;
|
||||||
layout.VerticalAlignment = TextAlignment::Far;
|
layout.VerticalAlignment = TextAlignment::Far;
|
||||||
Render2D::DrawTextInternal(_subtitleFont, subtitle, Color::FromRGB(0x8C8C8C), layout);
|
Render2D::DrawText(_subtitleFont, subtitle, Color::FromRGB(0x8C8C8C), layout);
|
||||||
|
|
||||||
// Additional info
|
// Additional info
|
||||||
const float infoMargin = 6 * s;
|
const float infoMargin = 6 * s;
|
||||||
layout.Bounds = Rectangle(infoMargin, lightBarHeight + infoMargin, width - (2 * infoMargin), height - lightBarHeight - (2 * infoMargin));
|
layout.Bounds = Rectangle(infoMargin, lightBarHeight + infoMargin, width - (2 * infoMargin), height - lightBarHeight - (2 * infoMargin));
|
||||||
layout.HorizontalAlignment = TextAlignment::Near;
|
layout.HorizontalAlignment = TextAlignment::Near;
|
||||||
layout.VerticalAlignment = TextAlignment::Center;
|
layout.VerticalAlignment = TextAlignment::Center;
|
||||||
Render2D::DrawTextInternal(_subtitleFont, _infoText, Color::FromRGB(0xFFFFFF) * 0.9f, layout);
|
Render2D::DrawText(_subtitleFont, _infoText, Color::FromRGB(0xFFFFFF) * 0.9f, layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SplashScreen::HasLoadedFonts() const
|
bool SplashScreen::HasLoadedFonts() const
|
||||||
|
|||||||
@@ -7,8 +7,6 @@
|
|||||||
#include "Engine/Core/Types/String.h"
|
#include "Engine/Core/Types/String.h"
|
||||||
#include "Engine/Core/Collections/Dictionary.h"
|
#include "Engine/Core/Collections/Dictionary.h"
|
||||||
|
|
||||||
class FontFallbackList;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The main game engine configuration service. Loads and applies game configuration.
|
/// The main game engine configuration service. Loads and applies game configuration.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
#include "Engine/Graphics/Enums.h"
|
#include "Engine/Graphics/Enums.h"
|
||||||
#include "Engine/Graphics/PostProcessSettings.h"
|
#include "Engine/Graphics/PostProcessSettings.h"
|
||||||
|
|
||||||
class FontFallbackList;
|
class FontAsset;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Graphics rendering settings.
|
/// Graphics rendering settings.
|
||||||
@@ -15,6 +15,7 @@ API_CLASS(sealed, Namespace="FlaxEditor.Content.Settings", NoConstructor) class
|
|||||||
{
|
{
|
||||||
API_AUTO_SERIALIZATION();
|
API_AUTO_SERIALIZATION();
|
||||||
DECLARE_SCRIPTING_TYPE_MINIMAL(GraphicsSettings);
|
DECLARE_SCRIPTING_TYPE_MINIMAL(GraphicsSettings);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Enables rendering synchronization with the refresh rate of the display device to avoid "tearing" artifacts.
|
/// Enables rendering synchronization with the refresh rate of the display device to avoid "tearing" artifacts.
|
||||||
@@ -121,16 +122,10 @@ public:
|
|||||||
PostProcessSettings PostProcessSettings;
|
PostProcessSettings PostProcessSettings;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether to enable font fallbacking globally.
|
/// The list of fallback fonts used for text rendering. Ignored if empty.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
API_FIELD(Attributes = "EditorOrder(12000), EditorDisplay(\"Text Render Settings\", EditorDisplayAttribute.InlineStyle)")
|
API_FIELD(Attributes="EditorOrder(5000), EditorDisplay(\"Text\")")
|
||||||
bool EnableFontFallback = true;
|
Array<AssetReference<FontAsset>> FallbackFonts;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The fallback fonts used for text rendering, ignored if null.
|
|
||||||
/// </summary>
|
|
||||||
API_FIELD(Attributes = "EditorOrder(12005), EditorDisplay(\"Text Render Settings\", EditorDisplayAttribute.InlineStyle)")
|
|
||||||
FontFallbackList* FallbackFonts;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#include "Engine/Core/Config/GraphicsSettings.h"
|
#include "Engine/Core/Config/GraphicsSettings.h"
|
||||||
#include "Engine/Engine/CommandLine.h"
|
#include "Engine/Engine/CommandLine.h"
|
||||||
#include "Engine/Engine/EngineService.h"
|
#include "Engine/Engine/EngineService.h"
|
||||||
#include "Engine/Render2D/Render2D.h"
|
#include "Engine/Render2D/Font.h"
|
||||||
|
|
||||||
bool Graphics::UseVSync = false;
|
bool Graphics::UseVSync = false;
|
||||||
Quality Graphics::AAQuality = Quality::Medium;
|
Quality Graphics::AAQuality = Quality::Medium;
|
||||||
@@ -70,9 +70,9 @@ void GraphicsSettings::Apply()
|
|||||||
Graphics::GIQuality = GIQuality;
|
Graphics::GIQuality = GIQuality;
|
||||||
Graphics::PostProcessSettings = ::PostProcessSettings();
|
Graphics::PostProcessSettings = ::PostProcessSettings();
|
||||||
Graphics::PostProcessSettings.BlendWith(PostProcessSettings, 1.0f);
|
Graphics::PostProcessSettings.BlendWith(PostProcessSettings, 1.0f);
|
||||||
|
#if !USE_EDITOR // OptionsModule handles fallback fonts in Editor
|
||||||
Render2D::EnableFontFallback = EnableFontFallback;
|
Font::FallbackFonts = FallbackFonts;
|
||||||
Render2D::FallbackFonts = FallbackFonts;
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::DisposeDevice()
|
void Graphics::DisposeDevice()
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
#include "FallbackFonts.h"
|
|
||||||
#include "FontManager.h"
|
|
||||||
#include "Engine/Core/Math/Math.h"
|
|
||||||
|
|
||||||
FontFallbackList::FontFallbackList(const Array<FontAsset*>& fonts)
|
|
||||||
: ManagedScriptingObject(SpawnParams(Guid::New(), Font::TypeInitializer)),
|
|
||||||
_fontAssets(fonts)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Engine/Core/Collections/Array.h"
|
|
||||||
#include "Engine/Core/Collections/Dictionary.h"
|
|
||||||
#include "Font.h"
|
|
||||||
#include "FontAsset.h"
|
|
||||||
|
|
||||||
struct TextRange;
|
|
||||||
class Font;
|
|
||||||
class FontAsset;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Defines a list of fonts that can be used as a fallback, ordered by priority.
|
|
||||||
/// </summary>
|
|
||||||
API_CLASS(Sealed, NoSpawn) class FLAXENGINE_API FontFallbackList : public ManagedScriptingObject
|
|
||||||
{
|
|
||||||
DECLARE_SCRIPTING_TYPE_NO_SPAWN(FontFallbackList);
|
|
||||||
private:
|
|
||||||
Array<FontAsset*> _fontAssets;
|
|
||||||
|
|
||||||
// Cache fallback fonts of various sizes
|
|
||||||
Dictionary<float, Array<Font*>*> _cache;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="FontFallbackList"/> class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="fonts">The fallback font assets.</param>
|
|
||||||
FontFallbackList(const Array<FontAsset*>& fonts);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="FontFallbackList"/> class, exposed for C#.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="fonts">The fallback font assets.</param>
|
|
||||||
/// <returns>The new instance.</returns>
|
|
||||||
API_FUNCTION() FORCE_INLINE static FontFallbackList* Create(const Array<FontAsset*>& fonts) {
|
|
||||||
return New<FontFallbackList>(fonts);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get the parent assets of fallback fonts.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>The font assets.</returns>
|
|
||||||
API_PROPERTY() FORCE_INLINE Array<FontAsset*>& GetFonts() {
|
|
||||||
return _fontAssets;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Set the fallback fonts.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="val">The parent assets of the new fonts.</param>
|
|
||||||
API_PROPERTY() FORCE_INLINE void SetFonts(const Array<FontAsset*>& val) {
|
|
||||||
_fontAssets = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the fallback fonts with the given size.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="size">The size.</param>
|
|
||||||
/// <returns>The generated fonts.</returns>
|
|
||||||
API_FUNCTION() FORCE_INLINE Array<Font*>& GetFontList(float size) {
|
|
||||||
Array<Font*>* result;
|
|
||||||
if (_cache.TryGet(size, result)) {
|
|
||||||
return *result;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = New<Array<Font*>>(_fontAssets.Count());
|
|
||||||
auto& arr = *result;
|
|
||||||
for (int32 i = 0; i < _fontAssets.Count(); i++)
|
|
||||||
{
|
|
||||||
arr.Add(_fontAssets[i]->CreateFont(size));
|
|
||||||
}
|
|
||||||
|
|
||||||
_cache[size] = result;
|
|
||||||
return *result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the index of the fallback font that should be used to render the char
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="c">The char.</param>
|
|
||||||
/// <param name="primaryFont">The primary font.</param>
|
|
||||||
/// <param name="missing">The number to return if none of the fonts can render.</param>
|
|
||||||
/// <returns>-1 if char can be rendered with primary font, index if it matches a fallback font. </returns>
|
|
||||||
API_FUNCTION() FORCE_INLINE int32 GetCharFallbackIndex(Char c, Font* primaryFont = nullptr, int32 missing = -1) {
|
|
||||||
if (primaryFont && primaryFont->GetAsset()->ContainsChar(c)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32 fontIndex = 0;
|
|
||||||
while (fontIndex < _fontAssets.Count() && _fontAssets[fontIndex] && !_fontAssets[fontIndex]->ContainsChar(c))
|
|
||||||
{
|
|
||||||
fontIndex++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fontIndex < _fontAssets.Count()) {
|
|
||||||
return fontIndex;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return missing;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks if every font is properly loaded.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>True if every font asset is non-null, otherwise false.</returns>
|
|
||||||
API_FUNCTION() FORCE_INLINE bool Verify() {
|
|
||||||
for (int32 i = 0; i < _fontAssets.Count(); i++)
|
|
||||||
{
|
|
||||||
if (!_fontAssets[i]) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -6,7 +6,8 @@
|
|||||||
#include "Engine/Core/Log.h"
|
#include "Engine/Core/Log.h"
|
||||||
#include "Engine/Threading/Threading.h"
|
#include "Engine/Threading/Threading.h"
|
||||||
#include "IncludeFreeType.h"
|
#include "IncludeFreeType.h"
|
||||||
#include "FallbackFonts.h"
|
|
||||||
|
Array<AssetReference<FontAsset>, HeapAllocation> Font::FallbackFonts;
|
||||||
|
|
||||||
Font::Font(FontAsset* parentAsset, float size)
|
Font::Font(FontAsset* parentAsset, float size)
|
||||||
: ManagedScriptingObject(SpawnParams(Guid::New(), Font::TypeInitializer))
|
: ManagedScriptingObject(SpawnParams(Guid::New(), Font::TypeInitializer))
|
||||||
@@ -33,7 +34,7 @@ Font::~Font()
|
|||||||
_asset->_fonts.Remove(this);
|
_asset->_fonts.Remove(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Font::GetCharacter(Char c, FontCharacterEntry& result)
|
void Font::GetCharacter(Char c, FontCharacterEntry& result, bool enableFallback)
|
||||||
{
|
{
|
||||||
// Try to get the character or cache it if cannot be found
|
// Try to get the character or cache it if cannot be found
|
||||||
if (!_characters.TryGet(c, result))
|
if (!_characters.TryGet(c, result))
|
||||||
@@ -45,6 +46,20 @@ void Font::GetCharacter(Char c, FontCharacterEntry& result)
|
|||||||
if (_characters.TryGet(c, result))
|
if (_characters.TryGet(c, result))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Try to use fallback font if character is missing
|
||||||
|
if (enableFallback && !_asset->ContainsChar(c))
|
||||||
|
{
|
||||||
|
for (int32 fallbackIndex = 0; fallbackIndex < FallbackFonts.Count(); fallbackIndex++)
|
||||||
|
{
|
||||||
|
FontAsset* fallbackFont = FallbackFonts.Get()[fallbackIndex].Get();
|
||||||
|
if (fallbackFont && fallbackFont->ContainsChar(c))
|
||||||
|
{
|
||||||
|
fallbackFont->CreateFont(GetSize())->GetCharacter(c, result, enableFallback);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create character cache
|
// Create character cache
|
||||||
FontManager::AddNewEntry(this, c, result);
|
FontManager::AddNewEntry(this, c, result);
|
||||||
|
|
||||||
@@ -88,7 +103,7 @@ void Font::CacheText(const StringView& text)
|
|||||||
FontCharacterEntry entry;
|
FontCharacterEntry entry;
|
||||||
for (int32 i = 0; i < text.Length(); i++)
|
for (int32 i = 0; i < text.Length(); i++)
|
||||||
{
|
{
|
||||||
GetCharacter(text[i], entry);
|
GetCharacter(text[i], entry, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,26 +118,16 @@ void Font::Invalidate()
|
|||||||
_characters.Clear();
|
_characters.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
float Font::GetMaxHeight(FontFallbackList* fallbacks) const
|
|
||||||
{
|
|
||||||
float height = GetHeight();
|
|
||||||
auto& fallbackFonts = fallbacks->GetFontList(GetSize());
|
|
||||||
for (int32 i = 0; i < fallbackFonts.Count(); i++)
|
|
||||||
{
|
|
||||||
height = Math::Max(height, static_cast<float>(fallbackFonts[i]->GetHeight()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return height;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Font::ProcessText(const StringView& text, Array<FontLineCache>& outputLines, const TextLayoutOptions& layout)
|
void Font::ProcessText(const StringView& text, Array<FontLineCache>& outputLines, const TextLayoutOptions& layout)
|
||||||
{
|
{
|
||||||
|
int32 textLength = text.Length();
|
||||||
|
if (textLength == 0)
|
||||||
|
return;
|
||||||
float cursorX = 0;
|
float cursorX = 0;
|
||||||
int32 kerning;
|
int32 kerning;
|
||||||
FontLineCache tmpLine;
|
FontLineCache tmpLine;
|
||||||
FontCharacterEntry entry;
|
FontCharacterEntry entry;
|
||||||
FontCharacterEntry previous;
|
FontCharacterEntry previous;
|
||||||
int32 textLength = text.Length();
|
|
||||||
float scale = layout.Scale / FontManager::FontScale;
|
float scale = layout.Scale / FontManager::FontScale;
|
||||||
float boundsWidth = layout.Bounds.GetWidth();
|
float boundsWidth = layout.Bounds.GetWidth();
|
||||||
float baseLinesDistance = static_cast<float>(_height) * layout.BaseLinesGapScale * scale;
|
float baseLinesDistance = static_cast<float>(_height) * layout.BaseLinesGapScale * scale;
|
||||||
@@ -131,10 +136,6 @@ void Font::ProcessText(const StringView& text, Array<FontLineCache>& outputLines
|
|||||||
tmpLine.FirstCharIndex = 0;
|
tmpLine.FirstCharIndex = 0;
|
||||||
tmpLine.LastCharIndex = -1;
|
tmpLine.LastCharIndex = -1;
|
||||||
|
|
||||||
if (textLength == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32 lastWrapCharIndex = INVALID_INDEX;
|
int32 lastWrapCharIndex = INVALID_INDEX;
|
||||||
float lastWrapCharX = 0;
|
float lastWrapCharX = 0;
|
||||||
bool lastMoveLine = false;
|
bool lastMoveLine = false;
|
||||||
@@ -146,11 +147,6 @@ void Font::ProcessText(const StringView& text, Array<FontLineCache>& outputLines
|
|||||||
float xAdvance = 0;
|
float xAdvance = 0;
|
||||||
int32 nextCharIndex = currentIndex + 1;
|
int32 nextCharIndex = currentIndex + 1;
|
||||||
|
|
||||||
// Submit line if text ends
|
|
||||||
if (nextCharIndex == textLength) {
|
|
||||||
moveLine = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cache current character
|
// Cache current character
|
||||||
const Char currentChar = text[currentIndex];
|
const Char currentChar = text[currentIndex];
|
||||||
const bool isWhitespace = StringUtils::IsWhitespace(currentChar);
|
const bool isWhitespace = StringUtils::IsWhitespace(currentChar);
|
||||||
@@ -168,6 +164,7 @@ void Font::ProcessText(const StringView& text, Array<FontLineCache>& outputLines
|
|||||||
{
|
{
|
||||||
// Break line
|
// Break line
|
||||||
moveLine = true;
|
moveLine = true;
|
||||||
|
currentIndex++;
|
||||||
tmpLine.LastCharIndex++;
|
tmpLine.LastCharIndex++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -178,7 +175,7 @@ void Font::ProcessText(const StringView& text, Array<FontLineCache>& outputLines
|
|||||||
// Get kerning
|
// Get kerning
|
||||||
if (!isWhitespace && previous.IsValid)
|
if (!isWhitespace && previous.IsValid)
|
||||||
{
|
{
|
||||||
kerning = GetKerning(previous.Character, entry.Character);
|
kerning = entry.Font->GetKerning(previous.Character, entry.Character);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -247,8 +244,8 @@ void Font::ProcessText(const StringView& text, Array<FontLineCache>& outputLines
|
|||||||
|
|
||||||
// Reset line
|
// Reset line
|
||||||
tmpLine.Location.Y += baseLinesDistance;
|
tmpLine.Location.Y += baseLinesDistance;
|
||||||
tmpLine.FirstCharIndex = nextCharIndex;
|
tmpLine.FirstCharIndex = currentIndex;
|
||||||
tmpLine.LastCharIndex = nextCharIndex - 1;
|
tmpLine.LastCharIndex = currentIndex - 1;
|
||||||
cursorX = 0;
|
cursorX = 0;
|
||||||
lastWrapCharIndex = INVALID_INDEX;
|
lastWrapCharIndex = INVALID_INDEX;
|
||||||
lastWrapCharX = 0;
|
lastWrapCharX = 0;
|
||||||
@@ -260,7 +257,7 @@ void Font::ProcessText(const StringView& text, Array<FontLineCache>& outputLines
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if an additional line should be created
|
// Check if an additional line should be created
|
||||||
if (text[textLength - 1] == '\n')
|
if (tmpLine.LastCharIndex >= tmpLine.FirstCharIndex || text[textLength - 1] == '\n')
|
||||||
{
|
{
|
||||||
// Add line
|
// Add line
|
||||||
tmpLine.Size.X = cursorX;
|
tmpLine.Size.X = cursorX;
|
||||||
@@ -305,262 +302,7 @@ void Font::ProcessText(const StringView& text, Array<FontLineCache>& outputLines
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Font::ProcessText(FontFallbackList* fallbacks, const StringView& text, Array<BlockedTextLineCache>& outputLines, API_PARAM(Ref) const TextLayoutOptions& layout)
|
Float2 Font::MeasureText(const StringView& text, const TextLayoutOptions& layout)
|
||||||
{
|
|
||||||
const Array<Font*>& fallbackFonts = fallbacks->GetFontList(GetSize());
|
|
||||||
float cursorX = 0;
|
|
||||||
int32 kerning;
|
|
||||||
BlockedTextLineCache tmpLine;
|
|
||||||
FontBlockCache tmpBlock;
|
|
||||||
FontCharacterEntry entry;
|
|
||||||
FontCharacterEntry previous;
|
|
||||||
int32 textLength = text.Length();
|
|
||||||
float scale = layout.Scale / FontManager::FontScale;
|
|
||||||
float boundsWidth = layout.Bounds.GetWidth();
|
|
||||||
float baseLinesDistanceScale = layout.BaseLinesGapScale * scale;
|
|
||||||
|
|
||||||
tmpBlock.Location = Float2::Zero;
|
|
||||||
tmpBlock.Size = Float2::Zero;
|
|
||||||
tmpBlock.FirstCharIndex = 0;
|
|
||||||
tmpBlock.LastCharIndex = -1;
|
|
||||||
|
|
||||||
tmpLine.Location = Float2::Zero;
|
|
||||||
tmpLine.Size = Float2::Zero;
|
|
||||||
tmpLine.Blocks = Array<FontBlockCache>();
|
|
||||||
|
|
||||||
if (textLength == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32 lastWrapCharIndex = INVALID_INDEX;
|
|
||||||
float lastWrapCharX = 0;
|
|
||||||
bool lastMoveLine = false;
|
|
||||||
// The index of the font used by the current block
|
|
||||||
int32 currentFontIndex = fallbacks->GetCharFallbackIndex(text[0], this);
|
|
||||||
// The maximum font height of the current line
|
|
||||||
float maxHeight = 0;
|
|
||||||
float maxAscender = 0;
|
|
||||||
float lastCursorX = 0;
|
|
||||||
|
|
||||||
auto getFont = [&](int32 index)->Font* {
|
|
||||||
return index >= 0 ? fallbackFonts[index] : this;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Process each character to split text into single blocks
|
|
||||||
for (int32 currentIndex = 0; currentIndex < textLength;)
|
|
||||||
{
|
|
||||||
bool moveLine = false;
|
|
||||||
bool moveBlock = false;
|
|
||||||
float xAdvance = 0;
|
|
||||||
int32 nextCharIndex = currentIndex + 1;
|
|
||||||
|
|
||||||
// Submit line and block if text ends
|
|
||||||
if (nextCharIndex == textLength) {
|
|
||||||
moveLine = moveBlock = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cache current character
|
|
||||||
const Char currentChar = text[currentIndex];
|
|
||||||
const bool isWhitespace = StringUtils::IsWhitespace(currentChar);
|
|
||||||
|
|
||||||
// Check if character can wrap words
|
|
||||||
const bool isWrapChar = !StringUtils::IsAlnum(currentChar) || isWhitespace || StringUtils::IsUpper(currentChar) || (currentChar >= 0x3040 && currentChar <= 0x9FFF);
|
|
||||||
if (isWrapChar && currentIndex != 0)
|
|
||||||
{
|
|
||||||
lastWrapCharIndex = currentIndex;
|
|
||||||
lastWrapCharX = cursorX;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32 nextFontIndex = currentFontIndex;
|
|
||||||
// Check if it's a newline character
|
|
||||||
if (currentChar == '\n')
|
|
||||||
{
|
|
||||||
// Break line
|
|
||||||
moveLine = moveBlock = true;
|
|
||||||
tmpBlock.LastCharIndex++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Get character entry
|
|
||||||
if (nextCharIndex < textLength) {
|
|
||||||
nextFontIndex = fallbacks->GetCharFallbackIndex(text[nextCharIndex], this, currentFontIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get character entry
|
|
||||||
getFont(currentFontIndex)->GetCharacter(currentChar, entry);
|
|
||||||
|
|
||||||
maxHeight = Math::Max(maxHeight,
|
|
||||||
static_cast<float>(getFont(currentFontIndex)->GetHeight()));
|
|
||||||
maxAscender = Math::Max(maxAscender,
|
|
||||||
static_cast<float>(getFont(currentFontIndex)->GetAscender()));
|
|
||||||
|
|
||||||
// Move block if the font changes or text ends
|
|
||||||
if (nextFontIndex != currentFontIndex || nextCharIndex == textLength) {
|
|
||||||
moveBlock = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get kerning, only when the font hasn't changed
|
|
||||||
if (!isWhitespace && previous.IsValid && !moveBlock)
|
|
||||||
{
|
|
||||||
kerning = getFont(currentFontIndex)->GetKerning(previous.Character, entry.Character);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
kerning = 0;
|
|
||||||
}
|
|
||||||
previous = entry;
|
|
||||||
xAdvance = (kerning + entry.AdvanceX) * scale;
|
|
||||||
|
|
||||||
// Check if character fits the line or skip wrapping
|
|
||||||
if (cursorX + xAdvance <= boundsWidth || layout.TextWrapping == TextWrapping::NoWrap)
|
|
||||||
{
|
|
||||||
// Move character
|
|
||||||
cursorX += xAdvance;
|
|
||||||
tmpBlock.LastCharIndex++;
|
|
||||||
}
|
|
||||||
else if (layout.TextWrapping == TextWrapping::WrapWords)
|
|
||||||
{
|
|
||||||
if (lastWrapCharIndex != INVALID_INDEX)
|
|
||||||
{
|
|
||||||
// Skip moving twice for the same character
|
|
||||||
int32 lastLineLastCharIndex = outputLines.HasItems() && outputLines.Last().Blocks.HasItems() ? outputLines.Last().Blocks.Last().LastCharIndex : -10000;
|
|
||||||
if (lastLineLastCharIndex == lastWrapCharIndex || lastLineLastCharIndex == lastWrapCharIndex - 1 || lastLineLastCharIndex == lastWrapCharIndex - 2)
|
|
||||||
{
|
|
||||||
currentIndex = nextCharIndex;
|
|
||||||
lastMoveLine = moveLine;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move line
|
|
||||||
const Char wrapChar = text[lastWrapCharIndex];
|
|
||||||
moveLine = true;
|
|
||||||
moveBlock = tmpBlock.FirstCharIndex < lastWrapCharIndex;
|
|
||||||
|
|
||||||
cursorX = lastWrapCharX;
|
|
||||||
if (StringUtils::IsWhitespace(wrapChar))
|
|
||||||
{
|
|
||||||
// Skip whitespaces
|
|
||||||
tmpBlock.LastCharIndex = lastWrapCharIndex - 1;
|
|
||||||
nextCharIndex = currentIndex = lastWrapCharIndex + 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tmpBlock.LastCharIndex = lastWrapCharIndex - 1;
|
|
||||||
nextCharIndex = currentIndex = lastWrapCharIndex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (layout.TextWrapping == TextWrapping::WrapChars)
|
|
||||||
{
|
|
||||||
// Move line
|
|
||||||
moveLine = true;
|
|
||||||
moveBlock = tmpBlock.FirstCharIndex < currentChar;
|
|
||||||
nextCharIndex = currentIndex;
|
|
||||||
|
|
||||||
// Skip moving twice for the same character
|
|
||||||
if (lastMoveLine)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (moveBlock) {
|
|
||||||
// Add block
|
|
||||||
tmpBlock.Size.X = lastCursorX - cursorX;
|
|
||||||
tmpBlock.Size.Y = baseLinesDistanceScale * getFont(currentFontIndex)->GetHeight();
|
|
||||||
tmpBlock.LastCharIndex = Math::Max(tmpBlock.LastCharIndex, tmpBlock.FirstCharIndex);
|
|
||||||
tmpBlock.FallbackFontIndex = currentFontIndex;
|
|
||||||
tmpLine.Blocks.Add(tmpBlock);
|
|
||||||
|
|
||||||
// Reset block
|
|
||||||
tmpBlock.Location.X = cursorX;
|
|
||||||
tmpBlock.FirstCharIndex = nextCharIndex;
|
|
||||||
tmpBlock.LastCharIndex = nextCharIndex - 1;
|
|
||||||
|
|
||||||
currentFontIndex = nextFontIndex;
|
|
||||||
lastCursorX = cursorX;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if move to another line
|
|
||||||
if (moveLine)
|
|
||||||
{
|
|
||||||
// Add line
|
|
||||||
tmpLine.Size.X = cursorX;
|
|
||||||
tmpLine.Size.Y = baseLinesDistanceScale * maxHeight;
|
|
||||||
tmpLine.MaxAscender = maxAscender;
|
|
||||||
outputLines.Add(tmpLine);
|
|
||||||
|
|
||||||
// Reset line
|
|
||||||
tmpLine.Blocks.Clear();
|
|
||||||
tmpLine.Location.Y += baseLinesDistanceScale * maxHeight;
|
|
||||||
cursorX = 0;
|
|
||||||
tmpBlock.Location.X = cursorX;
|
|
||||||
lastWrapCharIndex = INVALID_INDEX;
|
|
||||||
lastWrapCharX = 0;
|
|
||||||
previous.IsValid = false;
|
|
||||||
|
|
||||||
// Reset max font height
|
|
||||||
maxHeight = 0;
|
|
||||||
maxAscender = 0;
|
|
||||||
lastCursorX = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
currentIndex = nextCharIndex;
|
|
||||||
lastMoveLine = moveLine;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if an additional line should be created
|
|
||||||
if (text[textLength - 1] == '\n')
|
|
||||||
{
|
|
||||||
// Add line
|
|
||||||
tmpLine.Size.X = cursorX;
|
|
||||||
tmpLine.Size.Y = baseLinesDistanceScale * maxHeight;
|
|
||||||
outputLines.Add(tmpLine);
|
|
||||||
|
|
||||||
tmpLine.Location.Y += baseLinesDistanceScale * maxHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check amount of lines
|
|
||||||
if (outputLines.IsEmpty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
float totalHeight = tmpLine.Location.Y;
|
|
||||||
|
|
||||||
Float2 offset = Float2::Zero;
|
|
||||||
if (layout.VerticalAlignment == TextAlignment::Center)
|
|
||||||
{
|
|
||||||
offset.Y += (layout.Bounds.GetHeight() - totalHeight) * 0.5f;
|
|
||||||
}
|
|
||||||
else if (layout.VerticalAlignment == TextAlignment::Far)
|
|
||||||
{
|
|
||||||
offset.Y += layout.Bounds.GetHeight() - totalHeight;
|
|
||||||
}
|
|
||||||
for (int32 i = 0; i < outputLines.Count(); i++)
|
|
||||||
{
|
|
||||||
BlockedTextLineCache& line = outputLines[i];
|
|
||||||
Float2 rootPos = line.Location + offset;
|
|
||||||
|
|
||||||
// Fix upper left line corner to match desire text alignment
|
|
||||||
if (layout.HorizontalAlignment == TextAlignment::Center)
|
|
||||||
{
|
|
||||||
rootPos.X += (layout.Bounds.GetWidth() - line.Size.X) * 0.5f;
|
|
||||||
}
|
|
||||||
else if (layout.HorizontalAlignment == TextAlignment::Far)
|
|
||||||
{
|
|
||||||
rootPos.X += layout.Bounds.GetWidth() - line.Size.X;
|
|
||||||
}
|
|
||||||
|
|
||||||
line.Location = rootPos;
|
|
||||||
|
|
||||||
// Align all blocks to center in case they have different heights
|
|
||||||
for (int32 j = 0; j < line.Blocks.Count(); j++)
|
|
||||||
{
|
|
||||||
FontBlockCache& block = line.Blocks[j];
|
|
||||||
block.Location.Y += (line.MaxAscender - getFont(block.FallbackFontIndex)->GetAscender()) / 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Float2 Font::MeasureTextInternal(const StringView& text, const TextLayoutOptions& layout)
|
|
||||||
{
|
{
|
||||||
// Check if there is no need to do anything
|
// Check if there is no need to do anything
|
||||||
if (text.IsEmpty())
|
if (text.IsEmpty())
|
||||||
@@ -581,28 +323,7 @@ Float2 Font::MeasureTextInternal(const StringView& text, const TextLayoutOptions
|
|||||||
return max;
|
return max;
|
||||||
}
|
}
|
||||||
|
|
||||||
Float2 Font::MeasureTextInternal(FontFallbackList* fallbacks, const StringView& text, const TextLayoutOptions& layout)
|
int32 Font::HitTestText(const StringView& text, const Float2& location, const TextLayoutOptions& layout)
|
||||||
{
|
|
||||||
// Check if there is no need to do anything
|
|
||||||
if (text.IsEmpty())
|
|
||||||
return Float2::Zero;
|
|
||||||
|
|
||||||
// Process text
|
|
||||||
Array<BlockedTextLineCache> lines;
|
|
||||||
ProcessText(fallbacks, text, lines, layout);
|
|
||||||
|
|
||||||
// Calculate bounds
|
|
||||||
Float2 max = Float2::Zero;
|
|
||||||
for (int32 i = 0; i < lines.Count(); i++)
|
|
||||||
{
|
|
||||||
const BlockedTextLineCache& line = lines[i];
|
|
||||||
max = Float2::Max(max, line.Location + line.Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
return max;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32 Font::HitTestTextInternal(const StringView& text, const Float2& location, const TextLayoutOptions& layout)
|
|
||||||
{
|
{
|
||||||
// Check if there is no need to do anything
|
// Check if there is no need to do anything
|
||||||
if (text.Length() <= 0)
|
if (text.Length() <= 0)
|
||||||
@@ -639,7 +360,7 @@ int32 Font::HitTestTextInternal(const StringView& text, const Float2& location,
|
|||||||
// Apply kerning
|
// Apply kerning
|
||||||
if (!isWhitespace && previous.IsValid)
|
if (!isWhitespace && previous.IsValid)
|
||||||
{
|
{
|
||||||
x += GetKerning(previous.Character, entry.Character);
|
x += entry.Font->GetKerning(previous.Character, entry.Character);
|
||||||
}
|
}
|
||||||
previous = entry;
|
previous = entry;
|
||||||
|
|
||||||
@@ -676,107 +397,7 @@ int32 Font::HitTestTextInternal(const StringView& text, const Float2& location,
|
|||||||
return smallestIndex;
|
return smallestIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 Font::HitTestTextInternal(FontFallbackList* fallbacks, const StringView& text, const Float2& location, const TextLayoutOptions& layout)
|
Float2 Font::GetCharPosition(const StringView& text, int32 index, const TextLayoutOptions& layout)
|
||||||
{
|
|
||||||
// Check if there is no need to do anything
|
|
||||||
if (text.Length() <= 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
// Process text
|
|
||||||
const Array<Font*>& fallbackFonts = fallbacks->GetFontList(GetSize());
|
|
||||||
Array<BlockedTextLineCache> lines;
|
|
||||||
ProcessText(fallbacks, text, lines, layout);
|
|
||||||
ASSERT(lines.HasItems());
|
|
||||||
float scale = layout.Scale / FontManager::FontScale;
|
|
||||||
|
|
||||||
// Offset position to match lines origin space
|
|
||||||
Float2 rootOffset = layout.Bounds.Location + lines.First().Location;
|
|
||||||
Float2 testPoint = location - rootOffset;
|
|
||||||
|
|
||||||
// Get block which may intersect with the position (it's possible because lines have fixed height)
|
|
||||||
int32 lineIndex = 0;
|
|
||||||
while (lineIndex < lines.Count())
|
|
||||||
{
|
|
||||||
if (lines[lineIndex].Location.Y + lines[lineIndex].Size.Y >= location.Y) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
lineIndex++;
|
|
||||||
}
|
|
||||||
lineIndex = Math::Clamp(lineIndex, 0, lines.Count() - 1);
|
|
||||||
const BlockedTextLineCache& line = lines[lineIndex];
|
|
||||||
|
|
||||||
int32 blockIndex = 0;
|
|
||||||
while (blockIndex < line.Blocks.Count() - 1)
|
|
||||||
{
|
|
||||||
if (line.Location.X + line.Blocks[blockIndex + 1].Location.X >= location.X) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
blockIndex++;
|
|
||||||
}
|
|
||||||
const FontBlockCache& block = line.Blocks[blockIndex];
|
|
||||||
float x = line.Location.X;
|
|
||||||
|
|
||||||
// Check all characters in the line to find hit point
|
|
||||||
FontCharacterEntry previous;
|
|
||||||
FontCharacterEntry entry;
|
|
||||||
int32 smallestIndex = INVALID_INDEX;
|
|
||||||
float dst, smallestDst = MAX_float;
|
|
||||||
|
|
||||||
auto getFont = [&](int32 index)->Font* {
|
|
||||||
return index >= 0 ? fallbackFonts[index] : this;
|
|
||||||
};
|
|
||||||
|
|
||||||
for (int32 currentIndex = block.FirstCharIndex; currentIndex <= block.LastCharIndex; currentIndex++)
|
|
||||||
{
|
|
||||||
// Cache current character
|
|
||||||
const Char currentChar = text[currentIndex];
|
|
||||||
|
|
||||||
getFont(block.FallbackFontIndex)->GetCharacter(currentChar, entry);
|
|
||||||
const bool isWhitespace = StringUtils::IsWhitespace(currentChar);
|
|
||||||
|
|
||||||
// Apply kerning
|
|
||||||
if (!isWhitespace && previous.IsValid)
|
|
||||||
{
|
|
||||||
x += getFont(block.FallbackFontIndex)->GetKerning(previous.Character, entry.Character);
|
|
||||||
}
|
|
||||||
previous = entry;
|
|
||||||
|
|
||||||
// Test
|
|
||||||
dst = Math::Abs(testPoint.X - x);
|
|
||||||
if (dst < smallestDst)
|
|
||||||
{
|
|
||||||
// Found closer character
|
|
||||||
smallestIndex = currentIndex;
|
|
||||||
smallestDst = dst;
|
|
||||||
}
|
|
||||||
else if (dst > smallestDst)
|
|
||||||
{
|
|
||||||
// Current char is worse so return the best result
|
|
||||||
return smallestIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move
|
|
||||||
x += entry.AdvanceX * scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test line end edge
|
|
||||||
dst = Math::Abs(testPoint.X - x);
|
|
||||||
if (dst < smallestDst)
|
|
||||||
{
|
|
||||||
// Pointer is behind the last character in the line
|
|
||||||
smallestIndex = block.LastCharIndex;
|
|
||||||
|
|
||||||
// Fix for last line
|
|
||||||
if (lineIndex == lines.Count() - 1)
|
|
||||||
smallestIndex++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return smallestIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
Float2 Font::GetCharPositionInternal(const StringView& text, int32 index, const TextLayoutOptions& layout)
|
|
||||||
{
|
{
|
||||||
// Check if there is no need to do anything
|
// Check if there is no need to do anything
|
||||||
if (text.IsEmpty())
|
if (text.IsEmpty())
|
||||||
@@ -788,7 +409,7 @@ Float2 Font::GetCharPositionInternal(const StringView& text, int32 index, const
|
|||||||
ASSERT(lines.HasItems());
|
ASSERT(lines.HasItems());
|
||||||
float scale = layout.Scale / FontManager::FontScale;
|
float scale = layout.Scale / FontManager::FontScale;
|
||||||
float baseLinesDistance = static_cast<float>(_height) * layout.BaseLinesGapScale * scale;
|
float baseLinesDistance = static_cast<float>(_height) * layout.BaseLinesGapScale * scale;
|
||||||
Float2 rootOffset = layout.Bounds.Location;
|
Float2 rootOffset = layout.Bounds.Location + lines.First().Location;
|
||||||
|
|
||||||
// Find line with that position
|
// Find line with that position
|
||||||
FontCharacterEntry previous;
|
FontCharacterEntry previous;
|
||||||
@@ -813,7 +434,7 @@ Float2 Font::GetCharPositionInternal(const StringView& text, int32 index, const
|
|||||||
// Apply kerning
|
// Apply kerning
|
||||||
if (!isWhitespace && previous.IsValid)
|
if (!isWhitespace && previous.IsValid)
|
||||||
{
|
{
|
||||||
x += GetKerning(previous.Character, entry.Character);
|
x += entry.Font->GetKerning(previous.Character, entry.Character);
|
||||||
}
|
}
|
||||||
previous = entry;
|
previous = entry;
|
||||||
|
|
||||||
@@ -827,71 +448,7 @@ Float2 Font::GetCharPositionInternal(const StringView& text, int32 index, const
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Position after last character in the last line
|
// Position after last character in the last line
|
||||||
return rootOffset + Float2(lines.Last().Location.X + lines.Last().Size.X, static_cast<float>((lines.Count() - 1) * baseLinesDistance));
|
return rootOffset + Float2(lines.Last().Size.X, static_cast<float>((lines.Count() - 1) * baseLinesDistance));
|
||||||
}
|
|
||||||
|
|
||||||
Float2 Font::GetCharPositionInternal(FontFallbackList* fallbacks, const StringView& text, int32 index, const TextLayoutOptions& layout)
|
|
||||||
{
|
|
||||||
// Check if there is no need to do anything
|
|
||||||
if (text.IsEmpty())
|
|
||||||
return layout.Bounds.Location;
|
|
||||||
|
|
||||||
// Process text
|
|
||||||
const Array<Font*>& fallbackFonts = fallbacks->GetFontList(GetSize());
|
|
||||||
Array<BlockedTextLineCache> lines;
|
|
||||||
ProcessText(fallbacks, text, lines, layout);
|
|
||||||
ASSERT(lines.HasItems());
|
|
||||||
float scale = layout.Scale / FontManager::FontScale;
|
|
||||||
float baseLinesDistance = layout.BaseLinesGapScale * scale;
|
|
||||||
Float2 rootOffset = layout.Bounds.Location;
|
|
||||||
|
|
||||||
// Find line with that position
|
|
||||||
FontCharacterEntry previous;
|
|
||||||
FontCharacterEntry entry;
|
|
||||||
|
|
||||||
auto getFont = [&](int32 index)->Font* {
|
|
||||||
return index >= 0 ? fallbackFonts[index] : this;
|
|
||||||
};
|
|
||||||
|
|
||||||
for (int32 lineIndex = 0; lineIndex < lines.Count(); lineIndex++)
|
|
||||||
{
|
|
||||||
const BlockedTextLineCache& line = lines[lineIndex];
|
|
||||||
for (int32 blockIndex = 0; blockIndex < line.Blocks.Count(); blockIndex++)
|
|
||||||
{
|
|
||||||
const FontBlockCache& block = line.Blocks[blockIndex];
|
|
||||||
// Check if desire position is somewhere inside characters in line range
|
|
||||||
if (Math::IsInRange(index, block.FirstCharIndex, block.LastCharIndex))
|
|
||||||
{
|
|
||||||
float x = line.Location.X + block.Location.X;
|
|
||||||
float y = line.Location.Y + block.Location.Y;
|
|
||||||
|
|
||||||
// Check all characters in the line
|
|
||||||
for (int32 currentIndex = block.FirstCharIndex; currentIndex < index; currentIndex++)
|
|
||||||
{
|
|
||||||
// Cache current character
|
|
||||||
const Char currentChar = text[currentIndex];
|
|
||||||
getFont(block.FallbackFontIndex)->GetCharacter(currentChar, entry);
|
|
||||||
const bool isWhitespace = StringUtils::IsWhitespace(currentChar);
|
|
||||||
|
|
||||||
// Apply kerning
|
|
||||||
if (!isWhitespace && previous.IsValid)
|
|
||||||
{
|
|
||||||
x += getFont(block.FallbackFontIndex)->GetKerning(previous.Character, entry.Character);
|
|
||||||
}
|
|
||||||
previous = entry;
|
|
||||||
|
|
||||||
// Move
|
|
||||||
x += entry.AdvanceX * scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Upper left corner of the character
|
|
||||||
return rootOffset + Float2(x, y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Position after last character in the last line
|
|
||||||
return rootOffset + Float2(lines.Last().Location.X + lines.Last().Size.X, lines.Last().Location.Y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Font::FlushFaceSize() const
|
void Font::FlushFaceSize() const
|
||||||
|
|||||||
@@ -8,12 +8,9 @@
|
|||||||
#include "Engine/Content/AssetReference.h"
|
#include "Engine/Content/AssetReference.h"
|
||||||
#include "Engine/Scripting/ScriptingObject.h"
|
#include "Engine/Scripting/ScriptingObject.h"
|
||||||
#include "TextLayoutOptions.h"
|
#include "TextLayoutOptions.h"
|
||||||
#include "Render2D.h"
|
|
||||||
|
|
||||||
class FontAsset;
|
class FontAsset;
|
||||||
class FontFallbackList;
|
|
||||||
struct FontTextureAtlasSlot;
|
struct FontTextureAtlasSlot;
|
||||||
struct BlockedTextLineCache;
|
|
||||||
|
|
||||||
// The default DPI that engine is using
|
// The default DPI that engine is using
|
||||||
#define DefaultDPI 96
|
#define DefaultDPI 96
|
||||||
@@ -38,7 +35,7 @@ API_STRUCT(NoDefault) struct TextRange
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the range length.
|
/// Gets the range length.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
int32 Length() const
|
FORCE_INLINE int32 Length() const
|
||||||
{
|
{
|
||||||
return EndIndex - StartIndex;
|
return EndIndex - StartIndex;
|
||||||
}
|
}
|
||||||
@@ -46,7 +43,7 @@ API_STRUCT(NoDefault) struct TextRange
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a value indicating whether range is empty.
|
/// Gets a value indicating whether range is empty.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
bool IsEmpty() const
|
FORCE_INLINE bool IsEmpty() const
|
||||||
{
|
{
|
||||||
return (EndIndex - StartIndex) <= 0;
|
return (EndIndex - StartIndex) <= 0;
|
||||||
}
|
}
|
||||||
@@ -56,7 +53,7 @@ API_STRUCT(NoDefault) struct TextRange
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="index">The index.</param>
|
/// <param name="index">The index.</param>
|
||||||
/// <returns><c>true</c> if range contains the specified character index; otherwise, <c>false</c>.</returns>
|
/// <returns><c>true</c> if range contains the specified character index; otherwise, <c>false</c>.</returns>
|
||||||
bool Contains(int32 index) const
|
FORCE_INLINE bool Contains(int32 index) const
|
||||||
{
|
{
|
||||||
return index >= StartIndex && index < EndIndex;
|
return index >= StartIndex && index < EndIndex;
|
||||||
}
|
}
|
||||||
@@ -122,74 +119,6 @@ struct TIsPODType<FontLineCache>
|
|||||||
enum { Value = true };
|
enum { Value = true };
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The font block info generated during text processing.
|
|
||||||
/// A block means a range of text that belongs to the same line and can be rendered with the same font.
|
|
||||||
/// </summary>
|
|
||||||
API_STRUCT(NoDefault) struct FontBlockCache
|
|
||||||
{
|
|
||||||
DECLARE_SCRIPTING_TYPE_MINIMAL(FontBlockCache);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The root position of the block (upper left corner), relative to line.
|
|
||||||
/// </summary>
|
|
||||||
API_FIELD() Float2 Location;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The size of the current block
|
|
||||||
/// </summary>
|
|
||||||
API_FIELD() Float2 Size;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The first character index (from the input text).
|
|
||||||
/// </summary>
|
|
||||||
API_FIELD() int32 FirstCharIndex;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The last character index (from the input text), inclusive.
|
|
||||||
/// </summary>
|
|
||||||
API_FIELD() int32 LastCharIndex;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Indicates the fallback font to render this block with, -1 if doesn't require fallback.
|
|
||||||
/// </summary>
|
|
||||||
API_FIELD() int32 FallbackFontIndex;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct TIsPODType<FontBlockCache>
|
|
||||||
{
|
|
||||||
enum { Value = true };
|
|
||||||
};
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Line of font blocks info generated during text processing.
|
|
||||||
/// </summary>
|
|
||||||
API_STRUCT(NoDefault) struct BlockedTextLineCache
|
|
||||||
{
|
|
||||||
DECLARE_SCRIPTING_TYPE_MINIMAL(BlockedTextLineCache);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The root position of the line (upper left corner).
|
|
||||||
/// </summary>
|
|
||||||
API_FIELD() Float2 Location;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The line bounds (width and height).
|
|
||||||
/// </summary>
|
|
||||||
API_FIELD() Float2 Size;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The maximum ascender of the line.
|
|
||||||
/// </summary>
|
|
||||||
API_FIELD() float MaxAscender;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The blocks that belongs to this line
|
|
||||||
/// </summary>
|
|
||||||
API_FIELD() Array<FontBlockCache> Blocks;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Font glyph metrics:
|
// Font glyph metrics:
|
||||||
//
|
//
|
||||||
// xmin xmax
|
// xmin xmax
|
||||||
@@ -281,6 +210,11 @@ API_STRUCT(NoDefault) struct FontCharacterEntry
|
|||||||
/// The slot in texture atlas, containing the pixel data of the glyph.
|
/// The slot in texture atlas, containing the pixel data of the glyph.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
API_FIELD() const FontTextureAtlasSlot* Slot;
|
API_FIELD() const FontTextureAtlasSlot* Slot;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The owner font.
|
||||||
|
/// </summary>
|
||||||
|
API_FIELD() const class Font* Font;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
@@ -296,8 +230,8 @@ API_CLASS(Sealed, NoSpawn) class FLAXENGINE_API Font : public ManagedScriptingOb
|
|||||||
{
|
{
|
||||||
DECLARE_SCRIPTING_TYPE_NO_SPAWN(Font);
|
DECLARE_SCRIPTING_TYPE_NO_SPAWN(Font);
|
||||||
friend FontAsset;
|
friend FontAsset;
|
||||||
private:
|
|
||||||
|
|
||||||
|
private:
|
||||||
FontAsset* _asset;
|
FontAsset* _asset;
|
||||||
float _size;
|
float _size;
|
||||||
int32 _height;
|
int32 _height;
|
||||||
@@ -309,7 +243,6 @@ private:
|
|||||||
mutable Dictionary<uint32, int32> _kerningTable;
|
mutable Dictionary<uint32, int32> _kerningTable;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="Font"/> class.
|
/// Initializes a new instance of the <see cref="Font"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -323,6 +256,10 @@ public:
|
|||||||
~Font();
|
~Font();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/// <summary>
|
||||||
|
/// The active fallback fonts.
|
||||||
|
/// </summary>
|
||||||
|
API_FIELD() static Array<AssetReference<FontAsset>, HeapAllocation> FallbackFonts;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets parent font asset that contains font family used by this font.
|
/// Gets parent font asset that contains font family used by this font.
|
||||||
@@ -373,13 +310,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets character entry.
|
/// Gets character entry.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="c">The character.</param>
|
/// <param name="c">The character.</param>
|
||||||
/// <param name="result">The output character entry.</param>
|
/// <param name="result">The output character entry.</param>
|
||||||
void GetCharacter(Char c, FontCharacterEntry& result);
|
/// <param name="enableFallback">True if fallback to secondary font when the primary font doesn't contains this character.</param>
|
||||||
|
void GetCharacter(Char c, FontCharacterEntry& result, bool enableFallback = true);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the kerning amount for a pair of characters.
|
/// Gets the kerning amount for a pair of characters.
|
||||||
@@ -401,33 +338,8 @@ public:
|
|||||||
API_FUNCTION() void Invalidate();
|
API_FUNCTION() void Invalidate();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the maximum height among the font and the fallback fonts.
|
/// Processes text to get cached lines for rendering.
|
||||||
/// </summary>
|
|
||||||
/// <param name="fallbacks">The fallback fonts.</param>
|
|
||||||
/// <returns>The maximum height.</returns>
|
|
||||||
API_FUNCTION() float GetMaxHeight(FontFallbackList* fallbacks) const;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the maximum height among the font and the fallback fonts, uses the default font defined in <see cref="Render2D"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="fallbacks">The fallback fonts.</param>
|
|
||||||
/// <returns>The maximum height.</returns>
|
|
||||||
API_FUNCTION() FORCE_INLINE float GetMaxHeight() const
|
|
||||||
{
|
|
||||||
if (Render2D::EnableFontFallback && Render2D::FallbackFonts)
|
|
||||||
{
|
|
||||||
return GetMaxHeight(Render2D::FallbackFonts);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return GetHeight();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Processes text to get cached lines for rendering, with font fallbacking disabled.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="text">The input text.</param>
|
/// <param name="text">The input text.</param>
|
||||||
/// <param name="layout">The layout properties.</param>
|
/// <param name="layout">The layout properties.</param>
|
||||||
@@ -435,12 +347,12 @@ public:
|
|||||||
void ProcessText(const StringView& text, Array<FontLineCache>& outputLines, API_PARAM(Ref) const TextLayoutOptions& layout);
|
void ProcessText(const StringView& text, Array<FontLineCache>& outputLines, API_PARAM(Ref) const TextLayoutOptions& layout);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Processes text to get cached lines for rendering, with font fallbacking disabled.
|
/// Processes text to get cached lines for rendering.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="text">The input text.</param>
|
/// <param name="text">The input text.</param>
|
||||||
/// <param name="layout">The layout properties.</param>
|
/// <param name="layout">The layout properties.</param>
|
||||||
/// <returns>The output lines list.</returns>
|
/// <returns>The output lines list.</returns>
|
||||||
API_FUNCTION() FORCE_INLINE Array<FontLineCache> ProcessText(const StringView& text, API_PARAM(Ref) const TextLayoutOptions& layout)
|
API_FUNCTION() Array<FontLineCache> ProcessText(const StringView& text, API_PARAM(Ref) const TextLayoutOptions& layout)
|
||||||
{
|
{
|
||||||
Array<FontLineCache> lines;
|
Array<FontLineCache> lines;
|
||||||
ProcessText(text, lines, layout);
|
ProcessText(text, lines, layout);
|
||||||
@@ -448,13 +360,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Processes text to get cached lines for rendering, with font fallbacking disabled.
|
/// Processes text to get cached lines for rendering.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="text">The input text.</param>
|
/// <param name="text">The input text.</param>
|
||||||
/// <param name="textRange">The input text range (substring range of the input text parameter).</param>
|
/// <param name="textRange">The input text range (substring range of the input text parameter).</param>
|
||||||
/// <param name="layout">The layout properties.</param>
|
/// <param name="layout">The layout properties.</param>
|
||||||
/// <returns>The output lines list.</returns>
|
/// <returns>The output lines list.</returns>
|
||||||
API_FUNCTION() FORCE_INLINE Array<FontLineCache> ProcessText(const StringView& text, API_PARAM(Ref) const TextRange& textRange, API_PARAM(Ref) const TextLayoutOptions& layout)
|
API_FUNCTION() Array<FontLineCache> ProcessText(const StringView& text, API_PARAM(Ref) const TextRange& textRange, API_PARAM(Ref) const TextLayoutOptions& layout)
|
||||||
{
|
{
|
||||||
Array<FontLineCache> lines;
|
Array<FontLineCache> lines;
|
||||||
ProcessText(textRange.Substring(text), lines, layout);
|
ProcessText(textRange.Substring(text), lines, layout);
|
||||||
@@ -462,7 +374,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Processes text to get cached lines for rendering, with font fallbacking disabled.
|
/// Processes text to get cached lines for rendering.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="text">The input text.</param>
|
/// <param name="text">The input text.</param>
|
||||||
/// <returns>The output lines list.</returns>
|
/// <returns>The output lines list.</returns>
|
||||||
@@ -472,7 +384,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Processes text to get cached lines for rendering, with font fallbacking disabled.
|
/// Processes text to get cached lines for rendering.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="text">The input text.</param>
|
/// <param name="text">The input text.</param>
|
||||||
/// <param name="textRange">The input text range (substring range of the input text parameter).</param>
|
/// <param name="textRange">The input text range (substring range of the input text parameter).</param>
|
||||||
@@ -483,349 +395,81 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Processes text to get cached lines for rendering, using custom fallback options.
|
/// Measures minimum size of the rectangle that will be needed to draw given text.
|
||||||
/// </summary>
|
|
||||||
/// <param name="text">The input text.</param>
|
|
||||||
/// <param name="layout">The layout properties.</param>
|
|
||||||
/// <param name="outputLines">The output lines list.</param>
|
|
||||||
void ProcessText(FontFallbackList* fallbacks, const StringView& text, Array<BlockedTextLineCache>& outputLines, API_PARAM(Ref) const TextLayoutOptions& layout);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Processes text to get cached lines for rendering, using custom fallback options.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="text">The input text.</param>
|
|
||||||
/// <param name="layout">The layout properties.</param>
|
|
||||||
/// <returns>The output lines list.</returns>
|
|
||||||
API_FUNCTION() FORCE_INLINE Array<BlockedTextLineCache> ProcessText(FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextLayoutOptions& layout)
|
|
||||||
{
|
|
||||||
Array<BlockedTextLineCache> lines;
|
|
||||||
ProcessText(fallbacks, text, lines, layout);
|
|
||||||
return lines;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Processes text to get cached lines for rendering, using custom fallback options.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="text">The input text.</param>
|
|
||||||
/// <param name="textRange">The input text range (substring range of the input text parameter).</param>
|
|
||||||
/// <param name="layout">The layout properties.</param>
|
|
||||||
/// <returns>The output lines list.</returns>
|
|
||||||
API_FUNCTION() FORCE_INLINE Array<BlockedTextLineCache> ProcessText(FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, API_PARAM(Ref) const TextLayoutOptions& layout)
|
|
||||||
{
|
|
||||||
Array<BlockedTextLineCache> lines;
|
|
||||||
ProcessText(fallbacks, textRange.Substring(text), lines, layout);
|
|
||||||
return lines;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Processes text to get cached lines for rendering, using custom fallback options.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="text">The input text.</param>
|
|
||||||
/// <returns>The output lines list.</returns>
|
|
||||||
API_FUNCTION() FORCE_INLINE Array<BlockedTextLineCache> ProcessText(FontFallbackList* fallbacks, const StringView& text)
|
|
||||||
{
|
|
||||||
return ProcessText(fallbacks, text, TextLayoutOptions());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Processes text to get cached lines for rendering, using custom fallback options.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="text">The input text.</param>
|
|
||||||
/// <param name="textRange">The input text range (substring range of the input text parameter).</param>
|
|
||||||
/// <returns>The output lines list.</returns>
|
|
||||||
API_FUNCTION() FORCE_INLINE Array<BlockedTextLineCache> ProcessText(FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange)
|
|
||||||
{
|
|
||||||
return ProcessText(fallbacks, textRange.Substring(text), TextLayoutOptions());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Measures minimum size of the rectangle that will be needed to draw given text, with font fallbacking disabled.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="text">The input text to test.</param>
|
/// <param name="text">The input text to test.</param>
|
||||||
/// <param name="layout">The layout properties.</param>
|
/// <param name="layout">The layout properties.</param>
|
||||||
/// <returns>The minimum size for that text and fot to render properly.</returns>
|
/// <returns>The minimum size for that text and fot to render properly.</returns>
|
||||||
API_FUNCTION() Float2 MeasureTextInternal(const StringView& text, API_PARAM(Ref) const TextLayoutOptions& layout);
|
API_FUNCTION() Float2 MeasureText(const StringView& text, API_PARAM(Ref) const TextLayoutOptions& layout);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Measures minimum size of the rectangle that will be needed to draw given text, with font fallbacking disabled.
|
/// Measures minimum size of the rectangle that will be needed to draw given text.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="text">The input text to test.</param>
|
/// <param name="text">The input text to test.</param>
|
||||||
/// <param name="textRange">The input text range (substring range of the input text parameter).</param>
|
/// <param name="textRange">The input text range (substring range of the input text parameter).</param>
|
||||||
/// <param name="layout">The layout properties.</param>
|
/// <param name="layout">The layout properties.</param>
|
||||||
/// <returns>The minimum size for that text and fot to render properly.</returns>
|
/// <returns>The minimum size for that text and fot to render properly.</returns>
|
||||||
API_FUNCTION() FORCE_INLINE Float2 MeasureTextInternal(const StringView& text, API_PARAM(Ref) const TextRange& textRange, API_PARAM(Ref) const TextLayoutOptions& layout)
|
API_FUNCTION() Float2 MeasureText(const StringView& text, API_PARAM(Ref) const TextRange& textRange, API_PARAM(Ref) const TextLayoutOptions& layout)
|
||||||
{
|
{
|
||||||
return MeasureTextInternal(textRange.Substring(text), layout);
|
return MeasureText(textRange.Substring(text), layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Measures minimum size of the rectangle that will be needed to draw given text, with font fallbacking disabled.
|
/// Measures minimum size of the rectangle that will be needed to draw given text
|
||||||
/// </summary>.
|
|
||||||
/// <param name="text">The input text to test.</param>
|
|
||||||
/// <returns>The minimum size for that text and fot to render properly.</returns>
|
|
||||||
API_FUNCTION() FORCE_INLINE Float2 MeasureTextInternal(const StringView& text)
|
|
||||||
{
|
|
||||||
return MeasureTextInternal(text, TextLayoutOptions());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Measures minimum size of the rectangle that will be needed to draw given text, with font fallbacking disabled.
|
|
||||||
/// </summary>.
|
|
||||||
/// <param name="text">The input text to test.</param>
|
|
||||||
/// <param name="textRange">The input text range (substring range of the input text parameter).</param>
|
|
||||||
/// <returns>The minimum size for that text and fot to render properly.</returns>
|
|
||||||
API_FUNCTION() FORCE_INLINE Float2 MeasureTextInternal(const StringView& text, API_PARAM(Ref) const TextRange& textRange)
|
|
||||||
{
|
|
||||||
return MeasureTextInternal(textRange.Substring(text), TextLayoutOptions());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Measures minimum size of the rectangle that will be needed to draw given text, using custom fallback options.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="text">The input text to test.</param>
|
|
||||||
/// <param name="layout">The layout properties.</param>
|
|
||||||
/// <returns>The minimum size for that text and fot to render properly.</returns>
|
|
||||||
API_FUNCTION() Float2 MeasureTextInternal(FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextLayoutOptions& layout);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Measures minimum size of the rectangle that will be needed to draw given text, using custom fallback options.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="text">The input text to test.</param>
|
|
||||||
/// <param name="textRange">The input text range (substring range of the input text parameter).</param>
|
|
||||||
/// <param name="layout">The layout properties.</param>
|
|
||||||
/// <returns>The minimum size for that text and fot to render properly.</returns>
|
|
||||||
API_FUNCTION() FORCE_INLINE Float2 MeasureTextInternal(FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, API_PARAM(Ref) const TextLayoutOptions& layout)
|
|
||||||
{
|
|
||||||
return MeasureTextInternal(fallbacks, textRange.Substring(text), layout);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Measures minimum size of the rectangle that will be needed to draw given text, using custom fallback options.
|
|
||||||
/// </summary>.
|
|
||||||
/// <param name="text">The input text to test.</param>
|
|
||||||
/// <returns>The minimum size for that text and fot to render properly.</returns>
|
|
||||||
API_FUNCTION() FORCE_INLINE Float2 MeasureTextInternal(FontFallbackList* fallbacks, const StringView& text)
|
|
||||||
{
|
|
||||||
return MeasureTextInternal(fallbacks, text, TextLayoutOptions());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Measures minimum size of the rectangle that will be needed to draw given text, using custom fallback options.
|
|
||||||
/// </summary>.
|
|
||||||
/// <param name="text">The input text to test.</param>
|
|
||||||
/// <param name="textRange">The input text range (substring range of the input text parameter).</param>
|
|
||||||
/// <returns>The minimum size for that text and fot to render properly.</returns>
|
|
||||||
API_FUNCTION() FORCE_INLINE Float2 MeasureTextInternal(FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange)
|
|
||||||
{
|
|
||||||
return MeasureTextInternal(fallbacks, textRange.Substring(text), TextLayoutOptions());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Measures minimum size of the rectangle that will be needed to draw given text, follows the fallback settings defined in <see cref="Render2D" />.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="text">The input text to test.</param>
|
|
||||||
/// <param name="layout">The layout properties.</param>
|
|
||||||
/// <returns>The minimum size for that text and fot to render properly.</returns>
|
|
||||||
API_FUNCTION() FORCE_INLINE Float2 MeasureText(const StringView& text, API_PARAM(Ref) const TextLayoutOptions& layout) {
|
|
||||||
if (Render2D::EnableFontFallback && Render2D::FallbackFonts) {
|
|
||||||
return MeasureTextInternal(Render2D::FallbackFonts, text, layout);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return MeasureTextInternal(text, layout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Measures minimum size of the rectangle that will be needed to draw given text, follows the fallback settings defined in <see cref="Render2D" />.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="text">The input text to test.</param>
|
|
||||||
/// <param name="textRange">The input text range (substring range of the input text parameter).</param>
|
|
||||||
/// <param name="layout">The layout properties.</param>
|
|
||||||
/// <returns>The minimum size for that text and fot to render properly.</returns>
|
|
||||||
API_FUNCTION() FORCE_INLINE Float2 MeasureText(const StringView& text, API_PARAM(Ref) const TextRange& textRange, API_PARAM(Ref) const TextLayoutOptions& layout)
|
|
||||||
{
|
|
||||||
if (Render2D::EnableFontFallback && Render2D::FallbackFonts) {
|
|
||||||
return MeasureTextInternal(Render2D::FallbackFonts, textRange.Substring(text), layout);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return MeasureTextInternal(textRange.Substring(text), layout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Measures minimum size of the rectangle that will be needed to draw given text, follows the fallback settings defined in <see cref="Render2D" />.
|
|
||||||
/// </summary>.
|
/// </summary>.
|
||||||
/// <param name="text">The input text to test.</param>
|
/// <param name="text">The input text to test.</param>
|
||||||
/// <returns>The minimum size for that text and fot to render properly.</returns>
|
/// <returns>The minimum size for that text and fot to render properly.</returns>
|
||||||
API_FUNCTION() FORCE_INLINE Float2 MeasureText(const StringView& text)
|
API_FUNCTION() FORCE_INLINE Float2 MeasureText(const StringView& text)
|
||||||
{
|
{
|
||||||
if (Render2D::EnableFontFallback && Render2D::FallbackFonts) {
|
return MeasureText(text, TextLayoutOptions());
|
||||||
return MeasureTextInternal(Render2D::FallbackFonts, text, TextLayoutOptions());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return MeasureTextInternal(text, TextLayoutOptions());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Measures minimum size of the rectangle that will be needed to draw given text, follows the fallback settings defined in <see cref="Render2D" />.
|
/// Measures minimum size of the rectangle that will be needed to draw given text
|
||||||
/// </summary>.
|
/// </summary>.
|
||||||
/// <param name="text">The input text to test.</param>
|
/// <param name="text">The input text to test.</param>
|
||||||
/// <param name="textRange">The input text range (substring range of the input text parameter).</param>
|
/// <param name="textRange">The input text range (substring range of the input text parameter).</param>
|
||||||
/// <returns>The minimum size for that text and fot to render properly.</returns>
|
/// <returns>The minimum size for that text and fot to render properly.</returns>
|
||||||
API_FUNCTION() FORCE_INLINE Float2 MeasureText(const StringView& text, API_PARAM(Ref) const TextRange& textRange)
|
API_FUNCTION() FORCE_INLINE Float2 MeasureText(const StringView& text, API_PARAM(Ref) const TextRange& textRange)
|
||||||
{
|
{
|
||||||
if (Render2D::EnableFontFallback && Render2D::FallbackFonts) {
|
return MeasureText(textRange.Substring(text), TextLayoutOptions());
|
||||||
return MeasureTextInternal(Render2D::FallbackFonts, textRange.Substring(text), TextLayoutOptions());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return MeasureTextInternal(textRange.Substring(text), TextLayoutOptions());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calculates hit character index at given location, with font fallbacking disabled.
|
/// Calculates hit character index at given location.
|
||||||
/// </summary>
|
|
||||||
/// <param name="text">The input text to test.</param>
|
|
||||||
/// <param name="location">The input location to test.</param>
|
|
||||||
/// <param name="layout">The text layout properties.</param>
|
|
||||||
/// <returns>The selected character position index (can be equal to text length if location is outside of the layout rectangle).</returns>
|
|
||||||
API_FUNCTION() int32 HitTestTextInternal(const StringView& text, const Float2& location, API_PARAM(Ref) const TextLayoutOptions& layout);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Calculates hit character index at given location, with font fallbacking disabled.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="text">The input text to test.</param>
|
/// <param name="text">The input text to test.</param>
|
||||||
/// <param name="textRange">The input text range (substring range of the input text parameter).</param>
|
/// <param name="textRange">The input text range (substring range of the input text parameter).</param>
|
||||||
/// <param name="location">The input location to test.</param>
|
/// <param name="location">The input location to test.</param>
|
||||||
/// <param name="layout">The text layout properties.</param>
|
/// <param name="layout">The text layout properties.</param>
|
||||||
/// <returns>The selected character position index (can be equal to text length if location is outside of the layout rectangle).</returns>
|
/// <returns>The selected character position index (can be equal to text length if location is outside of the layout rectangle).</returns>
|
||||||
API_FUNCTION() FORCE_INLINE int32 HitTestTextInternal(const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Float2& location, API_PARAM(Ref) const TextLayoutOptions& layout)
|
API_FUNCTION() int32 HitTestText(const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Float2& location, API_PARAM(Ref) const TextLayoutOptions& layout)
|
||||||
{
|
{
|
||||||
return HitTestTextInternal(textRange.Substring(text), location, layout);
|
return HitTestText(textRange.Substring(text), location, layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calculates hit character index at given location, with font fallbacking disabled.
|
/// Calculates hit character index at given location.
|
||||||
/// </summary>
|
|
||||||
/// <param name="text">The input text to test.</param>
|
|
||||||
/// <param name="location">The input location to test.</param>
|
|
||||||
/// <returns>The selected character position index (can be equal to text length if location is outside of the layout rectangle).</returns>
|
|
||||||
API_FUNCTION() FORCE_INLINE int32 HitTestTextInternal(const StringView& text, const Float2& location)
|
|
||||||
{
|
|
||||||
return HitTestTextInternal(text, location, TextLayoutOptions());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Calculates hit character index at given location, with font fallbacking disabled.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="text">The input text to test.</param>
|
|
||||||
/// <param name="textRange">The input text range (substring range of the input text parameter).</param>
|
|
||||||
/// <param name="location">The input location to test.</param>
|
|
||||||
/// <returns>The selected character position index (can be equal to text length if location is outside of the layout rectangle).</returns>
|
|
||||||
API_FUNCTION() FORCE_INLINE int32 HitTestTextInternal(const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Float2& location)
|
|
||||||
{
|
|
||||||
return HitTestTextInternal(textRange.Substring(text), location, TextLayoutOptions());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Calculates hit character index at given location, using custom fallback options.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="text">The input text to test.</param>
|
/// <param name="text">The input text to test.</param>
|
||||||
/// <param name="location">The input location to test.</param>
|
/// <param name="location">The input location to test.</param>
|
||||||
/// <param name="layout">The text layout properties.</param>
|
/// <param name="layout">The text layout properties.</param>
|
||||||
/// <returns>The selected character position index (can be equal to text length if location is outside of the layout rectangle).</returns>
|
/// <returns>The selected character position index (can be equal to text length if location is outside of the layout rectangle).</returns>
|
||||||
API_FUNCTION() int32 HitTestTextInternal(FontFallbackList* fallbacks, const StringView& text, const Float2& location, API_PARAM(Ref) const TextLayoutOptions& layout);
|
API_FUNCTION() int32 HitTestText(const StringView& text, const Float2& location, API_PARAM(Ref) const TextLayoutOptions& layout);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calculates hit character index at given location, using custom fallback options.
|
/// Calculates hit character index at given location.
|
||||||
/// </summary>
|
|
||||||
/// <param name="text">The input text to test.</param>
|
|
||||||
/// <param name="textRange">The input text range (substring range of the input text parameter).</param>
|
|
||||||
/// <param name="location">The input location to test.</param>
|
|
||||||
/// <param name="layout">The text layout properties.</param>
|
|
||||||
/// <returns>The selected character position index (can be equal to text length if location is outside of the layout rectangle).</returns>
|
|
||||||
API_FUNCTION() FORCE_INLINE int32 HitTestTextInternal(FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Float2& location, API_PARAM(Ref) const TextLayoutOptions& layout)
|
|
||||||
{
|
|
||||||
return HitTestTextInternal(fallbacks, textRange.Substring(text), location, layout);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Calculates hit character index at given location, using custom fallback options.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="text">The input text to test.</param>
|
|
||||||
/// <param name="location">The input location to test.</param>
|
|
||||||
/// <returns>The selected character position index (can be equal to text length if location is outside of the layout rectangle).</returns>
|
|
||||||
API_FUNCTION() FORCE_INLINE int32 HitTestTextInternal(FontFallbackList* fallbacks, const StringView& text, const Float2& location)
|
|
||||||
{
|
|
||||||
return HitTestTextInternal(fallbacks, text, location, TextLayoutOptions());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Calculates hit character index at given location, using custom fallback options.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="text">The input text to test.</param>
|
|
||||||
/// <param name="textRange">The input text range (substring range of the input text parameter).</param>
|
|
||||||
/// <param name="location">The input location to test.</param>
|
|
||||||
/// <returns>The selected character position index (can be equal to text length if location is outside of the layout rectangle).</returns>
|
|
||||||
API_FUNCTION() FORCE_INLINE int32 HitTestTextInternal(FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Float2& location)
|
|
||||||
{
|
|
||||||
return HitTestTextInternal(fallbacks, textRange.Substring(text), location, TextLayoutOptions());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Calculates hit character index at given location, follows the fallback settings defined in <see cref="Render2D" />.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="text">The input text to test.</param>
|
|
||||||
/// <param name="location">The input location to test.</param>
|
|
||||||
/// <param name="layout">The text layout properties.</param>
|
|
||||||
/// <returns>The selected character position index (can be equal to text length if location is outside of the layout rectangle).</returns>
|
|
||||||
API_FUNCTION() FORCE_INLINE int32 HitTestText(const StringView& text, const Float2& location, API_PARAM(Ref) const TextLayoutOptions& layout) {
|
|
||||||
if (Render2D::EnableFontFallback && Render2D::FallbackFonts) {
|
|
||||||
return HitTestTextInternal(Render2D::FallbackFonts, text, location, layout);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return HitTestTextInternal(text, location, layout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Calculates hit character index at given location, follows the fallback settings defined in <see cref="Render2D" />.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="text">The input text to test.</param>
|
|
||||||
/// <param name="textRange">The input text range (substring range of the input text parameter).</param>
|
|
||||||
/// <param name="location">The input location to test.</param>
|
|
||||||
/// <param name="layout">The text layout properties.</param>
|
|
||||||
/// <returns>The selected character position index (can be equal to text length if location is outside of the layout rectangle).</returns>
|
|
||||||
API_FUNCTION() FORCE_INLINE int32 HitTestText(const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Float2& location, API_PARAM(Ref) const TextLayoutOptions& layout)
|
|
||||||
{
|
|
||||||
if (Render2D::EnableFontFallback && Render2D::FallbackFonts) {
|
|
||||||
return HitTestTextInternal(Render2D::FallbackFonts, textRange.Substring(text), location, layout);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return HitTestTextInternal(textRange.Substring(text), location, layout);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Calculates hit character index at given location, follows the fallback settings defined in <see cref="Render2D" />.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="text">The input text to test.</param>
|
/// <param name="text">The input text to test.</param>
|
||||||
/// <param name="location">The input location to test.</param>
|
/// <param name="location">The input location to test.</param>
|
||||||
/// <returns>The selected character position index (can be equal to text length if location is outside of the layout rectangle).</returns>
|
/// <returns>The selected character position index (can be equal to text length if location is outside of the layout rectangle).</returns>
|
||||||
API_FUNCTION() FORCE_INLINE int32 HitTestText(const StringView& text, const Float2& location)
|
API_FUNCTION() FORCE_INLINE int32 HitTestText(const StringView& text, const Float2& location)
|
||||||
{
|
{
|
||||||
if (Render2D::EnableFontFallback && Render2D::FallbackFonts) {
|
return HitTestText(text, location, TextLayoutOptions());
|
||||||
return HitTestTextInternal(Render2D::FallbackFonts, text, location, TextLayoutOptions());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return HitTestTextInternal(text, location, TextLayoutOptions());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calculates hit character index at given location, follows the fallback settings defined in <see cref="Render2D" />.
|
/// Calculates hit character index at given location.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="text">The input text to test.</param>
|
/// <param name="text">The input text to test.</param>
|
||||||
/// <param name="textRange">The input text range (substring range of the input text parameter).</param>
|
/// <param name="textRange">The input text range (substring range of the input text parameter).</param>
|
||||||
@@ -833,156 +477,44 @@ public:
|
|||||||
/// <returns>The selected character position index (can be equal to text length if location is outside of the layout rectangle).</returns>
|
/// <returns>The selected character position index (can be equal to text length if location is outside of the layout rectangle).</returns>
|
||||||
API_FUNCTION() FORCE_INLINE int32 HitTestText(const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Float2& location)
|
API_FUNCTION() FORCE_INLINE int32 HitTestText(const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Float2& location)
|
||||||
{
|
{
|
||||||
if (Render2D::EnableFontFallback && Render2D::FallbackFonts) {
|
return HitTestText(textRange.Substring(text), location, TextLayoutOptions());
|
||||||
return HitTestTextInternal(Render2D::FallbackFonts, textRange.Substring(text), location, TextLayoutOptions());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return HitTestTextInternal(textRange.Substring(text), location, TextLayoutOptions());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calculates character position for given text and character index, with font fallbacking disabled.
|
/// Calculates character position for given text and character index.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="text">The input text to test.</param>
|
/// <param name="text">The input text to test.</param>
|
||||||
/// <param name="index">The text position to get coordinates of.</param>
|
/// <param name="index">The text position to get coordinates of.</param>
|
||||||
/// <param name="layout">The text layout properties.</param>
|
/// <param name="layout">The text layout properties.</param>
|
||||||
/// <returns>The character position (upper left corner which can be used for a caret position).</returns>
|
/// <returns>The character position (upper left corner which can be used for a caret position).</returns>
|
||||||
API_FUNCTION() Float2 GetCharPositionInternal(const StringView& text, int32 index, API_PARAM(Ref) const TextLayoutOptions& layout);
|
API_FUNCTION() Float2 GetCharPosition(const StringView& text, int32 index, API_PARAM(Ref) const TextLayoutOptions& layout);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calculates character position for given text and character index, with font fallbacking disabled.
|
/// Calculates character position for given text and character index.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="text">The input text to test.</param>
|
/// <param name="text">The input text to test.</param>
|
||||||
/// <param name="textRange">The input text range (substring range of the input text parameter).</param>
|
/// <param name="textRange">The input text range (substring range of the input text parameter).</param>
|
||||||
/// <param name="index">The text position to get coordinates of.</param>
|
/// <param name="index">The text position to get coordinates of.</param>
|
||||||
/// <param name="layout">The text layout properties.</param>
|
/// <param name="layout">The text layout properties.</param>
|
||||||
/// <returns>The character position (upper left corner which can be used for a caret position).</returns>
|
/// <returns>The character position (upper left corner which can be used for a caret position).</returns>
|
||||||
API_FUNCTION() FORCE_INLINE Float2 GetCharPositionInternal(const StringView& text, API_PARAM(Ref) const TextRange& textRange, int32 index, API_PARAM(Ref) const TextLayoutOptions& layout)
|
API_FUNCTION() Float2 GetCharPosition(const StringView& text, API_PARAM(Ref) const TextRange& textRange, int32 index, API_PARAM(Ref) const TextLayoutOptions& layout)
|
||||||
{
|
{
|
||||||
return GetCharPositionInternal(textRange.Substring(text), index, layout);
|
return GetCharPosition(textRange.Substring(text), index, layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calculates character position for given text and character index, with font fallbacking disabled.
|
/// Calculates character position for given text and character index
|
||||||
/// </summary>
|
|
||||||
/// <param name="text">The input text to test.</param>
|
|
||||||
/// <param name="index">The text position to get coordinates of.</param>
|
|
||||||
/// <returns>The character position (upper left corner which can be used for a caret position).</returns>
|
|
||||||
API_FUNCTION() FORCE_INLINE Float2 GetCharPositionInternal(const StringView& text, int32 index)
|
|
||||||
{
|
|
||||||
return GetCharPositionInternal(text, index, TextLayoutOptions());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Calculates character position for given text and character index, with font fallbacking disabled.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="text">The input text to test.</param>
|
|
||||||
/// <param name="textRange">The input text range (substring range of the input text parameter).</param>
|
|
||||||
/// <param name="index">The text position to get coordinates of.</param>
|
|
||||||
/// <returns>The character position (upper left corner which can be used for a caret position).</returns>
|
|
||||||
API_FUNCTION() FORCE_INLINE Float2 GetCharPositionInternal(const StringView& text, API_PARAM(Ref) const TextRange& textRange, int32 index)
|
|
||||||
{
|
|
||||||
return GetCharPositionInternal(textRange.Substring(text), index, TextLayoutOptions());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Calculates character position for given text and character index, using custom fallback options.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="text">The input text to test.</param>
|
|
||||||
/// <param name="index">The text position to get coordinates of.</param>
|
|
||||||
/// <param name="layout">The text layout properties.</param>
|
|
||||||
/// <returns>The character position (upper left corner which can be used for a caret position).</returns>
|
|
||||||
API_FUNCTION() Float2 GetCharPositionInternal(FontFallbackList* fallbacks, const StringView& text, int32 index, API_PARAM(Ref) const TextLayoutOptions& layout);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Calculates character position for given text and character index, using custom fallback options.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="text">The input text to test.</param>
|
|
||||||
/// <param name="textRange">The input text range (substring range of the input text parameter).</param>
|
|
||||||
/// <param name="index">The text position to get coordinates of.</param>
|
|
||||||
/// <param name="layout">The text layout properties.</param>
|
|
||||||
/// <returns>The character position (upper left corner which can be used for a caret position).</returns>
|
|
||||||
API_FUNCTION() FORCE_INLINE Float2 GetCharPositionInternal(FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, int32 index, API_PARAM(Ref) const TextLayoutOptions& layout)
|
|
||||||
{
|
|
||||||
return GetCharPositionInternal(fallbacks, textRange.Substring(text), index, layout);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Calculates character position for given text and character index, using custom fallback options.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="text">The input text to test.</param>
|
|
||||||
/// <param name="index">The text position to get coordinates of.</param>
|
|
||||||
/// <returns>The character position (upper left corner which can be used for a caret position).</returns>
|
|
||||||
API_FUNCTION() FORCE_INLINE Float2 GetCharPositionInternal(FontFallbackList* fallbacks, const StringView& text, int32 index)
|
|
||||||
{
|
|
||||||
return GetCharPositionInternal(fallbacks, text, index, TextLayoutOptions());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Calculates character position for given text and character index, using custom fallback options.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="text">The input text to test.</param>
|
|
||||||
/// <param name="textRange">The input text range (substring range of the input text parameter).</param>
|
|
||||||
/// <param name="index">The text position to get coordinates of.</param>
|
|
||||||
/// <returns>The character position (upper left corner which can be used for a caret position).</returns>
|
|
||||||
API_FUNCTION() FORCE_INLINE Float2 GetCharPositionInternal(FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, int32 index)
|
|
||||||
{
|
|
||||||
return GetCharPositionInternal(fallbacks, textRange.Substring(text), index, TextLayoutOptions());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Calculates character position for given text and character index, follows the fallback settings defined in <see cref="Render2D" />.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="text">The input text to test.</param>
|
|
||||||
/// <param name="index">The text position to get coordinates of.</param>
|
|
||||||
/// <param name="layout">The text layout properties.</param>
|
|
||||||
/// <returns>The character position (upper left corner which can be used for a caret position).</returns>
|
|
||||||
API_FUNCTION() FORCE_INLINE Float2 GetCharPosition(const StringView& text, int32 index, API_PARAM(Ref) const TextLayoutOptions& layout) {
|
|
||||||
if (Render2D::EnableFontFallback && Render2D::FallbackFonts) {
|
|
||||||
return GetCharPositionInternal(Render2D::FallbackFonts, text, index, layout);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return GetCharPositionInternal(text, index, layout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Calculates character position for given text and character index, follows the fallback settings defined in <see cref="Render2D" />.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="text">The input text to test.</param>
|
|
||||||
/// <param name="textRange">The input text range (substring range of the input text parameter).</param>
|
|
||||||
/// <param name="index">The text position to get coordinates of.</param>
|
|
||||||
/// <param name="layout">The text layout properties.</param>
|
|
||||||
/// <returns>The character position (upper left corner which can be used for a caret position).</returns>
|
|
||||||
API_FUNCTION() FORCE_INLINE Float2 GetCharPosition(const StringView& text, API_PARAM(Ref) const TextRange& textRange, int32 index, API_PARAM(Ref) const TextLayoutOptions& layout)
|
|
||||||
{
|
|
||||||
if (Render2D::EnableFontFallback && Render2D::FallbackFonts) {
|
|
||||||
return GetCharPositionInternal(Render2D::FallbackFonts, textRange.Substring(text), index, layout);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return GetCharPositionInternal(textRange.Substring(text), index, layout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Calculates character position for given text and character index, follows the fallback settings defined in <see cref="Render2D" />.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="text">The input text to test.</param>
|
/// <param name="text">The input text to test.</param>
|
||||||
/// <param name="index">The text position to get coordinates of.</param>
|
/// <param name="index">The text position to get coordinates of.</param>
|
||||||
/// <returns>The character position (upper left corner which can be used for a caret position).</returns>
|
/// <returns>The character position (upper left corner which can be used for a caret position).</returns>
|
||||||
API_FUNCTION() FORCE_INLINE Float2 GetCharPosition(const StringView& text, int32 index)
|
API_FUNCTION() FORCE_INLINE Float2 GetCharPosition(const StringView& text, int32 index)
|
||||||
{
|
{
|
||||||
if (Render2D::EnableFontFallback && Render2D::FallbackFonts) {
|
return GetCharPosition(text, index, TextLayoutOptions());
|
||||||
return GetCharPositionInternal(Render2D::FallbackFonts, text, index, TextLayoutOptions());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return GetCharPositionInternal(text, index, TextLayoutOptions());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calculates character position for given text and character index, follows the fallback settings defined in <see cref="Render2D" />.
|
/// Calculates character position for given text and character index
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="text">The input text to test.</param>
|
/// <param name="text">The input text to test.</param>
|
||||||
/// <param name="textRange">The input text range (substring range of the input text parameter).</param>
|
/// <param name="textRange">The input text range (substring range of the input text parameter).</param>
|
||||||
@@ -990,12 +522,7 @@ public:
|
|||||||
/// <returns>The character position (upper left corner which can be used for a caret position).</returns>
|
/// <returns>The character position (upper left corner which can be used for a caret position).</returns>
|
||||||
API_FUNCTION() FORCE_INLINE Float2 GetCharPosition(const StringView& text, API_PARAM(Ref) const TextRange& textRange, int32 index)
|
API_FUNCTION() FORCE_INLINE Float2 GetCharPosition(const StringView& text, API_PARAM(Ref) const TextRange& textRange, int32 index)
|
||||||
{
|
{
|
||||||
if (Render2D::EnableFontFallback && Render2D::FallbackFonts) {
|
return GetCharPosition(textRange.Substring(text), index, TextLayoutOptions());
|
||||||
return GetCharPositionInternal(Render2D::FallbackFonts, textRange.Substring(text), index, TextLayoutOptions());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return GetCharPositionInternal(textRange.Substring(text), index, TextLayoutOptions());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -1004,7 +531,6 @@ public:
|
|||||||
void FlushFaceSize() const;
|
void FlushFaceSize() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// [Object]
|
// [Object]
|
||||||
String ToString() const override;
|
String ToString() const override;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -199,25 +199,29 @@ bool FontAsset::Save(const StringView& path)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool FontAsset::ContainsChar(Char c) const
|
||||||
/// <summary>
|
{
|
||||||
/// Check if the font contains the glyph of a char
|
return FT_Get_Char_Index(_face, c) > 0;
|
||||||
/// </summary>
|
|
||||||
/// <param name="c">The char to test.</param>
|
|
||||||
/// <returns>True if the font contains the glyph of the char, otherwise false.</returns>
|
|
||||||
|
|
||||||
bool FontAsset::ContainsChar(Char c) const {
|
|
||||||
return FT_Get_Char_Index(GetFTFace(), c) > 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FontAsset::Invalidate()
|
void FontAsset::Invalidate()
|
||||||
{
|
{
|
||||||
ScopeLock lock(Locker);
|
ScopeLock lock(Locker);
|
||||||
|
|
||||||
for (auto font : _fonts)
|
for (auto font : _fonts)
|
||||||
{
|
|
||||||
font->Invalidate();
|
font->Invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64 FontAsset::GetMemoryUsage() const
|
||||||
|
{
|
||||||
|
Locker.Lock();
|
||||||
|
uint64 result = BinaryAsset::GetMemoryUsage();
|
||||||
|
result += sizeof(FontAsset) - sizeof(BinaryAsset);
|
||||||
|
result += sizeof(FT_FaceRec);
|
||||||
|
result += _fontFile.Length();
|
||||||
|
for (auto font : _fonts)
|
||||||
|
result += sizeof(Font);
|
||||||
|
Locker.Unlock();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FontAsset::init(AssetInitData& initData)
|
bool FontAsset::init(AssetInitData& initData)
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ API_CLASS(NoSpawn) class FLAXENGINE_API FontAsset : public BinaryAsset
|
|||||||
{
|
{
|
||||||
DECLARE_BINARY_ASSET_HEADER(FontAsset, 3);
|
DECLARE_BINARY_ASSET_HEADER(FontAsset, 3);
|
||||||
friend Font;
|
friend Font;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FT_Face _face;
|
FT_Face _face;
|
||||||
FontOptions _options;
|
FontOptions _options;
|
||||||
@@ -175,7 +176,7 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Check if the font contains the glyph of a char
|
/// Check if the font contains the glyph of a char.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="c">The char to test.</param>
|
/// <param name="c">The char to test.</param>
|
||||||
/// <returns>True if the font contains the glyph of the char, otherwise false.</returns>
|
/// <returns>True if the font contains the glyph of the char, otherwise false.</returns>
|
||||||
@@ -186,6 +187,10 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
API_FUNCTION() void Invalidate();
|
API_FUNCTION() void Invalidate();
|
||||||
|
|
||||||
|
public:
|
||||||
|
// [BinaryAsset]
|
||||||
|
uint64 GetMemoryUsage() const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// [BinaryAsset]
|
// [BinaryAsset]
|
||||||
bool init(AssetInitData& initData) override;
|
bool init(AssetInitData& initData) override;
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ using namespace FontManagerImpl;
|
|||||||
class FontManagerService : public EngineService
|
class FontManagerService : public EngineService
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
FontManagerService()
|
FontManagerService()
|
||||||
: EngineService(TEXT("Font Manager"), -700)
|
: EngineService(TEXT("Font Manager"), -700)
|
||||||
{
|
{
|
||||||
@@ -155,9 +154,12 @@ bool FontManager::AddNewEntry(Font* font, Char c, FontCharacterEntry& entry)
|
|||||||
|
|
||||||
// Get the index to the glyph in the font face
|
// Get the index to the glyph in the font face
|
||||||
const FT_UInt glyphIndex = FT_Get_Char_Index(face, c);
|
const FT_UInt glyphIndex = FT_Get_Char_Index(face, c);
|
||||||
if (glyphIndex == 0) {
|
#if !BUILD_RELEASE
|
||||||
|
if (glyphIndex == 0)
|
||||||
|
{
|
||||||
LOG(Warning, "Font `{}` doesn't contain character `\\u{:x}`, consider choosing another font. ", String(face->family_name), c);
|
LOG(Warning, "Font `{}` doesn't contain character `\\u{:x}`, consider choosing another font. ", String(face->family_name), c);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Load the glyph
|
// Load the glyph
|
||||||
const FT_Error error = FT_Load_Glyph(face, glyphIndex, glyphFlags);
|
const FT_Error error = FT_Load_Glyph(face, glyphIndex, glyphFlags);
|
||||||
@@ -287,6 +289,7 @@ bool FontManager::AddNewEntry(Font* font, Char c, FontCharacterEntry& entry)
|
|||||||
entry.UVSize.X = static_cast<float>(slot->Width - 2 * padding);
|
entry.UVSize.X = static_cast<float>(slot->Width - 2 * padding);
|
||||||
entry.UVSize.Y = static_cast<float>(slot->Height - 2 * padding);
|
entry.UVSize.Y = static_cast<float>(slot->Height - 2 * padding);
|
||||||
entry.Slot = slot;
|
entry.Slot = slot;
|
||||||
|
entry.Font = font;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
#include "Render2D.h"
|
#include "Render2D.h"
|
||||||
#include "Font.h"
|
#include "Font.h"
|
||||||
#include "FontManager.h"
|
#include "FontManager.h"
|
||||||
#include "FallbackFonts.h"
|
|
||||||
#include "FontTextureAtlas.h"
|
#include "FontTextureAtlas.h"
|
||||||
#include "RotatedRectangle.h"
|
#include "RotatedRectangle.h"
|
||||||
#include "SpriteAtlas.h"
|
#include "SpriteAtlas.h"
|
||||||
@@ -55,7 +54,7 @@ const bool DownsampleForBlur = false;
|
|||||||
|
|
||||||
PACK_STRUCT(struct Data {
|
PACK_STRUCT(struct Data {
|
||||||
Matrix ViewProjection;
|
Matrix ViewProjection;
|
||||||
});
|
});
|
||||||
|
|
||||||
PACK_STRUCT(struct BlurData {
|
PACK_STRUCT(struct BlurData {
|
||||||
Float2 InvBufferSize;
|
Float2 InvBufferSize;
|
||||||
@@ -63,7 +62,7 @@ PACK_STRUCT(struct BlurData {
|
|||||||
float Dummy0;
|
float Dummy0;
|
||||||
Float4 Bounds;
|
Float4 Bounds;
|
||||||
Float4 WeightAndOffsets[RENDER2D_BLUR_MAX_SAMPLES / 2];
|
Float4 WeightAndOffsets[RENDER2D_BLUR_MAX_SAMPLES / 2];
|
||||||
});
|
});
|
||||||
|
|
||||||
enum class DrawCallType : byte
|
enum class DrawCallType : byte
|
||||||
{
|
{
|
||||||
@@ -181,9 +180,7 @@ struct ClipMask
|
|||||||
Rectangle Bounds;
|
Rectangle Bounds;
|
||||||
};
|
};
|
||||||
|
|
||||||
Render2D::RenderingFeatures Render2D::Features = RenderingFeatures::VertexSnapping;
|
Render2D::RenderingFeatures Render2D::Features = RenderingFeatures::VertexSnapping | RenderingFeatures::FallbackFonts;
|
||||||
bool Render2D::EnableFontFallback = true;
|
|
||||||
FontFallbackList* Render2D::FallbackFonts = nullptr;
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
@@ -197,7 +194,6 @@ namespace
|
|||||||
// Drawing
|
// Drawing
|
||||||
Array<Render2DDrawCall> DrawCalls;
|
Array<Render2DDrawCall> DrawCalls;
|
||||||
Array<FontLineCache> Lines;
|
Array<FontLineCache> Lines;
|
||||||
Array<BlockedTextLineCache> BlockedTextLines;
|
|
||||||
Array<Float2> Lines2;
|
Array<Float2> Lines2;
|
||||||
bool IsScissorsRectEmpty;
|
bool IsScissorsRectEmpty;
|
||||||
bool IsScissorsRectEnabled;
|
bool IsScissorsRectEnabled;
|
||||||
@@ -1141,12 +1137,12 @@ void DrawBatch(int32 startIndex, int32 count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Draw
|
// Draw
|
||||||
Context->BindVB(ToSpan(&vb, 1)); // TODO: reduce bindings frequency
|
Context->BindVB(ToSpan(&vb, 1));
|
||||||
Context->BindIB(ib); // TODO: reduce bindings frequency
|
Context->BindIB(ib);
|
||||||
Context->DrawIndexed(countIb, 0, d.StartIB);
|
Context->DrawIndexed(countIb, 0, d.StartIB);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Render2D::DrawTextInternal(Font* font, const StringView& text, const Color& color, const Float2& location, MaterialBase* customMaterial)
|
void Render2D::DrawText(Font* font, const StringView& text, const Color& color, const Float2& location, MaterialBase* customMaterial)
|
||||||
{
|
{
|
||||||
RENDER2D_CHECK_RENDERING_STATE;
|
RENDER2D_CHECK_RENDERING_STATE;
|
||||||
|
|
||||||
@@ -1163,6 +1159,7 @@ void Render2D::DrawTextInternal(Font* font, const StringView& text, const Color&
|
|||||||
FontCharacterEntry previous;
|
FontCharacterEntry previous;
|
||||||
int32 kerning;
|
int32 kerning;
|
||||||
float scale = 1.0f / FontManager::FontScale;
|
float scale = 1.0f / FontManager::FontScale;
|
||||||
|
const bool enableFallbackFonts = EnumHasAllFlags(Features, RenderingFeatures::FallbackFonts);
|
||||||
|
|
||||||
// Render all characters
|
// Render all characters
|
||||||
FontCharacterEntry entry;
|
FontCharacterEntry entry;
|
||||||
@@ -1178,7 +1175,7 @@ void Render2D::DrawTextInternal(Font* font, const StringView& text, const Color&
|
|||||||
drawCall.AsChar.Mat = nullptr;
|
drawCall.AsChar.Mat = nullptr;
|
||||||
}
|
}
|
||||||
Float2 pointer = location;
|
Float2 pointer = location;
|
||||||
for (int32 currentIndex = 0; currentIndex < text.Length(); currentIndex++)
|
for (int32 currentIndex = 0; currentIndex <= text.Length(); currentIndex++)
|
||||||
{
|
{
|
||||||
// Cache current character
|
// Cache current character
|
||||||
const Char currentChar = text[currentIndex];
|
const Char currentChar = text[currentIndex];
|
||||||
@@ -1187,7 +1184,7 @@ void Render2D::DrawTextInternal(Font* font, const StringView& text, const Color&
|
|||||||
if (currentChar != '\n')
|
if (currentChar != '\n')
|
||||||
{
|
{
|
||||||
// Get character entry
|
// Get character entry
|
||||||
font->GetCharacter(currentChar, entry);
|
font->GetCharacter(currentChar, entry, enableFallbackFonts);
|
||||||
|
|
||||||
// Check if need to select/change font atlas (since characters even in the same font may be located in different atlases)
|
// Check if need to select/change font atlas (since characters even in the same font may be located in different atlases)
|
||||||
if (fontAtlas == nullptr || entry.TextureIndex != fontAtlasIndex)
|
if (fontAtlas == nullptr || entry.TextureIndex != fontAtlasIndex)
|
||||||
@@ -1214,7 +1211,7 @@ void Render2D::DrawTextInternal(Font* font, const StringView& text, const Color&
|
|||||||
// Get kerning
|
// Get kerning
|
||||||
if (!isWhitespace && previous.IsValid)
|
if (!isWhitespace && previous.IsValid)
|
||||||
{
|
{
|
||||||
kerning = font->GetKerning(previous.Character, entry.Character);
|
kerning = entry.Font->GetKerning(previous.Character, entry.Character);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1254,12 +1251,12 @@ void Render2D::DrawTextInternal(Font* font, const StringView& text, const Color&
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Render2D::DrawTextInternal(Font* font, const StringView& text, const TextRange& textRange, const Color& color, const Float2& location, MaterialBase* customMaterial)
|
void Render2D::DrawText(Font* font, const StringView& text, const TextRange& textRange, const Color& color, const Float2& location, MaterialBase* customMaterial)
|
||||||
{
|
{
|
||||||
DrawTextInternal(font, textRange.Substring(text), color, location, customMaterial);
|
DrawText(font, textRange.Substring(text), color, location, customMaterial);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Render2D::DrawTextInternal(Font* font, const StringView& text, const Color& color, const TextLayoutOptions& layout, MaterialBase* customMaterial)
|
void Render2D::DrawText(Font* font, const StringView& text, const Color& color, const TextLayoutOptions& layout, MaterialBase* customMaterial)
|
||||||
{
|
{
|
||||||
RENDER2D_CHECK_RENDERING_STATE;
|
RENDER2D_CHECK_RENDERING_STATE;
|
||||||
|
|
||||||
@@ -1277,6 +1274,7 @@ void Render2D::DrawTextInternal(Font* font, const StringView& text, const Color&
|
|||||||
FontCharacterEntry previous;
|
FontCharacterEntry previous;
|
||||||
int32 kerning;
|
int32 kerning;
|
||||||
float scale = layout.Scale / FontManager::FontScale;
|
float scale = layout.Scale / FontManager::FontScale;
|
||||||
|
const bool enableFallbackFonts = EnumHasAllFlags(Features, RenderingFeatures::FallbackFonts);
|
||||||
|
|
||||||
// Process text to get lines
|
// Process text to get lines
|
||||||
Lines.Clear();
|
Lines.Clear();
|
||||||
@@ -1303,10 +1301,14 @@ void Render2D::DrawTextInternal(Font* font, const StringView& text, const Color&
|
|||||||
// Render all characters from the line
|
// Render all characters from the line
|
||||||
for (int32 charIndex = line.FirstCharIndex; charIndex <= line.LastCharIndex; charIndex++)
|
for (int32 charIndex = line.FirstCharIndex; charIndex <= line.LastCharIndex; charIndex++)
|
||||||
{
|
{
|
||||||
const Char c = text[charIndex];
|
// Cache current character
|
||||||
if (c != '\n')
|
const Char currentChar = text[charIndex];
|
||||||
|
|
||||||
|
// Check if it isn't a newline character
|
||||||
|
if (currentChar != '\n')
|
||||||
{
|
{
|
||||||
font->GetCharacter(c, entry);
|
// Get character entry
|
||||||
|
font->GetCharacter(currentChar, entry, enableFallbackFonts);
|
||||||
|
|
||||||
// Check if need to select/change font atlas (since characters even in the same font may be located in different atlases)
|
// Check if need to select/change font atlas (since characters even in the same font may be located in different atlases)
|
||||||
if (fontAtlas == nullptr || entry.TextureIndex != fontAtlasIndex)
|
if (fontAtlas == nullptr || entry.TextureIndex != fontAtlasIndex)
|
||||||
@@ -1328,10 +1330,10 @@ void Render2D::DrawTextInternal(Font* font, const StringView& text, const Color&
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get kerning
|
// Get kerning
|
||||||
const bool isWhitespace = StringUtils::IsWhitespace(c);
|
const bool isWhitespace = StringUtils::IsWhitespace(currentChar);
|
||||||
if (!isWhitespace && previous.IsValid)
|
if (!isWhitespace && previous.IsValid)
|
||||||
{
|
{
|
||||||
kerning = font->GetKerning(previous.Character, entry.Character);
|
kerning = entry.Font->GetKerning(previous.Character, entry.Character);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1367,317 +1369,9 @@ void Render2D::DrawTextInternal(Font* font, const StringView& text, const Color&
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Render2D::DrawTextInternal(Font* font, const StringView& text, const TextRange& textRange, const Color& color, const TextLayoutOptions& layout, MaterialBase* customMaterial)
|
void Render2D::DrawText(Font* font, const StringView& text, const TextRange& textRange, const Color& color, const TextLayoutOptions& layout, MaterialBase* customMaterial)
|
||||||
{
|
{
|
||||||
DrawTextInternal(font, textRange.Substring(text), color, layout, customMaterial);
|
DrawText(font, textRange.Substring(text), color, layout, customMaterial);
|
||||||
}
|
|
||||||
|
|
||||||
void Render2D::DrawTextInternal(Font* font, FontFallbackList* fallbacks, const StringView& text, const Color& color, const Float2& location, MaterialBase* customMaterial)
|
|
||||||
{
|
|
||||||
RENDER2D_CHECK_RENDERING_STATE;
|
|
||||||
|
|
||||||
// Check if there is no need to do anything
|
|
||||||
if (font == nullptr || text.Length() < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Temporary data
|
|
||||||
const Array<Font*>& fallbackFonts = fallbacks->GetFontList(font->GetSize());
|
|
||||||
uint32 fontAtlasIndex = 0;
|
|
||||||
FontTextureAtlas* fontAtlas = nullptr;
|
|
||||||
Float2 invAtlasSize = Float2::One;
|
|
||||||
FontCharacterEntry previous;
|
|
||||||
int32 kerning;
|
|
||||||
float scale = 1.0f / FontManager::FontScale;
|
|
||||||
|
|
||||||
// Process text to get lines
|
|
||||||
Array<float> maxAscenders;
|
|
||||||
|
|
||||||
// Render all characters
|
|
||||||
FontCharacterEntry entry;
|
|
||||||
Render2DDrawCall drawCall;
|
|
||||||
if (customMaterial)
|
|
||||||
{
|
|
||||||
drawCall.Type = DrawCallType::DrawCharMaterial;
|
|
||||||
drawCall.AsChar.Mat = customMaterial;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
drawCall.Type = DrawCallType::DrawChar;
|
|
||||||
drawCall.AsChar.Mat = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32 lineIndex = 0;
|
|
||||||
maxAscenders.Add(0);
|
|
||||||
|
|
||||||
auto getFont = [&](int32 index)->Font* {
|
|
||||||
return index >= 0 ? fallbackFonts[index] : font;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Preprocess the text to determine vertical offset of blocks
|
|
||||||
for (int32 currentIndex = 0; currentIndex < text.Length(); currentIndex++)
|
|
||||||
{
|
|
||||||
const Char c = text[currentIndex];
|
|
||||||
if (c != '\n') {
|
|
||||||
int32 fontIndex = fallbacks->GetCharFallbackIndex(c, font);
|
|
||||||
maxAscenders[lineIndex] = Math::Max(maxAscenders[lineIndex],
|
|
||||||
static_cast<float>(getFont(fontIndex)->GetAscender()));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
lineIndex++;
|
|
||||||
maxAscenders.Add(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lineIndex = 0;
|
|
||||||
// The following code cut the text into blocks, according to the font used to render
|
|
||||||
Float2 pointer = location;
|
|
||||||
// The starting index of the current block
|
|
||||||
int32 startIndex = 0;
|
|
||||||
// The index of the font used by the current block
|
|
||||||
int32 currentFontIndex = fallbacks->GetCharFallbackIndex(text[0], font);
|
|
||||||
// The maximum font height of the current line
|
|
||||||
float maxHeight = 0;
|
|
||||||
for (int32 currentIndex = 0; currentIndex < text.Length(); currentIndex++)
|
|
||||||
{
|
|
||||||
// Cache current character
|
|
||||||
const Char currentChar = text[currentIndex];
|
|
||||||
int32 nextCharIndex = currentIndex + 1;
|
|
||||||
bool moveBlock = false;
|
|
||||||
bool moveLine = false;
|
|
||||||
int32 nextFontIndex = currentFontIndex;
|
|
||||||
|
|
||||||
// Submit block if text ends
|
|
||||||
if (nextCharIndex == text.Length()) {
|
|
||||||
moveBlock = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if it isn't a newline character
|
|
||||||
if (currentChar != '\n')
|
|
||||||
{
|
|
||||||
// Get character entry
|
|
||||||
if (nextCharIndex < text.Length()) {
|
|
||||||
nextFontIndex = fallbacks->GetCharFallbackIndex(text[nextCharIndex], font);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nextFontIndex != currentFontIndex) {
|
|
||||||
moveBlock = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Move
|
|
||||||
moveLine = moveBlock = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (moveBlock) {
|
|
||||||
// Render the pending block before beginning the new block
|
|
||||||
auto fontHeight = getFont(currentFontIndex)->GetHeight();
|
|
||||||
maxHeight = Math::Max(maxHeight, static_cast<float>(fontHeight));
|
|
||||||
auto fontDescender = getFont(currentFontIndex)->GetDescender();
|
|
||||||
for (int32 renderIndex = startIndex; renderIndex <= currentIndex; renderIndex++)
|
|
||||||
{
|
|
||||||
// Get character entry
|
|
||||||
getFont(currentFontIndex)->GetCharacter(text[renderIndex], entry);
|
|
||||||
|
|
||||||
// Check if need to select/change font atlas (since characters even in the same font may be located in different atlases)
|
|
||||||
if (fontAtlas == nullptr || entry.TextureIndex != fontAtlasIndex)
|
|
||||||
{
|
|
||||||
// Get texture atlas that contains current character
|
|
||||||
fontAtlasIndex = entry.TextureIndex;
|
|
||||||
fontAtlas = FontManager::GetAtlas(fontAtlasIndex);
|
|
||||||
if (fontAtlas)
|
|
||||||
{
|
|
||||||
fontAtlas->EnsureTextureCreated();
|
|
||||||
drawCall.AsChar.Tex = fontAtlas->GetTexture();
|
|
||||||
invAtlasSize = 1.0f / fontAtlas->GetSize();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
drawCall.AsChar.Tex = nullptr;
|
|
||||||
invAtlasSize = 1.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if character is a whitespace
|
|
||||||
const bool isWhitespace = StringUtils::IsWhitespace(text[renderIndex]);
|
|
||||||
|
|
||||||
// Get kerning
|
|
||||||
if (!isWhitespace && previous.IsValid)
|
|
||||||
{
|
|
||||||
kerning = getFont(currentFontIndex)->GetKerning(previous.Character, entry.Character);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
kerning = 0;
|
|
||||||
}
|
|
||||||
pointer.X += kerning * scale;
|
|
||||||
previous = entry;
|
|
||||||
|
|
||||||
// Omit whitespace characters
|
|
||||||
if (!isWhitespace)
|
|
||||||
{
|
|
||||||
// Calculate character size and atlas coordinates
|
|
||||||
const float x = pointer.X + entry.OffsetX * scale;
|
|
||||||
const float y = pointer.Y + (fontHeight + fontDescender - entry.OffsetY) * scale;
|
|
||||||
|
|
||||||
Rectangle charRect(x, y + (maxAscenders[lineIndex] - getFont(currentFontIndex)->GetAscender()) / 2, entry.UVSize.X * scale, entry.UVSize.Y * scale);
|
|
||||||
|
|
||||||
Float2 upperLeftUV = entry.UV * invAtlasSize;
|
|
||||||
Float2 rightBottomUV = (entry.UV + entry.UVSize) * invAtlasSize;
|
|
||||||
|
|
||||||
// Add draw call
|
|
||||||
drawCall.StartIB = IBIndex;
|
|
||||||
drawCall.CountIB = 6;
|
|
||||||
DrawCalls.Add(drawCall);
|
|
||||||
WriteRect(charRect, color, upperLeftUV, rightBottomUV);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move
|
|
||||||
pointer.X += entry.AdvanceX * scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (moveLine) {
|
|
||||||
pointer.X = location.X;
|
|
||||||
pointer.Y += maxHeight * scale;
|
|
||||||
// Clear max height
|
|
||||||
maxHeight = 0;
|
|
||||||
lineIndex++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start new block
|
|
||||||
startIndex = nextCharIndex;
|
|
||||||
currentFontIndex = nextFontIndex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Render2D::DrawTextInternal(Font* font, FontFallbackList* fallbacks, const StringView& text, const TextRange& textRange, const Color& color, const Float2& location, MaterialBase* customMaterial)
|
|
||||||
{
|
|
||||||
DrawTextInternal(font, fallbacks, textRange.Substring(text), color, location, customMaterial);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Render2D::DrawTextInternal(Font* font, FontFallbackList* fallbacks, const StringView& text, const Color& color, const TextLayoutOptions& layout, MaterialBase* customMaterial)
|
|
||||||
{
|
|
||||||
RENDER2D_CHECK_RENDERING_STATE;
|
|
||||||
|
|
||||||
// Check if there is no need to do anything
|
|
||||||
if (font == nullptr || text.IsEmpty() || layout.Scale <= ZeroTolerance)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Temporary data
|
|
||||||
const Array<Font*>& fallbackFonts = fallbacks->GetFontList(font->GetSize());
|
|
||||||
uint32 fontAtlasIndex = 0;
|
|
||||||
FontTextureAtlas* fontAtlas = nullptr;
|
|
||||||
Float2 invAtlasSize = Float2::One;
|
|
||||||
FontCharacterEntry previous;
|
|
||||||
int32 kerning;
|
|
||||||
float scale = layout.Scale / FontManager::FontScale;
|
|
||||||
|
|
||||||
// Process text to get lines
|
|
||||||
BlockedTextLines.Clear();
|
|
||||||
font->ProcessText(fallbacks, text, BlockedTextLines, layout);
|
|
||||||
|
|
||||||
// Render all lines
|
|
||||||
FontCharacterEntry entry;
|
|
||||||
Render2DDrawCall drawCall;
|
|
||||||
if (customMaterial)
|
|
||||||
{
|
|
||||||
drawCall.Type = DrawCallType::DrawCharMaterial;
|
|
||||||
drawCall.AsChar.Mat = customMaterial;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
drawCall.Type = DrawCallType::DrawChar;
|
|
||||||
drawCall.AsChar.Mat = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto getFont = [&](int32 index)->Font* {
|
|
||||||
return index >= 0 ? fallbackFonts[index] : font;
|
|
||||||
};
|
|
||||||
|
|
||||||
for (int32 lineIndex = 0; lineIndex < BlockedTextLines.Count(); lineIndex++)
|
|
||||||
{
|
|
||||||
const BlockedTextLineCache& line = BlockedTextLines[lineIndex];
|
|
||||||
for (int32 blockIndex = 0; blockIndex < line.Blocks.Count(); blockIndex++)
|
|
||||||
{
|
|
||||||
const FontBlockCache& block = BlockedTextLines[lineIndex].Blocks[blockIndex];
|
|
||||||
auto fontHeight = getFont(block.FallbackFontIndex)->GetHeight();
|
|
||||||
auto fontDescender = getFont(block.FallbackFontIndex)->GetDescender();
|
|
||||||
Float2 pointer = line.Location + block.Location;
|
|
||||||
|
|
||||||
for (int32 charIndex = block.FirstCharIndex; charIndex <= block.LastCharIndex; charIndex++)
|
|
||||||
{
|
|
||||||
Char c = text[charIndex];
|
|
||||||
if (c == '\n')
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get character entry
|
|
||||||
getFont(block.FallbackFontIndex)->GetCharacter(c, entry);
|
|
||||||
|
|
||||||
// Check if need to select/change font atlas (since characters even in the same font may be located in different atlases)
|
|
||||||
if (fontAtlas == nullptr || entry.TextureIndex != fontAtlasIndex)
|
|
||||||
{
|
|
||||||
// Get texture atlas that contains current character
|
|
||||||
fontAtlasIndex = entry.TextureIndex;
|
|
||||||
fontAtlas = FontManager::GetAtlas(fontAtlasIndex);
|
|
||||||
if (fontAtlas)
|
|
||||||
{
|
|
||||||
fontAtlas->EnsureTextureCreated();
|
|
||||||
invAtlasSize = 1.0f / fontAtlas->GetSize();
|
|
||||||
drawCall.AsChar.Tex = fontAtlas->GetTexture();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
invAtlasSize = 1.0f;
|
|
||||||
drawCall.AsChar.Tex = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get kerning
|
|
||||||
const bool isWhitespace = StringUtils::IsWhitespace(c);
|
|
||||||
if (!isWhitespace && previous.IsValid)
|
|
||||||
{
|
|
||||||
kerning = getFont(block.FallbackFontIndex)->GetKerning(previous.Character, entry.Character);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
kerning = 0;
|
|
||||||
}
|
|
||||||
pointer.X += (float)kerning * scale;
|
|
||||||
previous = entry;
|
|
||||||
|
|
||||||
// Omit whitespace characters
|
|
||||||
if (!isWhitespace)
|
|
||||||
{
|
|
||||||
// Calculate character size and atlas coordinates
|
|
||||||
const float x = pointer.X + entry.OffsetX * scale;
|
|
||||||
const float y = pointer.Y - entry.OffsetY * scale + Math::Ceil((fontHeight + fontDescender) * scale);
|
|
||||||
|
|
||||||
Rectangle charRect(x, y, entry.UVSize.X * scale, entry.UVSize.Y * scale);
|
|
||||||
charRect.Offset(layout.Bounds.Location);
|
|
||||||
|
|
||||||
Float2 upperLeftUV = entry.UV * invAtlasSize;
|
|
||||||
Float2 rightBottomUV = (entry.UV + entry.UVSize) * invAtlasSize;
|
|
||||||
|
|
||||||
// Add draw call
|
|
||||||
drawCall.StartIB = IBIndex;
|
|
||||||
drawCall.CountIB = 6;
|
|
||||||
DrawCalls.Add(drawCall);
|
|
||||||
WriteRect(charRect, color, upperLeftUV, rightBottomUV);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move
|
|
||||||
pointer.X += entry.AdvanceX * scale;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Render2D::DrawTextInternal(Font* font, FontFallbackList* fallbacks, const StringView& text, const TextRange& textRange, const Color& color, const TextLayoutOptions& layout, MaterialBase* customMaterial)
|
|
||||||
{
|
|
||||||
DrawTextInternal(font, fallbacks, textRange.Substring(text), color, layout, customMaterial);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE bool NeedAlphaWithTint(const Color& color)
|
FORCE_INLINE bool NeedAlphaWithTint(const Color& color)
|
||||||
@@ -2181,22 +1875,22 @@ void Render2D::DrawBezier(const Float2& p1, const Float2& p2, const Float2& p3,
|
|||||||
{
|
{
|
||||||
RENDER2D_CHECK_RENDERING_STATE;
|
RENDER2D_CHECK_RENDERING_STATE;
|
||||||
|
|
||||||
// Find amount of blocks to use
|
// Find amount of segments to use
|
||||||
const Float2 d1 = p2 - p1;
|
const Float2 d1 = p2 - p1;
|
||||||
const Float2 d2 = p3 - p2;
|
const Float2 d2 = p3 - p2;
|
||||||
const Float2 d3 = p4 - p3;
|
const Float2 d3 = p4 - p3;
|
||||||
const float len = d1.Length() + d2.Length() + d3.Length();
|
const float len = d1.Length() + d2.Length() + d3.Length();
|
||||||
const int32 blockCount = Math::Clamp(Math::CeilToInt(len * 0.05f), 1, 100);
|
const int32 segmentCount = Math::Clamp(Math::CeilToInt(len * 0.05f), 1, 100);
|
||||||
const float blockCountInv = 1.0f / blockCount;
|
const float segmentCountInv = 1.0f / segmentCount;
|
||||||
|
|
||||||
// Draw blocked curve
|
// Draw segmented curve
|
||||||
Float2 p;
|
Float2 p;
|
||||||
AnimationUtils::Bezier(p1, p2, p3, p4, 0, p);
|
AnimationUtils::Bezier(p1, p2, p3, p4, 0, p);
|
||||||
Lines2.Clear();
|
Lines2.Clear();
|
||||||
Lines2.Add(p);
|
Lines2.Add(p);
|
||||||
for (int32 i = 1; i <= blockCount; i++)
|
for (int32 i = 1; i <= segmentCount; i++)
|
||||||
{
|
{
|
||||||
const float t = i * blockCountInv;
|
const float t = i * segmentCountInv;
|
||||||
AnimationUtils::Bezier(p1, p2, p3, p4, t, p);
|
AnimationUtils::Bezier(p1, p2, p3, p4, t, p);
|
||||||
Lines2.Add(p);
|
Lines2.Add(p);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
using FlaxEngine.GUI;
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace FlaxEngine
|
namespace FlaxEngine
|
||||||
{
|
{
|
||||||
partial class Render2D
|
partial class Render2D
|
||||||
{
|
{
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Pushes transformation layer.
|
/// Pushes transformation layer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -102,7 +100,7 @@ namespace FlaxEngine
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Draws a text, follows the font fallback settings defined in <see cref="Render2D"/>.
|
/// Draws a text.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="font">The font to use.</param>
|
/// <param name="font">The font to use.</param>
|
||||||
/// <param name="text">The text to render.</param>
|
/// <param name="text">The text to render.</param>
|
||||||
@@ -128,7 +126,7 @@ namespace FlaxEngine
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Draws a text using a custom material shader. Given material must have GUI domain and a public parameter named Font (texture parameter used for a font atlas sampling). Follows the font fallback settings defined in <see cref="Render2D"/>.
|
/// Draws a text using a custom material shader. Given material must have GUI domain and a public parameter named Font (texture parameter used for a font atlas sampling).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="font">The font to use.</param>
|
/// <param name="font">The font to use.</param>
|
||||||
/// <param name="customMaterial">Custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.</param>
|
/// <param name="customMaterial">Custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.</param>
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ struct Matrix3x3;
|
|||||||
struct Viewport;
|
struct Viewport;
|
||||||
struct TextRange;
|
struct TextRange;
|
||||||
class Font;
|
class Font;
|
||||||
class FontFallbackList;
|
|
||||||
class GPUPipelineState;
|
class GPUPipelineState;
|
||||||
class GPUTexture;
|
class GPUTexture;
|
||||||
class GPUTextureView;
|
class GPUTextureView;
|
||||||
@@ -34,7 +33,7 @@ API_CLASS(Static) class FLAXENGINE_API Render2D
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The rendering features and options flags.
|
/// The rendering features and options flags.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
API_ENUM(Attributes = "Flags") enum class RenderingFeatures
|
API_ENUM(Attributes="Flags") enum class RenderingFeatures
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The none.
|
/// The none.
|
||||||
@@ -45,6 +44,11 @@ API_CLASS(Static) class FLAXENGINE_API Render2D
|
|||||||
/// Enables automatic geometry vertices snapping to integer coordinates in screen space. Reduces aliasing and sampling artifacts. Might be disabled for 3D projection viewport or for complex UI transformations.
|
/// Enables automatic geometry vertices snapping to integer coordinates in screen space. Reduces aliasing and sampling artifacts. Might be disabled for 3D projection viewport or for complex UI transformations.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
VertexSnapping = 1,
|
VertexSnapping = 1,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enables automatic characters usage from fallback fonts.
|
||||||
|
/// </summary>
|
||||||
|
FallbackFonts = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CustomData
|
struct CustomData
|
||||||
@@ -54,7 +58,6 @@ API_CLASS(Static) class FLAXENGINE_API Render2D
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks if interface is during rendering phrase (Draw calls may be performed without failing).
|
/// Checks if interface is during rendering phrase (Draw calls may be performed without failing).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -70,10 +73,6 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
API_FIELD() static RenderingFeatures Features;
|
API_FIELD() static RenderingFeatures Features;
|
||||||
|
|
||||||
API_FIELD() static bool EnableFontFallback;
|
|
||||||
|
|
||||||
API_FIELD() static FontFallbackList* FallbackFonts;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called when frame rendering begins by the graphics device.
|
/// Called when frame rendering begins by the graphics device.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -180,17 +179,17 @@ public:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Draws a text, with font fallbacking disabled.
|
/// Draws a text.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="font">The font to use.</param>
|
/// <param name="font">The font to use.</param>
|
||||||
/// <param name="text">The text to render.</param>
|
/// <param name="text">The text to render.</param>
|
||||||
/// <param name="color">The text color.</param>
|
/// <param name="color">The text color.</param>
|
||||||
/// <param name="location">The text location.</param>
|
/// <param name="location">The text location.</param>
|
||||||
/// <param name="customMaterial">The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.</param>
|
/// <param name="customMaterial">The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.</param>
|
||||||
API_FUNCTION() static void DrawTextInternal(Font* font, const StringView& text, const Color& color, const Float2& location, MaterialBase* customMaterial = nullptr);
|
API_FUNCTION() static void DrawText(Font* font, const StringView& text, const Color& color, const Float2& location, MaterialBase* customMaterial = nullptr);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Draws a text, with font fallbacking disabled.
|
/// Draws a text.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="font">The font to use.</param>
|
/// <param name="font">The font to use.</param>
|
||||||
/// <param name="text">The text to render.</param>
|
/// <param name="text">The text to render.</param>
|
||||||
@@ -198,20 +197,20 @@ public:
|
|||||||
/// <param name="color">The text color.</param>
|
/// <param name="color">The text color.</param>
|
||||||
/// <param name="location">The text location.</param>
|
/// <param name="location">The text location.</param>
|
||||||
/// <param name="customMaterial">The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.</param>
|
/// <param name="customMaterial">The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.</param>
|
||||||
API_FUNCTION() static void DrawTextInternal(Font* font, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Color& color, const Float2& location, MaterialBase* customMaterial = nullptr);
|
API_FUNCTION() static void DrawText(Font* font, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Color& color, const Float2& location, MaterialBase* customMaterial = nullptr);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Draws a text with formatting, with font fallbacking disabled.
|
/// Draws a text with formatting.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="font">The font to use.</param>
|
/// <param name="font">The font to use.</param>
|
||||||
/// <param name="text">The text to render.</param>
|
/// <param name="text">The text to render.</param>
|
||||||
/// <param name="color">The text color.</param>
|
/// <param name="color">The text color.</param>
|
||||||
/// <param name="layout">The text layout properties.</param>
|
/// <param name="layout">The text layout properties.</param>
|
||||||
/// <param name="customMaterial">The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.</param>
|
/// <param name="customMaterial">The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.</param>
|
||||||
API_FUNCTION() static void DrawTextInternal(Font* font, const StringView& text, const Color& color, API_PARAM(Ref) const TextLayoutOptions& layout, MaterialBase* customMaterial = nullptr);
|
API_FUNCTION() static void DrawText(Font* font, const StringView& text, const Color& color, API_PARAM(Ref) const TextLayoutOptions& layout, MaterialBase* customMaterial = nullptr);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Draws a text with formatting, with font fallbacking disabled.
|
/// Draws a text with formatting.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="font">The font to use.</param>
|
/// <param name="font">The font to use.</param>
|
||||||
/// <param name="text">The text to render.</param>
|
/// <param name="text">The text to render.</param>
|
||||||
@@ -219,120 +218,7 @@ public:
|
|||||||
/// <param name="color">The text color.</param>
|
/// <param name="color">The text color.</param>
|
||||||
/// <param name="layout">The text layout properties.</param>
|
/// <param name="layout">The text layout properties.</param>
|
||||||
/// <param name="customMaterial">The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.</param>
|
/// <param name="customMaterial">The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.</param>
|
||||||
API_FUNCTION() static void DrawTextInternal(Font* font, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Color& color, API_PARAM(Ref) const TextLayoutOptions& layout, MaterialBase* customMaterial = nullptr);
|
API_FUNCTION() static void DrawText(Font* font, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Color& color, API_PARAM(Ref) const TextLayoutOptions& layout, MaterialBase* customMaterial = nullptr);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Draws a text, using custom fallback options.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="fonts">The fonts to use, ordered by priority.</param>
|
|
||||||
/// <param name="text">The text to render.</param>
|
|
||||||
/// <param name="textRange">The input text range (substring range of the input text parameter).</param>
|
|
||||||
/// <param name="color">The text color.</param>
|
|
||||||
/// <param name="location">The text location.</param>
|
|
||||||
/// <param name="customMaterial">The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.</param>
|
|
||||||
API_FUNCTION() static void DrawTextInternal(Font* font, FontFallbackList* fallbacks, const StringView& text, const Color& color, const Float2& location, MaterialBase* customMaterial = nullptr);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Draws a text with formatting, using custom fallback options.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="fonts">The fonts to use, ordered by priority.</param>
|
|
||||||
/// <param name="text">The text to render.</param>
|
|
||||||
/// <param name="color">The text color.</param>
|
|
||||||
/// <param name="layout">The text layout properties.</param>
|
|
||||||
/// <param name="customMaterial">The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.</param>
|
|
||||||
API_FUNCTION() static void DrawTextInternal(Font* font, FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Color& color, const Float2& location, MaterialBase* customMaterial = nullptr);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Draws a text with formatting, using custom fallback options.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="fonts">The fonts to use, ordered by priority.</param>
|
|
||||||
/// <param name="text">The text to render.</param>
|
|
||||||
/// <param name="textRange">The input text range (substring range of the input text parameter).</param>
|
|
||||||
/// <param name="color">The text color.</param>
|
|
||||||
/// <param name="layout">The text layout properties.</param>
|
|
||||||
/// <param name="customMaterial">The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.</param>
|
|
||||||
API_FUNCTION() static void DrawTextInternal(Font* font, FontFallbackList* fallbacks, const StringView& text, const Color& color, API_PARAM(Ref) const TextLayoutOptions& layout, MaterialBase* customMaterial = nullptr);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Draws a text with formatting, using custom fallback options.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="fonts">The fonts to use, ordered by priority.</param>
|
|
||||||
/// <param name="text">The text to render.</param>
|
|
||||||
/// <param name="textRange">The input text range (substring range of the input text parameter).</param>
|
|
||||||
/// <param name="color">The text color.</param>
|
|
||||||
/// <param name="layout">The text layout properties.</param>
|
|
||||||
/// <param name="customMaterial">The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.</param>
|
|
||||||
API_FUNCTION() static void DrawTextInternal(Font* font, FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Color& color, API_PARAM(Ref) const TextLayoutOptions& layout, MaterialBase* customMaterial = nullptr);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Draws a text, follows the fallback settings defined in <see cref="Render2D" />.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="font">The font to use.</param>
|
|
||||||
/// <param name="text">The text to render.</param>
|
|
||||||
/// <param name="color">The text color.</param>
|
|
||||||
/// <param name="location">The text location.</param>
|
|
||||||
/// <param name="customMaterial">The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.</param>
|
|
||||||
API_FUNCTION() FORCE_INLINE static void DrawText(Font* font, const StringView& text, const Color& color, const Float2& location, MaterialBase* customMaterial = nullptr) {
|
|
||||||
if (EnableFontFallback && FallbackFonts) {
|
|
||||||
DrawTextInternal(font, FallbackFonts, text, color, location, customMaterial);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
DrawTextInternal(font, text, color, location, customMaterial);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Draws a text, follows the fallback settings defined in <see cref="Render2D" />.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="font">The font to use.</param>
|
|
||||||
/// <param name="text">The text to render.</param>
|
|
||||||
/// <param name="textRange">The input text range (substring range of the input text parameter).</param>
|
|
||||||
/// <param name="color">The text color.</param>
|
|
||||||
/// <param name="location">The text location.</param>
|
|
||||||
/// <param name="customMaterial">The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.</param>
|
|
||||||
API_FUNCTION() FORCE_INLINE static void DrawText(Font* font, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Color& color, const Float2& location, MaterialBase* customMaterial = nullptr) {
|
|
||||||
if (EnableFontFallback && FallbackFonts) {
|
|
||||||
DrawTextInternal(font, FallbackFonts, text, textRange, color, location, customMaterial);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
DrawTextInternal(font, text, textRange, color, location, customMaterial);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Draws a text with formatting, follows the fallback settings defined in <see cref="Render2D" />.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="font">The font to use.</param>
|
|
||||||
/// <param name="text">The text to render.</param>
|
|
||||||
/// <param name="color">The text color.</param>
|
|
||||||
/// <param name="layout">The text layout properties.</param>
|
|
||||||
/// <param name="customMaterial">The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.</param>
|
|
||||||
API_FUNCTION() FORCE_INLINE static void DrawText(Font* font, const StringView& text, const Color& color, API_PARAM(Ref) const TextLayoutOptions& layout, MaterialBase* customMaterial = nullptr) {
|
|
||||||
if (EnableFontFallback && FallbackFonts) {
|
|
||||||
DrawTextInternal(font, FallbackFonts, text, color, layout, customMaterial);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
DrawTextInternal(font, text, color, layout, customMaterial);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Draws a text with formatting, follows the fallback settings defined in <see cref="Render2D" />.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="font">The font to use.</param>
|
|
||||||
/// <param name="text">The text to render.</param>
|
|
||||||
/// <param name="textRange">The input text range (substring range of the input text parameter).</param>
|
|
||||||
/// <param name="color">The text color.</param>
|
|
||||||
/// <param name="layout">The text layout properties.</param>
|
|
||||||
/// <param name="customMaterial">The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.</param>
|
|
||||||
API_FUNCTION() FORCE_INLINE static void DrawText(Font* font, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Color& color, API_PARAM(Ref) const TextLayoutOptions& layout, MaterialBase* customMaterial = nullptr) {
|
|
||||||
if (EnableFontFallback && FallbackFonts) {
|
|
||||||
DrawTextInternal(font, FallbackFonts, text, textRange, color, layout, customMaterial);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
DrawTextInternal(font, text, textRange, color, layout, customMaterial);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fills a rectangle area.
|
/// Fills a rectangle area.
|
||||||
@@ -571,3 +457,5 @@ public:
|
|||||||
/// <param name="color">The color.</param>
|
/// <param name="color">The color.</param>
|
||||||
API_FUNCTION() static void FillTriangle(const Float2& p0, const Float2& p1, const Float2& p2, const Color& color);
|
API_FUNCTION() static void FillTriangle(const Float2& p0, const Float2& p1, const Float2& p2, const Color& color);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
DECLARE_ENUM_OPERATORS(Render2D::RenderingFeatures);
|
||||||
|
|||||||
@@ -294,12 +294,14 @@ namespace FlaxEngine
|
|||||||
style.DragWindow = style.BackgroundSelected * 0.7f;
|
style.DragWindow = style.BackgroundSelected * 0.7f;
|
||||||
|
|
||||||
// Use optionally bundled default font (matches Editor)
|
// Use optionally bundled default font (matches Editor)
|
||||||
FontAsset defaultFont = Content.LoadAsyncInternal<FontAsset>("Editor/Fonts/Roboto-Regular");
|
var defaultFont = Content.LoadAsyncInternal<FontAsset>("Editor/Fonts/Roboto-Regular");
|
||||||
|
if (defaultFont)
|
||||||
style.FontTitle = new FontReference(defaultFont, 18).GetFont();
|
{
|
||||||
style.FontLarge = new FontReference(defaultFont, 14).GetFont();
|
style.FontTitle = defaultFont.CreateFont(18);
|
||||||
style.FontMedium = new FontReference(defaultFont, 9).GetFont();
|
style.FontLarge = defaultFont.CreateFont(14);
|
||||||
style.FontSmall = new FontReference(defaultFont, 9).GetFont();
|
style.FontMedium = defaultFont.CreateFont(9);
|
||||||
|
style.FontSmall = defaultFont.CreateFont(9);
|
||||||
|
}
|
||||||
|
|
||||||
Style.Current = style;
|
Style.Current = style;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -182,12 +182,6 @@ namespace FlaxEngine.GUI
|
|||||||
set => _autoFitTextRange = value;
|
set => _autoFitTextRange = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets whether to fallback when the primary font cannot render a char.
|
|
||||||
/// </summary>
|
|
||||||
[EditorOrder(120), DefaultValue(true), Tooltip("Whether to fallback when the font cannot render a char.")]
|
|
||||||
public bool EnableFontFallback { get; set; } = true;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="Label"/> class.
|
/// Initializes a new instance of the <see cref="Label"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -239,23 +233,7 @@ namespace FlaxEngine.GUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (EnableFontFallback)
|
Render2D.DrawText(_font.GetFont(), Material, _text, rect, color, hAlignment, wAlignment, Wrapping, BaseLinesGapScale, scale);
|
||||||
{
|
|
||||||
Render2D.DrawText(_font.GetFont(), Material, _text, rect, color, hAlignment, wAlignment, Wrapping, BaseLinesGapScale, scale);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var layout = new TextLayoutOptions
|
|
||||||
{
|
|
||||||
Bounds = rect,
|
|
||||||
HorizontalAlignment = hAlignment,
|
|
||||||
VerticalAlignment = wAlignment,
|
|
||||||
TextWrapping = Wrapping,
|
|
||||||
Scale = scale,
|
|
||||||
BaseLinesGapScale = BaseLinesGapScale,
|
|
||||||
};
|
|
||||||
Render2D.DrawTextInternal(_font.GetFont(), _text, color, ref layout, Material);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ClipText)
|
if (ClipText)
|
||||||
Render2D.PopClip();
|
Render2D.PopClip();
|
||||||
@@ -276,8 +254,7 @@ namespace FlaxEngine.GUI
|
|||||||
layout.Bounds.Size.X = Width - Margin.Width;
|
layout.Bounds.Size.X = Width - Margin.Width;
|
||||||
else if (_autoWidth && !_autoHeight)
|
else if (_autoWidth && !_autoHeight)
|
||||||
layout.Bounds.Size.Y = Height - Margin.Height;
|
layout.Bounds.Size.Y = Height - Margin.Height;
|
||||||
_textSize = EnableFontFallback ?
|
_textSize = font.MeasureText(_text, ref layout);
|
||||||
font.MeasureText(_text, ref layout) : font.MeasureTextInternal(_text, ref layout);
|
|
||||||
_textSize.Y *= BaseLinesGapScale;
|
_textSize.Y *= BaseLinesGapScale;
|
||||||
|
|
||||||
// Check if size is controlled via text
|
// Check if size is controlled via text
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using FlaxEngine.Utilities;
|
using FlaxEngine.Utilities;
|
||||||
|
|||||||
@@ -213,18 +213,18 @@ namespace FlaxEngine.GUI
|
|||||||
style.Alignment &= ~TextBlockStyle.Alignments.VerticalMask;
|
style.Alignment &= ~TextBlockStyle.Alignments.VerticalMask;
|
||||||
switch (valign)
|
switch (valign)
|
||||||
{
|
{
|
||||||
case "top":
|
case "top":
|
||||||
style.Alignment = TextBlockStyle.Alignments.Top;
|
style.Alignment = TextBlockStyle.Alignments.Top;
|
||||||
break;
|
break;
|
||||||
case "bottom":
|
case "bottom":
|
||||||
style.Alignment = TextBlockStyle.Alignments.Bottom;
|
style.Alignment = TextBlockStyle.Alignments.Bottom;
|
||||||
break;
|
break;
|
||||||
case "middle":
|
case "middle":
|
||||||
style.Alignment = TextBlockStyle.Alignments.Middle;
|
style.Alignment = TextBlockStyle.Alignments.Middle;
|
||||||
break;
|
break;
|
||||||
case "baseline":
|
case "baseline":
|
||||||
style.Alignment = TextBlockStyle.Alignments.Baseline;
|
style.Alignment = TextBlockStyle.Alignments.Baseline;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
context.StyleStack.Push(style);
|
context.StyleStack.Push(style);
|
||||||
@@ -245,15 +245,15 @@ namespace FlaxEngine.GUI
|
|||||||
style.Alignment &= ~TextBlockStyle.Alignments.VerticalMask;
|
style.Alignment &= ~TextBlockStyle.Alignments.VerticalMask;
|
||||||
switch (valign)
|
switch (valign)
|
||||||
{
|
{
|
||||||
case "left":
|
case "left":
|
||||||
style.Alignment = TextBlockStyle.Alignments.Left;
|
style.Alignment = TextBlockStyle.Alignments.Left;
|
||||||
break;
|
break;
|
||||||
case "right":
|
case "right":
|
||||||
style.Alignment = TextBlockStyle.Alignments.Right;
|
style.Alignment = TextBlockStyle.Alignments.Right;
|
||||||
break;
|
break;
|
||||||
case "center":
|
case "center":
|
||||||
style.Alignment = TextBlockStyle.Alignments.Center;
|
style.Alignment = TextBlockStyle.Alignments.Center;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
context.StyleStack.Push(style);
|
context.StyleStack.Push(style);
|
||||||
|
|||||||
@@ -316,7 +316,6 @@ namespace FlaxEngine.GUI
|
|||||||
color = textBlock.Style.ShadowColor;
|
color = textBlock.Style.ShadowColor;
|
||||||
if (!enabled)
|
if (!enabled)
|
||||||
color *= 0.6f;
|
color *= 0.6f;
|
||||||
// We don't need font fallbacks for rich text since the font is user-selected
|
|
||||||
Render2D.DrawText(font, _text, ref textBlock.Range, color, textBlock.Bounds.Location + textBlock.Style.ShadowOffset, textBlock.Style.CustomMaterial);
|
Render2D.DrawText(font, _text, ref textBlock.Range, color, textBlock.Bounds.Location + textBlock.Style.ShadowOffset, textBlock.Style.CustomMaterial);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
|
||||||
using System.ComponentModel;
|
|
||||||
|
|
||||||
namespace FlaxEngine.GUI
|
namespace FlaxEngine.GUI
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -67,12 +64,6 @@ namespace FlaxEngine.GUI
|
|||||||
[EditorDisplay("Text Style"), EditorOrder(2022), Tooltip("The color of the selection (Transparent if not used).")]
|
[EditorDisplay("Text Style"), EditorOrder(2022), Tooltip("The color of the selection (Transparent if not used).")]
|
||||||
public Color SelectionColor { get; set; }
|
public Color SelectionColor { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets whether to fallback when the primary font cannot render a char.
|
|
||||||
/// </summary>
|
|
||||||
[EditorOrder(120), DefaultValue(true), Tooltip("Whether to fallback when the font cannot render a char.")]
|
|
||||||
public bool EnableFontFallback { get; set; } = true;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="TextBox"/> class.
|
/// Initializes a new instance of the <see cref="TextBox"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -112,8 +103,7 @@ namespace FlaxEngine.GUI
|
|||||||
return Float2.Zero;
|
return Float2.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
return EnableFontFallback ? font.MeasureText(_text, ref _layout) :
|
return font.MeasureText(_text, ref _layout);
|
||||||
font.MeasureTextInternal(_text, ref _layout);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -126,9 +116,8 @@ namespace FlaxEngine.GUI
|
|||||||
return Float2.Zero;
|
return Float2.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
height = (EnableFontFallback ? font.GetMaxHeight() : font.Height) / DpiScale;
|
height = font.Height / DpiScale;
|
||||||
return EnableFontFallback ? font.GetCharPosition(_text, index, ref _layout) :
|
return font.GetCharPosition(_text, index, ref _layout);
|
||||||
font.GetCharPositionInternal(_text, index, ref _layout);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -140,8 +129,7 @@ namespace FlaxEngine.GUI
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return EnableFontFallback ? font.HitTestText(_text, location, ref _layout) :
|
return font.HitTestText(_text, location, ref _layout);
|
||||||
font.HitTestTextInternal(_text, location, ref _layout);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -180,13 +168,9 @@ namespace FlaxEngine.GUI
|
|||||||
// Check if sth is selected to draw selection
|
// Check if sth is selected to draw selection
|
||||||
if (HasSelection)
|
if (HasSelection)
|
||||||
{
|
{
|
||||||
var leftEdge = EnableFontFallback ?
|
var leftEdge = font.GetCharPosition(_text, SelectionLeft, ref _layout);
|
||||||
font.GetCharPosition(_text, SelectionLeft, ref _layout) :
|
var rightEdge = font.GetCharPosition(_text, SelectionRight, ref _layout);
|
||||||
font.GetCharPositionInternal(_text, SelectionLeft, ref _layout);
|
float fontHeight = font.Height / DpiScale;
|
||||||
var rightEdge = EnableFontFallback ?
|
|
||||||
font.GetCharPosition(_text, SelectionRight, ref _layout) :
|
|
||||||
font.GetCharPositionInternal(_text, SelectionRight, ref _layout);
|
|
||||||
float fontHeight = font.GetMaxHeight() / DpiScale;
|
|
||||||
|
|
||||||
// Draw selection background
|
// Draw selection background
|
||||||
float alpha = Mathf.Min(1.0f, Mathf.Cos(_animateTime * BackgroundSelectedFlashSpeed) * 0.5f + 1.3f);
|
float alpha = Mathf.Min(1.0f, Mathf.Cos(_animateTime * BackgroundSelectedFlashSpeed) * 0.5f + 1.3f);
|
||||||
@@ -226,19 +210,11 @@ namespace FlaxEngine.GUI
|
|||||||
var color = TextColor;
|
var color = TextColor;
|
||||||
if (!enabled)
|
if (!enabled)
|
||||||
color *= 0.6f;
|
color *= 0.6f;
|
||||||
if (EnableFontFallback)
|
Render2D.DrawText(font, _text, color, ref _layout, TextMaterial);
|
||||||
Render2D.DrawText(font, _text, color, ref _layout, TextMaterial);
|
|
||||||
else
|
|
||||||
// Draw without fallback
|
|
||||||
Render2D.DrawTextInternal(font, _text, color, ref _layout, TextMaterial);
|
|
||||||
}
|
}
|
||||||
else if (!string.IsNullOrEmpty(_watermarkText) && !IsFocused)
|
else if (!string.IsNullOrEmpty(_watermarkText) && !IsFocused)
|
||||||
{
|
{
|
||||||
if (EnableFontFallback)
|
Render2D.DrawText(font, _watermarkText, WatermarkTextColor, ref _layout, TextMaterial);
|
||||||
Render2D.DrawText(font, _watermarkText, WatermarkTextColor, ref _layout, TextMaterial);
|
|
||||||
else
|
|
||||||
// Draw without fallback
|
|
||||||
Render2D.DrawTextInternal(font, _watermarkText, WatermarkTextColor, ref _layout, TextMaterial);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Caret
|
// Caret
|
||||||
|
|||||||
@@ -280,13 +280,13 @@ namespace FlaxEngine.GUI
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[EditorDisplay("Border Style"), EditorOrder(2010), Tooltip("Whether to have a border."), ExpandGroups]
|
[EditorDisplay("Border Style"), EditorOrder(2010), Tooltip("Whether to have a border."), ExpandGroups]
|
||||||
public bool HasBorder { get; set; } = true;
|
public bool HasBorder { get; set; } = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the border thickness.
|
/// Gets or sets the border thickness.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[EditorDisplay("Border Style"), EditorOrder(2011), Tooltip("The thickness of the border."), Limit(0)]
|
[EditorDisplay("Border Style"), EditorOrder(2011), Tooltip("The thickness of the border."), Limit(0)]
|
||||||
public float BorderThickness { get; set; } = 1.0f;
|
public float BorderThickness { get; set; } = 1.0f;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the color of the border (Transparent if not used).
|
/// Gets or sets the color of the border (Transparent if not used).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -239,7 +239,7 @@ void TextRender::UpdateLayout()
|
|||||||
const bool isWhitespace = StringUtils::IsWhitespace(c);
|
const bool isWhitespace = StringUtils::IsWhitespace(c);
|
||||||
if (!isWhitespace && previous.IsValid)
|
if (!isWhitespace && previous.IsValid)
|
||||||
{
|
{
|
||||||
kerning = font->GetKerning(previous.Character, entry.Character);
|
kerning = entry.Font->GetKerning(previous.Character, entry.Character);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user