Update text rendering.

This commit is contained in:
jmsgrogan 2023-01-18 17:31:16 +00:00
parent 8536908eab
commit 8130308f7f
27 changed files with 503 additions and 77 deletions

View file

@ -34,22 +34,46 @@ void DirectX2dPainter::paint(SceneModel* model)
if (model->getGeometry()->getType() == AbstractGeometricItem::Type::RECTANGLE)
{
auto rect = dynamic_cast<ntk::Rectangle*>(model->getGeometry());
const auto loc = model->getTransform().getLocation();
const auto scale_x = model->getTransform().getScaleX();
const auto scale_y = model->getTransform().getScaleY();
D2D1_RECT_F d2d_rect{ static_cast<float>(loc.getX()), static_cast<float>(loc.getY() + scale_y), static_cast<float>(loc.getX() + scale_x), static_cast<float>(loc.getY()) };
if (model->hasFillColor())
{
mSolidBrush->SetColor(toD2dColor(model->getFillColor()));
rt->FillRectangle(d2d_rect, mSolidBrush.Get());
const auto min_x = static_cast<float>(loc.getX());
const auto max_x = static_cast<float>(loc.getX() + rect->getWidth()* scale_x);
const auto min_y = static_cast<float>(loc.getY());
const auto max_y = static_cast<float>(loc.getY() + rect->getHeight() * scale_y);
D2D1_RECT_F d2d_rect{ min_x, max_y, max_x, min_y };
if (rect->getRadius() == 0.0)
{
if (model->hasFillColor())
{
mSolidBrush->SetColor(toD2dColor(model->getFillColor()));
rt->FillRectangle(d2d_rect, mSolidBrush.Get());
}
if (model->hasOutlineColor())
{
mSolidBrush->SetColor(toD2dColor(model->getOutlineColor()));
rt->DrawRectangle(d2d_rect, mSolidBrush.Get(), 1.0f);
}
}
if (model->hasOutlineColor())
else
{
mSolidBrush->SetColor(toD2dColor(model->getOutlineColor()));
rt->DrawRectangle(d2d_rect, mSolidBrush.Get(), 1.0f);
}
D2D1_ROUNDED_RECT rounded_rect{ d2d_rect , static_cast<float>(rect->getRadius()), static_cast<float>(rect->getRadius()) };
if (model->hasFillColor())
{
mSolidBrush->SetColor(toD2dColor(model->getFillColor()));
rt->FillRoundedRectangle(rounded_rect, mSolidBrush.Get());
}
if (model->hasOutlineColor())
{
mSolidBrush->SetColor(toD2dColor(model->getOutlineColor()));
rt->DrawRoundedRectangle(rounded_rect, mSolidBrush.Get(), 1.0f);
}
}
}
else if (model->getGeometry()->getType() == AbstractGeometricItem::Type::CIRCLE)
{

View file

@ -30,28 +30,40 @@ void DirectXTextPainter::setD2dInterface(DirectX2dInterface* d2dIterface)
mD2dInterface->getRenderTarget()->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black), &mTextBrush);
}
void DirectXTextPainter::updateTextFormat(const FontItem& font)
void DirectXTextPainter::updateTextFormat(SceneText* text)
{
mD2dInterface->getDirectWriteFactory()->CreateTextFormat(
UnicodeUtils::utf8ToUtf16WString(font.getFaceName()).c_str(),
UnicodeUtils::utf8ToUtf16WString(text->getTextData().mFont.getFaceName()).c_str(),
nullptr,
DWRITE_FONT_WEIGHT_NORMAL,
DWRITE_FONT_STYLE_NORMAL,
DWRITE_FONT_STRETCH_NORMAL,
static_cast<float>(font.getSize()),
static_cast<float>(text->getTextData().mFont.getSize()),
L"en-us",
&mTextFormat
);
//mTextFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER);
//mTextFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER);
mTextFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER);
mTextFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER);
mTextBrush->SetColor(toD2dColor(text->getFillColor()));
}
D2D1::ColorF DirectXTextPainter::toD2dColor(const Color& color)
{
return D2D1::ColorF(static_cast<float>(color.getR() / 255.0), static_cast<float>(color.getG() / 255.0),
static_cast<float>(color.getB() / 255.0), static_cast<float>(color.getAlpha()));
}
void DirectXTextPainter::paint(SceneText* text, DrawingContext* context)
{
const auto location = text->getTransform().getLocation();
D2D1_RECT_F textRect = D2D1::RectF(static_cast<float>(location.getX()), static_cast<float>(location.getY()), static_cast<float>(location.getX() + 200), static_cast<float>(location.getY() + 100));
updateTextFormat(text->getTextData().mFont);
const auto width = static_cast<float>(text->getTextWidth());
const auto height = static_cast<float>(text->getTextHeight());
D2D1_RECT_F textRect = D2D1::RectF(static_cast<float>(location.getX()), static_cast<float>(location.getY()), static_cast<float>(location.getX() + width), static_cast<float>(location.getY() + height));
updateTextFormat(text);
auto content = UnicodeUtils::utf8ToUtf16WString(text->getTextData().mContent);

View file

@ -1,6 +1,7 @@
#pragma once
#include "FontItem.h"
#include "Color.h"
#include <wrl.h>
#include <dwrite.h>
@ -32,7 +33,9 @@ public:
void setD2dInterface(DirectX2dInterface* d2dIterface);
private:
void updateTextFormat(const FontItem& font);
void updateTextFormat(SceneText* text);
D2D1::ColorF toD2dColor(const Color& color);
DirectX2dInterface* mD2dInterface{ nullptr };
Microsoft::WRL::ComPtr<ID2D1SolidColorBrush> mTextBrush;

View file

@ -23,6 +23,8 @@ list(APPEND visual_elements_LIB_INCLUDES
svg/SvgReader.h
svg/SvgShapeElement.h
svg/SvgElement.h
svg/SvgTextElement.h
svg/SvgTextElement.cpp
svg/elements/SvgShapeElements.h
svg/SvgDocument.cpp
svg/SvgReader.cpp

View file

@ -42,7 +42,7 @@ void RectangleNode::setWidth(double width)
{
if (mWidth != width)
{
mTransformIsDirty = true;
mGeometryIsDirty = true;
mWidth = width;
}
}
@ -51,7 +51,7 @@ void RectangleNode::setHeight(double height)
{
if (mHeight != height)
{
mTransformIsDirty = true;
mGeometryIsDirty = true;
mHeight = height;
}
}
@ -71,7 +71,7 @@ void RectangleNode::createOrUpdateGeometry(SceneInfo* sceneInfo)
{
if (sceneInfo->mSupportsGeometryPrimitives)
{
auto rect = std::make_unique<ntk::Rectangle>(Point{ 0, 0 }, 1, 1);
auto rect = std::make_unique<ntk::Rectangle>(Point{ 0, 0 }, mWidth, mHeight);
rect->setRadius(mRadius);
mBackgroundItem = std::make_unique<SceneModel>(std::move(rect));
}
@ -87,7 +87,7 @@ void RectangleNode::createOrUpdateGeometry(SceneInfo* sceneInfo)
{
if (sceneInfo->mSupportsGeometryPrimitives)
{
auto rect = std::make_unique<ntk::Rectangle>(Point{ 0, 0 }, 1, 1);
auto rect = std::make_unique<ntk::Rectangle>(Point{ 0, 0 }, mWidth, mHeight);
rect->setRadius(mRadius);
mBackgroundItem->updateGeometry(std::move(rect));
}
@ -96,5 +96,5 @@ void RectangleNode::createOrUpdateGeometry(SceneInfo* sceneInfo)
void RectangleNode::updateTransform()
{
mBackgroundItem->updateTransform({ mLocation, mWidth, mHeight });
mBackgroundItem->updateTransform({ mLocation });
}

View file

@ -161,7 +161,7 @@ void TextNode::update(SceneInfo* sceneInfo)
if (mContentIsDirty || mLinesAreDirty)
{
dynamic_cast<SceneText*>(mTextItem.get())->setTextData(mTextData);
mTextItem->setTextData(mTextData);
mContentIsDirty = false;
mLinesAreDirty = false;
}
@ -169,6 +169,8 @@ void TextNode::update(SceneInfo* sceneInfo)
if (mTransformIsDirty)
{
mTextItem->updateTransform({mLocation});
mTextItem->setTextWidth(mWidth);
mTextItem->setTextHeight(mHeight);
mTransformIsDirty = false;
}

View file

@ -4,6 +4,8 @@
#include "FontItem.h"
#include "TextData.h"
#include "Bounds.h"
#include "SceneText.h"
#include <memory>
#include <string>
@ -47,7 +49,7 @@ private:
double mWidth{1};
double mHeight{1};
std::unique_ptr<SceneItem> mTextItem;
std::unique_ptr<SceneText> mTextItem;
};
using TextNodetr = std::unique_ptr<TextNode>;

View file

@ -23,3 +23,31 @@ void SceneText::setTextData(const TextData& data)
mTextData = data;
}
}
double SceneText::getTextWidth() const
{
return mTextWidth;
}
double SceneText::getTextHeight() const
{
return mTextHeight;
}
void SceneText::setTextWidth(double width)
{
if (mTextWidth != width)
{
mTextWidth = width;
mTextGeometryIsDirty = true;
}
}
void SceneText::setTextHeight(double height)
{
if (mTextHeight != height)
{
mTextHeight = height;
mTextGeometryIsDirty = true;
}
}

View file

@ -10,11 +10,21 @@ public:
Type getType() const override;
double getTextWidth() const;
double getTextHeight() const;
const TextData& getTextData() const;
void setTextWidth(double width);
void setTextHeight(double height);
void setTextData(const TextData& content);
private:
bool mTextGeometryIsDirty{true};
TextData mTextData;
double mTextWidth{ 0.0 };
double mTextHeight{ 0.0 };
};

View file

@ -0,0 +1,53 @@
#include "SvgTextElement.h"
#include "XmlAttribute.h"
#include <sstream>
SvgTextElement::SvgTextElement()
:SvgElement("text")
{
}
void SvgTextElement::setLocation(const Point& loc)
{
auto x = std::make_unique<XmlAttribute>("x");
auto y = std::make_unique<XmlAttribute>("y");
x->setValue(std::to_string(loc.getX()));
y->setValue(std::to_string(loc.getY()));
addAttribute(std::move(x));
addAttribute(std::move(y));
}
void SvgTextElement::setContent(const std::string& content)
{
setText(content);
}
void SvgTextElement::setFill(const Color& fill)
{
auto attr = std::make_unique<XmlAttribute>("fill");
std::stringstream sstr;
sstr << "rgb(" << fill.toString() << ")";
attr->setValue(sstr.str());
addAttribute(std::move(attr));
}
void SvgTextElement::setFontFamily(const std::string& family)
{
auto attr = std::make_unique<XmlAttribute>("font-family");
attr->setValue(family);
addAttribute(std::move(attr));
}
void SvgTextElement::setFontSize(float size)
{
auto attr = std::make_unique<XmlAttribute>("font-size");
attr->setValue(std::to_string(size));
addAttribute(std::move(attr));
}

View file

@ -0,0 +1,21 @@
#pragma once
#include "SvgElement.h"
#include "Point.h"
#include "Color.h"
class SvgTextElement : public SvgElement
{
public:
SvgTextElement();
void setLocation(const Point& loc);
void setContent(const std::string& content);
void setFill(const Color& fill);
void setFontFamily(const std::string& family);
void setFontSize(float size);
};

View file

@ -124,6 +124,15 @@ void SvgRectangle::setHeight(double h)
addAttribute(std::move(height));
}
void SvgRectangle::setRadius(double radius)
{
auto rx = std::make_unique<XmlAttribute>("rx");
rx->setValue(std::to_string(radius));
addAttribute(std::move(rx));
}
SvgPolygon::SvgPolygon()
: SvgShapeElement("polygon")

View file

@ -43,6 +43,8 @@ public:
void setWidth(double width);
void setHeight(double height);
void setRadius(double radius);
};
class SvgPolygon : public SvgShapeElement