1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
|
#pragma once
#include "Canvas.h"
#include "Font.h"
#include "../../nCine/Primitives/Rect.h"
#include "../../nCine/Primitives/Vector2.h"
#include <Containers/SmallVector.h>
#include <Containers/String.h>
#include <Containers/StringView.h>
using namespace Death::Containers;
using namespace nCine;
namespace Jazz2::UI
{
/** @brief Initialization parameters for formatted text block */
struct FormattedTextBlockParams
{
StringView Text;
Font* TextFont = nullptr;
Alignment Align = Alignment::Left;
Colorf Color = Font::DefaultColor;
float Scale = 1.0f;
float CharSpacing = 1.0f;
float LineSpacing = 1.0f;
};
/** @brief Formatted text block */
class FormattedTextBlock
{
public:
FormattedTextBlock();
FormattedTextBlock(const FormattedTextBlockParams& params);
FormattedTextBlock(const FormattedTextBlock&) = delete;
FormattedTextBlock(FormattedTextBlock&& other) noexcept;
FormattedTextBlock& operator=(const FormattedTextBlock&) = delete;
FormattedTextBlock& operator=(FormattedTextBlock&& other) noexcept;
static FormattedTextBlock From(const FormattedTextBlock& source);
void Draw(Canvas* canvas, Rectf bounds, std::uint16_t depth, std::int32_t& charOffset, float angleOffset = 0.0f, float varianceX = 4.0f, float varianceY = 4.0f, float speed = 0.4f);
Vector2f MeasureSize(Vector2f proposedSize);
float GetCachedWidth() const;
float GetCachedHeight() const;
Alignment GetAlignment() const {
return _alignment;
}
void SetAlignment(Alignment value);
Colorf GetDefaultColor() const {
return _defaultColor;
}
void SetDefaultColor(Colorf color);
Font* GetFont() {
return _font;
}
void SetFont(Font* value);
float GetScale() const {
return _defaultScale;
}
void SetScale(float value);
float GetCharSpacing() const {
return _defaultCharSpacing;
}
void SetCharSpacing(float value);
float GetLineSpacing() const {
return _defaultLineSpacing;
}
void SetLineSpacing(float value);
constexpr float GetProposedWidth() const {
return _proposedWidth;
}
void SetProposedWidth(float value);
StringView GetText() const {
return _text;
}
void SetText(StringView value);
void SetText(String&& value);
constexpr bool IsMultiline() const {
return (_flags & FormattedTextBlockFlags::Multiline) == FormattedTextBlockFlags::Multiline;
}
void SetMultiline(bool value);
constexpr bool GetWrapping() const {
return (_flags & FormattedTextBlockFlags::Wrapping) == FormattedTextBlockFlags::Wrapping;
}
void SetWrapping(bool value);
constexpr bool IsEllipsized() const {
return (_flags & FormattedTextBlockFlags::Ellipsized) == FormattedTextBlockFlags::Ellipsized;
}
private:
static constexpr std::uint32_t Ellipsis = UINT32_MAX;
#ifndef DOXYGEN_GENERATING_OUTPUT
// Doxygen 1.12.0 outputs also private structs/unions even if it shouldn't
struct Part
{
std::uint32_t Begin;
std::uint32_t Length;
Vector2f Location;
float Height;
Colorf CurrentColor;
float Scale;
float CharSpacing;
bool AllowVariance;
Part(std::uint32_t begin, std::uint32_t length, Vector2f location, float height, Colorf color, float scale, float charSpacing, bool allowVariance) noexcept;
Part(const Part& other) noexcept;
Part(Part&& other) noexcept;
Part& operator=(const Part& other) noexcept;
Part& operator=(Part&& other) noexcept;
};
struct BackgroundPart
{
Rectf Bounds;
Colorf CurrentColor;
BackgroundPart(Colorf color);
};
#endif
enum class FormattedTextBlockFlags : std::uint16_t {
None = 0,
Multiline = 0x01,
Wrapping = 0x02,
Ellipsized = 0x10
};
DEATH_PRIVATE_ENUM_FLAGS(FormattedTextBlockFlags);
SmallVector<Part, 1> _parts;
SmallVector<BackgroundPart, 0> _background;
Font* _font;
String _text;
FormattedTextBlockFlags _flags;
float _proposedWidth;
float _cachedWidth;
Colorf _defaultColor;
float _defaultScale;
float _defaultCharSpacing;
float _defaultLineSpacing;
Alignment _alignment;
void RecreateCache();
void HandleEndOfLine(Vector2f currentLocation, std::int32_t& lineBeginIndex, std::int32_t& lineAlignIndex, std::int32_t& backgroundIndex);
void InsertEllipsis(Vector2f& currentLocation, Colorf currentColor, float scale, float charSpacing, float lineSpacing, bool allowVariance, float maxWidth, float* charFitWidths);
void InsertDottedUnderline(Part& part, float width);
static float PerformVerticalAlignment(SmallVectorImpl<Part>& processedParts, std::int32_t firstPartOfLine);
static void FinalizeBackgroundPart(Vector2f currentLocation, SmallVectorImpl<Part>& parts, SmallVectorImpl<BackgroundPart>& backgroundParts);
static char* FindFirstControlSequence(char* string, std::int32_t length);
static Colorf Uint32ToColorf(std::uint32_t value);
};
}
|