Skip to content

Commit

Permalink
[SUTK] Various fixes and added Text::serialize and Text::deserialize
Browse files Browse the repository at this point in the history
  • Loading branch information
ravi688 committed Aug 18, 2024
1 parent b0a83e9 commit 6b6cc52
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 26 deletions.
4 changes: 2 additions & 2 deletions sutk/include/sutk/IGfxDriver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ namespace SUTK
virtual void destroyGeometry(GfxDriverObjectHandleType geometry) = 0;
virtual GfxDriverObjectHandleType getGeometryObject(GfxDriverObjectHandleType geometry) = 0;

virtual u32 getTextBaselineHeightInPixels(GfxDriverObjectHandleType handle) = 0;
virtual f32 getTextBaselineHeightInCentimeters(GfxDriverObjectHandleType handle) = 0;
virtual u32 getTextBaselineHeightInPixels(f32 pointSize) = 0;
virtual f32 getTextBaselineHeightInCentimeters(f32 pointSize) = 0;
// the Vec2Df arguments is in centimeters (not pixels!)
typedef std::function<void(Vec2Df)> OnResizeCallbackHandler;
virtual u32 addOnResizeHandler(OnResizeCallbackHandler handler) = 0;
Expand Down
4 changes: 2 additions & 2 deletions sutk/include/sutk/SGEGfxDriver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,8 @@ namespace SUTK
virtual void destroyGeometry(GfxDriverObjectHandleType geometry) override;
virtual GfxDriverObjectHandleType getGeometryObject(GfxDriverObjectHandleType geometry) override;

virtual u32 getTextBaselineHeightInPixels(GfxDriverObjectHandleType handle) override;
virtual f32 getTextBaselineHeightInCentimeters(GfxDriverObjectHandleType handle) override;
virtual u32 getTextBaselineHeightInPixels(f32 pointSize) override;
virtual f32 getTextBaselineHeightInCentimeters(f32 pointSize) override;
virtual u32 addOnResizeHandler(OnResizeCallbackHandler handler) override;
virtual void removeOnResizeHandler(u32 id) override;
};
Expand Down
9 changes: 8 additions & 1 deletion sutk/include/sutk/Text.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,10 +190,14 @@ namespace SUTK
T getLine() const noexcept { return m_line; }
T getColumn() const noexcept { return m_col; }

static CursorPosition StartOfText();
static CursorPosition StartOfLine(T line);
static CursorPosition EndOfText();
static CursorPosition EndOfLine(T line);
};

template<> CursorPosition<LineCountType> CursorPosition<LineCountType>::StartOfText();
template<> CursorPosition<LineCountType> CursorPosition<LineCountType>::StartOfLine(LineCountType line);
template<> CursorPosition<LineCountType> CursorPosition<LineCountType>::EndOfText();
template<> CursorPosition<LineCountType> CursorPosition<LineCountType>::EndOfLine(LineCountType line);

Expand Down Expand Up @@ -286,7 +290,7 @@ namespace SUTK
void append(const std::string& str) noexcept { insert(CursorPosition<LineCountType>::EndOfText(), str); }
LineText* getLine(LineCountType line) noexcept;
const LineText* getLine(LineCountType line) const noexcept { return const_cast<Text*>(this)->getLine(line); }
void insert(const CursorPosition<LineCountType>& position, const std::string& str) noexcept;
void insert(CursorPosition<LineCountType> position, const std::string& str) noexcept;
void removeRange(CursorPosition<LineCountType> start, CursorPosition<LineCountType> end) noexcept;
void set(const std::string& str) noexcept;
void enableClipping(bool isEnable = true) noexcept;
Expand All @@ -309,5 +313,8 @@ namespace SUTK
CursorPosition<LineCountType> end() const noexcept;

void serialize(std::ostream& stream) const noexcept;
void serializeToFile(const std::string& filePath) const noexcept;
void deserialize(std::istream& stream) noexcept;
void deserializeFromFile(const std::string& filePath, CursorPosition<LineCountType> pos = CursorPosition<LineCountType>::EndOfText()) noexcept;
};
}
7 changes: 3 additions & 4 deletions sutk/source/SGEGfxDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -620,19 +620,18 @@ namespace SUTK
return geometry;
}

u32 SGEGfxDriver::getTextBaselineHeightInPixels(GfxDriverObjectHandleType handle)
u32 SGEGfxDriver::getTextBaselineHeightInPixels(f32 pointSize)
{
f32 pointSize = getText(handle).getPointSize();
f32 save = m_font.getCharSize();
m_font.setCharSize(pointSize);
u32 pixels = m_font.getFontUnitsToPixels(m_font.getBaselineSpace(), SGE::Display::GetDPI().height);
m_font.setCharSize(save);
return pixels;
}

f32 SGEGfxDriver::getTextBaselineHeightInCentimeters(GfxDriverObjectHandleType handle)
f32 SGEGfxDriver::getTextBaselineHeightInCentimeters(f32 pointSize)
{
return SGE::Display::ConvertPixelsToInches({ 0, static_cast<f32>(getTextBaselineHeightInPixels(handle)) }).height * CENTIMETERS_PER_INCH;
return SGE::Display::ConvertPixelsToInches({ 0, static_cast<f32>(getTextBaselineHeightInPixels(pointSize)) }).height * CENTIMETERS_PER_INCH;
}

u32 SGEGfxDriver::addOnResizeHandler(OnResizeCallbackHandler handler)
Expand Down
111 changes: 94 additions & 17 deletions sutk/source/Text.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,16 @@
#include <sutk/RenderableContainer.hpp> /* for SUTK::RenderableContainer::getLocalCoordsToScreenCoords() */

#include <common/assert.h> /* for _assert() */
#include <common/debug.h> // for debug_log_error()
#include <disk_manager/file_reader.h> // for load_text_from_file()

#include <algorithm> // for std::min and std::clamp
#include <fstream> // for std::ofstream

namespace SUTK
{
template<> CursorPosition<LineCountType> CursorPosition<LineCountType>::StartOfText() { return { 0, 0 }; }
template<> CursorPosition<LineCountType> CursorPosition<LineCountType>::StartOfLine(LineCountType line) { return { line, 0 }; }
template<> CursorPosition<LineCountType> CursorPosition<LineCountType>::EndOfText() { return { END_OF_TEXT, END_OF_LINE }; }
template<> CursorPosition<LineCountType> CursorPosition<LineCountType>::EndOfLine(LineCountType line) { return { line, END_OF_LINE }; }

Expand Down Expand Up @@ -170,13 +175,13 @@ namespace SUTK
}
f32 LineText::getBaselineHeight() noexcept
{
updatePointSize();
return getGfxDriver().getTextBaselineHeightInCentimeters(getGfxDriverObjectHandle());
return getGfxDriver().getTextBaselineHeightInCentimeters(m_pointSize);
}

Text::Text(UIDriver& driver, RenderableContainer* container) noexcept : Renderable(driver, container), m_textGroup(GFX_DRIVER_OBJECT_NULL_HANDLE), m_baselineHeight(0), m_isDirty(false), m_isClippingEnabled(false), m_color(SUTK::Color4::yellow()), m_pointSize(12)
{
m_textGroup = getGfxDriver().createTextGroup();
m_baselineHeight = getGfxDriver().getTextBaselineHeightInCentimeters(m_pointSize);
}

bool Text::isDirty()
Expand Down Expand Up @@ -286,6 +291,8 @@ namespace SUTK

Vec2Df Text::getLocalPositionFromCursorPosition(const CursorPosition<LineCountType>& cursor) noexcept
{
if(m_lines.size() == 0)
return { m_scrollDelta.x, m_scrollDelta.y };
LineCountType line = cursor.getLine();
_assert((line >= 0) && (line < m_lines.size()));
return { m_lines[line]->getCoordFromColPos(cursor.getColumn()) + m_scrollDelta.x, getBaselineHeight() * cursor.getLine() + m_scrollDelta.y };
Expand Down Expand Up @@ -320,14 +327,17 @@ namespace SUTK
LineText* Text::createNewLine(Flags flags, LineCountType line) noexcept
{
CursorPosition<LineCountType> cursorPosition;

if((line == 0) && (getLineCount() == 0))
line = END_OF_TEXT;

if(line == END_OF_TEXT)
{
line = m_lines.size();
if(line >= 1u)
line -= 1u;
};
cursorPosition.moveToLine(static_cast<DisplaySizeType>(line));
cursorPosition.moveToLine(static_cast<LineCountType>(line));

if(flags == Flags::After)
cursorPosition.moveToNextLine(m_lines.size());
Expand All @@ -338,7 +348,7 @@ namespace SUTK

// insert the line at which the cursor points to
LineText* lineText = new LineText(getUIDriver(), m_textGroup);
m_lines.insert(com::GetIteratorFromIndex<std::vector, LineText*>(m_lines, cursorPosition.getLine()), lineText);
m_lines.insert(std::next(m_lines.begin(), cursorPosition.getLine()), lineText);

lineText->setFontSize(m_pointSize);
lineText->setColor(m_color);
Expand All @@ -356,7 +366,7 @@ namespace SUTK
// delete m_lines[line];
m_lines[line]->setData("");
// remove the line at index 'line'
m_lines.erase(com::GetIteratorFromIndex<std::vector, LineText*>(m_lines, line));
m_lines.erase(std::next(m_lines.begin(), line));

// shift the line at which the cursor points to and the lines succeeding it
for(std::size_t i = line; i < m_lines.size(); i++)
Expand Down Expand Up @@ -395,46 +405,72 @@ namespace SUTK
return m_lines[line];
}

void Text::insert(const CursorPosition<LineCountType>& position, const std::string& str) noexcept
void Text::insert(CursorPosition<LineCountType> position, const std::string& str) noexcept
{
// if there is nothing to write then return
if(str.empty())
return;
LineText* lineText = getLine(position.getLine());

std::string::size_type index = str.find_first_of('\n');
LineText* lineText = NULL;
if(position >= end())
position = CursorPosition<LineCountType>::EndOfText();

lineText = getLine(position.getLine());

// Take line-endings into account
// Possible line endings are: '\r', '\r\n', and '\n'.
bool isCarriageReturn = false;
std::string::size_type index = str.find_first_of('\r');
if(index == std::string::npos)
index = str.find_first_of('\n');
else
isCarriageReturn = true;

if(index == std::string::npos)
lineText->insert(position.getColumn(), str);
else
lineText->insert(position.getColumn(), str.substr(0, index));

LineText* newLineText = NULL;
auto line = position.getLine();
auto line = (position.getLine() == END_OF_LINE) ? (getLineCount() - 1) : position.getLine();
auto saveIndex = index;
while(index != std::string::npos)
{
// create a new line
newLineText = createNewLine(Flags::After, line++);

// character just after '\n'
++index;
if(isCarriageReturn && (str[index] == '\n'))
++index;

// if the new line character is at the very end, then no extra characters to add,
// i.e. it is an empty new line
if(index == (str.size() - 1))
if(index == str.size())
break;

// character just after '\n'
++index;

// determine the substring to be added into the just created new line
// i.e. the substring is sandwitched with either '\n' characters on both the sides (left and right),
// or '\n' character on left and end of the string on the right.
auto end = str.find_first_of('\n', index);

auto end = str.find_first_of('\r', index);
if(end == std::string::npos)
{
end = str.find_first_of('\n', index);
isCarriageReturn = false;
}
else isCarriageReturn = true;


// if no new line character on the right side, then append rest of the string
if(end == std::string::npos)
newLineText->append(str.substr(index, std::string::npos));
// otherwise, append a substring surrounded by '\n' charactesr from both the sides (left and right)
else
{
_com_assert(end >= index);
newLineText->append(str.substr(index, end - index));
}
index = end;
}

Expand Down Expand Up @@ -568,8 +604,6 @@ namespace SUTK

f32 Text::getBaselineHeight() noexcept
{
if((m_baselineHeight == 0.0f) && (m_lines.size() > 0))
m_baselineHeight = m_lines[0]->getBaselineHeight();
return m_baselineHeight;
}

Expand Down Expand Up @@ -597,6 +631,49 @@ namespace SUTK
}
}

void Text::serializeToFile(const std::string& filePath) const noexcept
{
std::ofstream file(filePath, std::ios::out | std::ios::trunc);
if(!file.is_open())
{
debug_log_error("Failed to open file: %.*s", filePath.size(), filePath.data());
return;
}
serialize(file);
file.close();
}

void Text::deserialize(std::istream& stream) noexcept
{
std::streamsize beginPos = stream.tellg();
stream.seekg(0, std::ios::end);
std::streamsize endPos = stream.tellg();
std::streamsize size = endPos - beginPos;
stream.seekg(beginPos);
if(size == 0)
return;
std::string buffer(size, '\0');
char* data = reinterpret_cast<char*>(&buffer[0]);
stream.read(data, size);
std::streamsize readSize = stream.gcount();
// ERROR: For some reason, this assertion always fails. Therefore use Text::deserializeFromFile() for now
_com_assert(static_cast<std::streamsize>(readSize) == size);
set(buffer);
}

void Text::deserializeFromFile(const std::string& filePath, CursorPosition<LineCountType> pos) noexcept
{
BUFFER* buffer = load_text_from_file_s(filePath.c_str());
if(buffer == NULL)
{
debug_log_error("Failed to open file: %.*s", filePath.size(), filePath.data());
return;
}
std::string str(reinterpret_cast<const char*>(buf_get_ptr(buffer)), buf_get_element_count(buffer));
insert(pos, str);
buf_free(buffer);
}

void Text::setFontSize(const f32 pointSize) noexcept
{
// update the point sizes for each line
Expand All @@ -606,7 +683,7 @@ namespace SUTK

// update the baseline height
if(m_lines.size() > 0)
m_baselineHeight = m_lines[0]->getBaselineHeight();
m_baselineHeight = getGfxDriver().getTextBaselineHeightInCentimeters(m_pointSize);

updateLinePositions();
}
Expand Down

0 comments on commit 6b6cc52

Please sign in to comment.