Skip to content

Commit

Permalink
[SUTK] Added Text::setColor and other color range setters
Browse files Browse the repository at this point in the history
  • Loading branch information
ravi688 committed Aug 15, 2024
1 parent cd24c04 commit 5f2a8cb
Show file tree
Hide file tree
Showing 7 changed files with 293 additions and 10 deletions.
13 changes: 13 additions & 0 deletions sutk/include/sutk/IColorable.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#pragma once

#include <sutk/defines.hpp> // for SUTK::Colo4 and SUTK_API

namespace SUTK
{
class SUTK_API IColorable
{
public:
virtual void setColor(Color4 color) = 0;
virtual Color4 getColor() const = 0;
};
}
14 changes: 14 additions & 0 deletions sutk/include/sutk/IGfxDriver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,18 @@ namespace SUTK

class Geometry;

struct ColorRange
{
// 4-Byte
LineCountType begin;
// 4-Byte
LineCountType end;
// 4-Byte
Color4 color;
};

typedef std::vector<ColorRange> ColorRangeList;

class IGfxDriver
{
public:
Expand All @@ -24,6 +36,8 @@ namespace SUTK
virtual void setTextPosition(GfxDriverObjectHandleType handle, Vec2Df position) = 0;
virtual void setTextPointSize(GfxDriverObjectHandleType handle, f32 pointSize) = 0;
virtual f32 getTextPointSize(GfxDriverObjectHandleType handle) = 0;
virtual void setTextColor(GfxDriverObjectHandleType handle, const Color4 color) = 0;
virtual void setTextColorRanges(GfxDriverObjectHandleType handle, const ColorRange* ranges, u32 rangeCount) = 0;
virtual void setTextData(GfxDriverObjectHandleType handle, const std::string& data) = 0;
virtual LineCountType getTextGlyphIndexFromCoord(GfxDriverObjectHandleType handle, f32 coord) = 0;
virtual f32 getTextCoordFromGlyphIndex(GfxDriverObjectHandleType handle, LineCountType col) = 0;
Expand Down
4 changes: 4 additions & 0 deletions sutk/include/sutk/SGEGfxDriver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ namespace SUTK
};
std::unordered_map<id_generator_id_type_t, OnResizeCallbackHandlerData> m_onResizeHandlers;

std::vector<char_attr_color_range_t> m_colorRangeBuffer;

// We're caching current window size into this member variable to avoid calling internal function calls everytime getSize() is called
// The value of this variable will be updated whenever window is resized.
Vec2D<DisplaySizeType> m_size;
Expand Down Expand Up @@ -118,6 +120,8 @@ namespace SUTK
virtual void setTextPosition(GfxDriverObjectHandleType handle, Vec2Df position) override;
virtual void setTextPointSize(GfxDriverObjectHandleType handle, f32 pointSize) override;
virtual f32 getTextPointSize(GfxDriverObjectHandleType handle) override;
virtual void setTextColor(GfxDriverObjectHandleType handle, const Color4 color) override;
virtual void setTextColorRanges(GfxDriverObjectHandleType handle, const ColorRange* ranges, u32 rangeCount) override;
virtual void setTextData(GfxDriverObjectHandleType handle, const std::string& data) override;

virtual LineCountType getTextGlyphIndexFromCoord(GfxDriverObjectHandleType handle, f32 coord) override;
Expand Down
60 changes: 56 additions & 4 deletions sutk/include/sutk/Text.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <sutk/defines.hpp>
#include <sutk/Renderable.hpp> /* for SUTK::Renderable */
#include <sutk/UIDriver.hpp> /* for SUTK::UIDriver::getGfxDriver() */
#include <sutk/IColorable.hpp> // for SUTK::IColorable

#include <string> /* for std::string */
#include <vector> /* for std::vector*/
Expand Down Expand Up @@ -71,17 +72,21 @@ namespace SUTK
std::size_t size() const noexcept { return m_data.size(); }
};

class LineText : public GfxDriverRenderable
class LineText : public GfxDriverRenderable, public IColorable
{
private:
bool m_isPosDirty;
bool m_isDataDirty;
bool m_isPointSizeDirty;
bool m_isColorDirty;
bool m_isColorRangesDirty;
LineTextData m_data;
Color4 m_color;
std::vector<ColorRange> m_colorRanges;
Vec2Df m_pos;
f32 m_pointSize;

LineText(UIDriver& driver, GfxDriverObjectHandleType textGroup) noexcept;
LineText(UIDriver& driver, GfxDriverObjectHandleType textGroup, Color4 color = SUTK::Color4::white()) noexcept;

friend class Text;

Expand All @@ -99,7 +104,14 @@ namespace SUTK
virtual bool isDirty() override;
virtual void update() override;

// Implementation of IColorable::setColor() and IColorable::getColor()
virtual void setColor(Color4 color) noexcept override;
virtual Color4 getColor() const noexcept override;

virtual void destroy() override;

void clearColorRanges() noexcept;
void addColorRange(std::size_t pos, std::size_t len, const Color4 color) noexcept;

// returns column (index of a glyph) given a coordinate (absisca) along the line length.
LineCountType getColPosFromCoord(f32 coord) noexcept;
Expand Down Expand Up @@ -148,6 +160,22 @@ namespace SUTK
CursorPosition(T line, T col = 0) noexcept : m_line(line), m_col(col) { }
CursorPosition(const CursorPosition&) = default;
CursorPosition& operator=(const CursorPosition&) = default;
bool operator <(const CursorPosition& rhs) const noexcept
{
return (m_line < rhs.m_line) && (m_col < rhs.m_col);
}
bool operator <=(const CursorPosition& rhs) const noexcept
{
return (m_line <= rhs.m_line) && (m_col <= rhs.m_col);
}
bool operator >(const CursorPosition& rhs) const noexcept
{
return (m_line > rhs.m_line) && (m_col > rhs.m_col);
}
bool operator >=(const CursorPosition& rhs) const noexcept
{
return (m_line >= rhs.m_line) && (m_col >= rhs.m_col);
}

void moveToNextLine(const T& max = std::numeric_limits<T>::max()) noexcept { if(m_line < max) m_line += 1; }
void moveToPrevLine(const T& min = std::numeric_limits<T>::min()) noexcept { if(m_line > min) m_line -= 1; }
Expand All @@ -173,10 +201,17 @@ namespace SUTK
return stream;
}

template<typename T>
struct SelectionRange
{
CursorPosition<T> begin;
CursorPosition<T> end;
};

// One text object is responsible for rendering a small to medium sized sub-text
// This usually translates to a single Gfx API specific buffer object. For example, it is VkBuffer (and VkDeviceMemory) in vulkan.
// This is to ensure fast manipulation of larget text data consisting of multiple such 'Text' objects.
class Text : public Renderable
class Text : public Renderable, public IColorable
{
private:
GfxDriverObjectHandleType m_textGroup;
Expand All @@ -189,7 +224,7 @@ namespace SUTK
bool m_isClippingEnabled;

// data and rendering attributes
Color3 m_color;
Color4 m_color;
TPGEmphasis m_emphasis;
GfxDriverObjectHandleType m_font;
f32 m_pointSize;
Expand All @@ -213,6 +248,9 @@ namespace SUTK

std::pair<s32, s32> getUnclippedLineRange() noexcept;
void updateLinePositions() noexcept;
LineCountType getNumChars(const CursorPosition<LineCountType>& position) noexcept;
void addColorRange(const SelectionRange<LineCountType>& range, Color4 color) noexcept;

public:

Vec2Df getLocalPositionFromCursorPosition(const CursorPosition<LineCountType>& cursor) noexcept;
Expand All @@ -230,6 +268,12 @@ namespace SUTK

void clear() noexcept;

// Implementation of IColorable::setColor() and IColorable::getColor()
virtual void setColor(Color4 color) noexcept override;
virtual Color4 getColor() const noexcept override;

void setColorRanges(const std::vector<std::pair<SelectionRange<LineCountType>, Color4>>& ranges) noexcept;

LineText* createNewLine(Flags flags = Flags::After, LineCountType line = END_OF_TEXT) noexcept;
void removeLine(LineCountType line) noexcept;
LineText* getOrCreateLastLine() noexcept;
Expand All @@ -244,9 +288,17 @@ namespace SUTK
Vec2Df getScrollDelta() const noexcept { return m_scrollDelta; }

std::size_t getLineCount() const noexcept { return m_lines.size(); }
// TODO: Optimize it, maintain a monolithic std::string and pass lightweight slices (pair of indices) to LineText class,
// and returns (that std::string).size() when getCharCount() is called.
// That's because, at the end SGE caches the set character array internally and there is no need to maintain std::string objects for each line.
// For now, it iterates through all the lines and sums the char count of each line.
std::size_t getCharCount() const noexcept;

void setFontSize(const f32 pointSize) noexcept;
f32 getFontSize() const noexcept;
f32 getBaselineHeight() noexcept;

CursorPosition<LineCountType> begin() const noexcept;
CursorPosition<LineCountType> end() const noexcept;
};
}
42 changes: 40 additions & 2 deletions sutk/include/sutk/defines.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -367,10 +367,48 @@ namespace SUTK
}

static constexpr Color3 red() noexcept { return { 255, 0, 0 }; }
static constexpr Color3 blue() noexcept { return { 0, 255, 0 }; }
static constexpr Color3 green() noexcept { return { 0, 0, 255 }; }
static constexpr Color3 blue() noexcept { return { 0, 0, 255 }; }
static constexpr Color3 green() noexcept { return { 0, 255, 0 }; }
static constexpr Color3 white() noexcept { return { 255, 255, 255 }; }
static constexpr Color3 black() noexcept { return { 0, 0, 0 }; }
static constexpr Color3 yellow() noexcept { return { 255, 255, 0 }; }
};


struct Color4
{
union
{
struct
{
u8 r;
u8 g;
u8 b;
};
Color3 color3;
};
u8 a;

constexpr Color4() noexcept : r(0), g(0), b(0), a(0) { }
constexpr Color4(u8 _r, u8 _g, u8 _b, u8 _a) noexcept : r(_r), g(_g), b(_b), a(_a) { }
constexpr Color4(u8 _r, u8 _g, u8 _b) noexcept : Color4(_r, _g, _b, 255) { }

bool operator ==(Color4& rhs) const noexcept
{
return (r == rhs.r) && (g == rhs.g) && (b == rhs.b);
}

bool operator !=(Color4& rhs) const noexcept
{
return !Color4::operator==(rhs);
}

static constexpr Color4 red() noexcept { return { 255, 0, 0, 255 }; }
static constexpr Color4 blue() noexcept { return { 0, 0, 255, 255 }; }
static constexpr Color4 green() noexcept { return { 0, 255, 0, 255 }; }
static constexpr Color4 white() noexcept { return { 255, 255, 255, 255 }; }
static constexpr Color4 black() noexcept { return { 0, 0, 0, 255 }; }
static constexpr Color4 yellow() noexcept { return { 255, 255, 0, 255 }; }
};

typedef Rect2D<f32> Rect2Df;
Expand Down
28 changes: 27 additions & 1 deletion sutk/source/SGEGfxDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ namespace SUTK

// create camera
SGE::Camera camera = cameraSystem.createCamera(SGE::Camera::ProjectionType::Perspective);
camera.setClear(COLOR_BLUE, 1.0f);
camera.setClear(COLOR_BLACK, 1.0f);
camera.setActive(true);
camera.setTransform(mat4_mul(2, mat4_translation(-1.8f, 0.6f, 0), mat4_rotation(0, 0, -22 * DEG2RAD)));

Expand Down Expand Up @@ -288,6 +288,32 @@ namespace SUTK
return getText(handle).getPointSize();
}

static INLINE_IF_RELEASE_MODE color_t to_color(const Color4 _color)
{
return color(_color.r / 255.0f, _color.g / 255.0f, _color.b / 255.0f, _color.a / 255.0f);
}

void SGEGfxDriver::setTextColor(GfxDriverObjectHandleType handle, const Color4 color)
{
getText(handle).setColor(to_color(color));
}

void SGEGfxDriver::setTextColorRanges(GfxDriverObjectHandleType handle, const ColorRange* ranges, u32 rangeCount)
{
SGE::BitmapTextString textString = getText(handle);
m_colorRangeBuffer.clear();
m_colorRangeBuffer.reserve(textString.getLength());
for(u32 i = 0; i < rangeCount; ++i)
{
char_attr_color_range_t range { };
range.begin = ranges[i].begin;
range.end = ranges[i].end;
range.color = to_color(ranges[i].color);
m_colorRangeBuffer.push_back(range);
}
textString.setCharAttrColor(m_colorRangeBuffer.data(), rangeCount);
}

void SGEGfxDriver::setTextData(GfxDriverObjectHandleType handle, const std::string& data)
{
auto it = getSubTextIterator(handle);
Expand Down
Loading

0 comments on commit 5f2a8cb

Please sign in to comment.