D2d offscreen rendering finish up.

This commit is contained in:
jmsgrogan 2023-01-12 09:18:16 +00:00
parent 8c814ce89f
commit c63138c455
32 changed files with 288 additions and 64 deletions

View file

@ -9,6 +9,18 @@ Color::Color(unsigned r, unsigned g, unsigned b, double a)
} }
Color::Color(Name name)
{
if (name == Name::WHITE)
{
Color(255, 255, 255);
}
else
{
Color(255, 255, 255);
}
}
std::shared_ptr<Color> Color::CreateShared(unsigned r, unsigned g, unsigned b, std::shared_ptr<Color> Color::CreateShared(unsigned r, unsigned g, unsigned b,
double a ) double a )
{ {

View file

@ -7,8 +7,16 @@
class Color class Color
{ {
public: public:
enum class Name
{
WHITE
};
Color(unsigned r = 0, unsigned g = 0, unsigned b = 0, double a = 1.0); Color(unsigned r = 0, unsigned g = 0, unsigned b = 0, double a = 1.0);
Color(Name name);
static std::shared_ptr<Color> CreateShared(unsigned r, unsigned g, unsigned b, double a = 1.0); static std::shared_ptr<Color> CreateShared(unsigned r, unsigned g, unsigned b, double a = 1.0);
static std::unique_ptr<Color> Create(unsigned r, unsigned g, unsigned b, double a = 1.0); static std::unique_ptr<Color> Create(unsigned r, unsigned g, unsigned b, double a = 1.0);
static std::unique_ptr<Color> Create(const Color& color); static std::unique_ptr<Color> Create(const Color& color);
@ -41,6 +49,11 @@ public:
return mB + (mG<<8) + (mR<<16); return mB + (mG<<8) + (mR<<16);
} }
static Color White()
{
return { 255, 255, 255, 1 };
}
private: private:
unsigned mR{0}; unsigned mR{0};
unsigned mG{0}; unsigned mG{0};

View file

@ -161,12 +161,10 @@ std::string StringUtils::convert(const std::wstring& input)
} }
#ifdef _WIN32 #ifdef _WIN32
const auto size = ::WideCharToMultiByte(CP_UTF8, 0, &input[0], const auto size = ::WideCharToMultiByte(CP_UTF8, 0, &input[0], (int)input.size(), nullptr, 0, nullptr, nullptr);
(int)input.size(), nullptr, 0, nullptr, nullptr);
std::string result(size, 0); std::string result(size, 0);
::WideCharToMultiByte(CP_UTF8, 0, &input[0], (int)input.size(), ::WideCharToMultiByte(CP_UTF8, 0, &input[0], (int)input.size(), &result[0], size, nullptr, nullptr);
&result[0], size, nullptr, nullptr);
return result; return result;
#else #else
throw std::logic_error("Not implemented"); throw std::logic_error("Not implemented");

View file

@ -46,6 +46,7 @@ public:
&& (mY == rhs.mY) && (mY == rhs.mY)
&& (mZ == rhs.mZ); && (mZ == rhs.mZ);
} }
bool operator!=(const Point& rhs) const bool operator!=(const Point& rhs) const
{ {
return !operator==(rhs); return !operator==(rhs);

View file

@ -8,3 +8,23 @@ Transform::Transform(const Point& location, double scaleX, double scaleY, double
{ {
} }
const Point& Transform::getLocation() const
{
return mLocation;
}
double Transform::getScaleX() const
{
return mScaleX;
}
double Transform::getScaleY() const
{
return mScaleY;
}
double Transform::getScaleZ() const
{
return mScaleZ;
}

View file

@ -7,25 +7,13 @@ class Transform
public: public:
Transform(const Point& location = {}, double scaleX = 1.0, double scaleY = 1.0, double scaleZ = 1.0); Transform(const Point& location = {}, double scaleX = 1.0, double scaleY = 1.0, double scaleZ = 1.0);
const Point& getLocation() const const Point& getLocation() const;
{
return mLocation;
}
double getScaleX() const double getScaleX() const;
{
return mScaleX;
}
double getScaleY() const double getScaleY() const;
{
return mScaleY;
}
double getScaleZ() const double getScaleZ() const;
{
return mScaleZ;
}
bool operator==(const Transform& rhs) const bool operator==(const Transform& rhs) const
{ {

View file

@ -15,31 +15,43 @@ void DirectX2dPainter::finishDrawing()
mD2dInterface->getRenderTarget()->EndDraw(); mD2dInterface->getRenderTarget()->EndDraw();
} }
void DirectX2dPainter::clearBackground() D2D1::ColorF DirectX2dPainter::toD2dColor(const Color& color)
{ {
mD2dInterface->getRenderTarget()->Clear(D2D1::ColorF(D2D1::ColorF::White)); return D2D1::ColorF(color.getR() / 255.0, color.getG() / 255.0, color.getB() / 255.0, static_cast<float>(color.getAlpha()));
}
void DirectX2dPainter::clearBackground(const Color& color)
{
mD2dInterface->getRenderTarget()->Clear(toD2dColor(color));
} }
void DirectX2dPainter::paint(SceneModel* model) void DirectX2dPainter::paint(SceneModel* model)
{ {
auto rt = mD2dInterface->getRenderTarget(); auto rt = mD2dInterface->getRenderTarget();
auto hr = rt->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black), &mWorkingBrush);
if (model->getGeometry()->getType() == AbstractGeometricItem::Type::RECTANGLE) if (model->getGeometry()->getType() == AbstractGeometricItem::Type::RECTANGLE)
{ {
auto rect = dynamic_cast<ntk::Rectangle*>(model->getGeometry()); const auto loc = model->getTransform().getLocation();
const auto loc = rect->getLocation(); const auto scale_x = model->getTransform().getScaleX();
const auto width = rect->getWidth(); const auto scale_y = model->getTransform().getScaleY();
const auto height = rect->getHeight(); D2D1_RECT_F d2d_rect{ static_cast<float>(loc.getX()), static_cast<float>(loc.getY() + scale_x), static_cast<float>(loc.getX() + scale_y), static_cast<float>(loc.getY()) };
D2D1_RECT_F d2d_rect{ static_cast<float>(loc.getX()), static_cast<float>(loc.getY() + height), static_cast<float>(loc.getX() + width), static_cast<float>(loc.getY()) }; if (model->hasFillColor())
{
mSolidBrush->SetColor(toD2dColor(model->getFillColor()));
rt->FillRectangle(d2d_rect, mSolidBrush.Get());
}
rt->FillRectangle(d2d_rect, mWorkingBrush.Get()); if (model->hasOutlineColor())
{
mSolidBrush->SetColor(toD2dColor(model->getOutlineColor()));
rt->DrawRectangle(d2d_rect, mSolidBrush.Get(), 1.0f);
}
} }
} }
void DirectX2dPainter::setD2dInterface(DirectX2dInterface* d2dIterface) void DirectX2dPainter::setD2dInterface(DirectX2dInterface* d2dIterface)
{ {
mD2dInterface = d2dIterface; mD2dInterface = d2dIterface;
auto hr = mD2dInterface->getRenderTarget()->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black, 1.0f), &mSolidBrush);
} }

View file

@ -1,5 +1,7 @@
#pragma once #pragma once
#include "Color.h"
#include <wrl.h> #include <wrl.h>
class SceneModel; class SceneModel;
@ -7,12 +9,17 @@ class DirectX2dInterface;
struct ID2D1SolidColorBrush; struct ID2D1SolidColorBrush;
namespace D2D1
{
class ColorF;
}
class DirectX2dPainter class DirectX2dPainter
{ {
public: public:
void startDrawing(); void startDrawing();
void clearBackground(); void clearBackground(const Color& color);
void finishDrawing(); void finishDrawing();
@ -21,9 +28,9 @@ public:
void setD2dInterface(DirectX2dInterface* d2dIterface); void setD2dInterface(DirectX2dInterface* d2dIterface);
private: private:
void createRectangle(); static D2D1::ColorF toD2dColor(const Color& color);
Microsoft::WRL::ComPtr<ID2D1SolidColorBrush> mWorkingBrush; Microsoft::WRL::ComPtr<ID2D1SolidColorBrush> mSolidBrush;
DirectX2dInterface* mD2dInterface{ nullptr }; DirectX2dInterface* mD2dInterface{ nullptr };
}; };

View file

@ -24,7 +24,7 @@ void DirectXMesh::update(DrawingContext* context, ID3D12Device* device)
const auto width = float(context->getSurface()->getWidth()); const auto width = float(context->getSurface()->getWidth());
const auto height = float(context->getSurface()->getHeight()); const auto height = float(context->getSurface()->getHeight());
auto model_color = mModel->getColor().getAsVectorDouble(); auto model_color = mModel->getFillColor().getAsVectorDouble();
std::vector<float> color = { float(model_color[0]), float(model_color[1]), float(model_color[2]), float(model_color[3]) }; std::vector<float> color = { float(model_color[0]), float(model_color[1]), float(model_color[2]), float(model_color[3]) };
auto transform = mModel->getTransform(); auto transform = mModel->getTransform();

View file

@ -111,7 +111,7 @@ void DirectXPainter::paint()
auto scene = mDrawingContext->getSurface()->getScene(); auto scene = mDrawingContext->getSurface()->getScene();
m2dPainter->startDrawing(); m2dPainter->startDrawing();
m2dPainter->clearBackground(); m2dPainter->clearBackground(scene->getBackgroundColor());
for (const auto item : scene->getItems()) for (const auto item : scene->getItems())
{ {

View file

@ -11,6 +11,10 @@ list(APPEND publishing_HEADERS
pdf/PdfWriter.h pdf/PdfWriter.h
plotting/GraphPlotter.h plotting/GraphPlotter.h
plotting/SvgConverter.h plotting/SvgConverter.h
latex/LatexDocument.h
latex/LatexMathExpression.h
latex/LatexSymbols.h
DocumentConverter.h
) )
list(APPEND publishing_LIB_INCLUDES list(APPEND publishing_LIB_INCLUDES
@ -24,6 +28,9 @@ list(APPEND publishing_LIB_INCLUDES
pdf/PdfStream.cpp pdf/PdfStream.cpp
pdf/PdfXRefTable.cpp pdf/PdfXRefTable.cpp
pdf/PdfWriter.cpp pdf/PdfWriter.cpp
latex/LatexDocument.cpp
latex/LatexMathExpression.cpp
latex/LatexSymbols.cpp
plotting/GraphPlotter.h plotting/GraphPlotter.h
plotting/SvgConverter.cpp plotting/SvgConverter.cpp
DocumentConverter.cpp DocumentConverter.cpp
@ -35,6 +42,7 @@ target_include_directories(publishing PUBLIC
${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/pdf ${CMAKE_CURRENT_SOURCE_DIR}/pdf
${CMAKE_CURRENT_SOURCE_DIR}/plotting ${CMAKE_CURRENT_SOURCE_DIR}/plotting
${CMAKE_CURRENT_SOURCE_DIR}/latex
) )
set_target_properties( publishing PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON ) set_target_properties( publishing PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON )
target_link_libraries( publishing PUBLIC core web graphics visual_elements) target_link_libraries( publishing PUBLIC core web graphics visual_elements)

View file

View file

View file

@ -0,0 +1,41 @@
#pragma once
#include "LatexSymbols.h"
#include <string>
#include <memory>
#include <vector>
class LatexMathExpression
{
public:
LatexMathExpression(const std::string& expression = {})
: mRawExpression(expression)
{
}
void parse()
{
for (auto c : mRawExpression)
{
}
}
const std::vector<LatexMathSymbol>& getSymbols() const
{
return mSymbols;
}
private:
unsigned mOpenTagCount{ 0 };
std::string mRawExpression;
std::unique_ptr<LatexMathExpression> mSuperScriptExpr;
std::unique_ptr<LatexMathExpression> mSubScriptExpr;
std::unique_ptr<LatexMathExpression> mEnclosedExpr;
std::vector<LatexMathSymbol> mSymbols;
};

View file

View file

@ -0,0 +1,26 @@
#pragma once
#include <string>
#include <unordered_map>
#include <optional>
struct LatexMathSymbol
{
enum class Type
{
RAW,
TAG,
RELATIONAL,
RELATIONAL_TAG,
ENCLOSING,
ENCLOSING_TAG
};
std::string mName;
std::wstring mUnicode;
};
class LatexSymbolLookup
{
public:
std::unordered_map<std::string, LatexMathSymbol> mTags;
};

View file

@ -43,7 +43,7 @@ std::unique_ptr<SvgDocument> SvgConverter::convert(Scene* scene)
count++; count++;
} }
svg_tri->setPoints(points); svg_tri->setPoints(points);
svg_tri->setFill(item->getColor()); svg_tri->setFill(item->getFillColor());
doc->getRoot()->addChild(std::move(svg_tri)); doc->getRoot()->addChild(std::move(svg_tri));
if (scene->shouldShowMeshOutline()) if (scene->shouldShowMeshOutline())

View file

@ -61,7 +61,7 @@ void CircleNode::update(SceneInfo* sceneInfo)
{ {
mBackgroundItem = std::make_unique<SceneModel>(std::move(mesh)); mBackgroundItem = std::make_unique<SceneModel>(std::move(mesh));
mBackgroundItem->setName(mName + "_Model"); mBackgroundItem->setName(mName + "_Model");
mBackgroundItem->updateUniformColor(mFillColor); mBackgroundItem->setFillColor(mFillColor);
} }
else else
{ {
@ -78,7 +78,7 @@ void CircleNode::update(SceneInfo* sceneInfo)
if (mMaterialIsDirty) if (mMaterialIsDirty)
{ {
mBackgroundItem->updateUniformColor(mFillColor); mBackgroundItem->setFillColor(mFillColor);
mMaterialIsDirty = false; mMaterialIsDirty = false;
} }
} }

View file

@ -3,6 +3,7 @@
#include "Rectangle.h" #include "Rectangle.h"
#include "MeshPrimitives.h" #include "MeshPrimitives.h"
#include "SceneInfo.h"
#include <iostream> #include <iostream>
@ -69,21 +70,27 @@ void RectangleNode::setHeight(double height)
} }
} }
void RectangleNode::createOrUpdateGeometry(SceneInfo* sceneInfo)
{
if (sceneInfo->mSupportsGeometryPrimitives)
{
auto rect = std::make_unique<ntk::Rectangle>(Point{ 0, 0 }, 1, 1);
mBackgroundItem = std::make_unique<SceneModel>(std::move(rect));
}
else
{
auto mesh = MeshPrimitives::buildRectangleAsTriMesh();
mBackgroundItem = std::make_unique<SceneModel>(std::move(mesh));
}
mBackgroundItem->setName(mName + "_Model");
}
void RectangleNode::update(SceneInfo* sceneInfo) void RectangleNode::update(SceneInfo* sceneInfo)
{ {
if (!mBackgroundItem || mGeometryIsDirty) if (!mBackgroundItem || mGeometryIsDirty)
{ {
auto mesh = MeshPrimitives::buildRectangleAsTriMesh(); createOrUpdateGeometry(sceneInfo);
if (!mBackgroundItem)
{
mBackgroundItem = std::make_unique<SceneModel>(std::move(mesh));
mBackgroundItem->setName(mName + "_Model");
}
else
{
mBackgroundItem->updateMesh(std::move(mesh));
}
mGeometryIsDirty = false; mGeometryIsDirty = false;
} }
@ -95,7 +102,14 @@ void RectangleNode::update(SceneInfo* sceneInfo)
if (mMaterialIsDirty) if (mMaterialIsDirty)
{ {
mBackgroundItem->updateUniformColor(mFillColor); if (mHasFillColor)
{
mBackgroundItem->setFillColor(mFillColor);
}
if (mHasStrokeColor)
{
mBackgroundItem->setOutlineColor(mStrokeColor);
}
mMaterialIsDirty = false; mMaterialIsDirty = false;
} }
} }

View file

@ -21,7 +21,9 @@ public:
void setHeight(double height); void setHeight(double height);
void update(SceneInfo* sceneInfo) override; void update(SceneInfo* sceneInfo) override;
private: private:
void createOrUpdateGeometry(SceneInfo* sceneInfo);
double mWidth{1}; double mWidth{1};
double mHeight{1}; double mHeight{1};

View file

@ -131,7 +131,7 @@ void GridNode::update(SceneInfo* sceneInfo)
if (mMaterialIsDirty) if (mMaterialIsDirty)
{ {
mOutlineModel->updateUniformColor(mStrokeColor); mOutlineModel->setFillColor(mStrokeColor);
mMaterialIsDirty = false; mMaterialIsDirty = false;
} }

View file

@ -16,6 +16,9 @@ public:
void setStrokeColor(const Color& color); void setStrokeColor(const Color& color);
protected: protected:
bool mHasFillColor{ false };
bool mHasStrokeColor{ true };
Color mFillColor; Color mFillColor;
Color mStrokeColor; Color mStrokeColor;
bool mMaterialIsDirty{true}; bool mMaterialIsDirty{true};

View file

@ -83,7 +83,7 @@ void MeshNode::update(SceneInfo* sceneInfo)
if (mMaterialIsDirty) if (mMaterialIsDirty)
{ {
mModel->updateUniformColor(mFillColor); mModel->setFillColor(mFillColor);
mMaterialIsDirty = false; mMaterialIsDirty = false;
} }
} }

View file

@ -165,7 +165,7 @@ void TextNode::update(SceneInfo* sceneInfo)
if (mMaterialIsDirty) if (mMaterialIsDirty)
{ {
mTextItem->updateUniformColor(mFillColor); mTextItem->setFillColor(mFillColor);
mMaterialIsDirty = false; mMaterialIsDirty = false;
} }
} }

View file

@ -8,7 +8,8 @@
Scene::Scene() Scene::Scene()
: mRootNode(std::make_unique<RootNode>()), : mRootNode(std::make_unique<RootNode>()),
mSceneInfo(std::make_unique<SceneInfo>()) mSceneInfo(std::make_unique<SceneInfo>()),
mBackGroundColor(Color(255, 255, 255))
{ {
mRootNode->setName("Scene_RootNode"); mRootNode->setName("Scene_RootNode");
} }
@ -34,6 +35,16 @@ bool Scene::isEmpty() const
return mRootNode->getNumChildren() == 0; return mRootNode->getNumChildren() == 0;
} }
const Color& Scene::getBackgroundColor() const
{
return mBackGroundColor;
}
void Scene::setBackgroundColor(const Color& color)
{
mBackGroundColor = color;
}
void Scene::updateNode(AbstractVisualNode* node) void Scene::updateNode(AbstractVisualNode* node)
{ {
for (auto child : node->getChildren()) for (auto child : node->getChildren())

View file

@ -2,6 +2,7 @@
#include "TextData.h" #include "TextData.h"
#include "SceneInfo.h" #include "SceneInfo.h"
#include "Color.h"
#include <vector> #include <vector>
#include <memory> #include <memory>
@ -21,10 +22,14 @@ public:
const std::vector<SceneItem*>& getItems() const; const std::vector<SceneItem*>& getItems() const;
const Color& getBackgroundColor() const;
bool isEmpty() const; bool isEmpty() const;
bool shouldShowMeshOutline() const; bool shouldShowMeshOutline() const;
void setBackgroundColor(const Color&);
void setShowMeshOutline(bool shouldShow); void setShowMeshOutline(bool shouldShow);
void setFontsManager(FontsManager* fontsManager); void setFontsManager(FontsManager* fontsManager);
@ -35,6 +40,7 @@ public:
private: private:
void updateNode(AbstractVisualNode* node); void updateNode(AbstractVisualNode* node);
Color mBackGroundColor;
std::unique_ptr<RootNode> mRootNode; std::unique_ptr<RootNode> mRootNode;
std::vector<SceneItem*> mSceneItems; std::vector<SceneItem*> mSceneItems;
std::unique_ptr<SceneInfo> mSceneInfo; std::unique_ptr<SceneInfo> mSceneInfo;

View file

@ -5,9 +5,14 @@ SceneItem::SceneItem()
} }
const Color& SceneItem::getColor() const const Color& SceneItem::getFillColor() const
{ {
return mUniformColor; return mFillColor;
}
const Color& SceneItem::getOutlineColor() const
{
return mOutlineColor;
} }
const Transform& SceneItem::getTransform() const const Transform& SceneItem::getTransform() const
@ -20,18 +25,38 @@ bool SceneItem::isVisible() const
return mIsVisible; return mIsVisible;
} }
bool SceneItem::hasFillColor() const
{
return mHasFillColor;
}
bool SceneItem::hasOutlineColor() const
{
return mHasOutlineColor;
}
void SceneItem::setIsVisible(bool isVisible) void SceneItem::setIsVisible(bool isVisible)
{ {
mIsVisible = isVisible; mIsVisible = isVisible;
} }
void SceneItem::updateUniformColor(const Color& color) void SceneItem::setFillColor(const Color& color)
{ {
if (mUniformColor != color) if (!mHasFillColor || mFillColor != color)
{ {
mColorIsDirty = true; mColorIsDirty = true;
mUniformColor = color; mFillColor = color;
mHasFillColor = true;
}
}
void SceneItem::setOutlineColor(const Color& color)
{
if (!mHasOutlineColor || mOutlineColor != color)
{
mColorIsDirty = true;
mOutlineColor = color;
mHasOutlineColor = true;
} }
} }

View file

@ -20,17 +20,25 @@ public:
virtual ~SceneItem() = default; virtual ~SceneItem() = default;
const Color& getColor() const; const Color& getFillColor() const;
const Color& getOutlineColor() const;
const Transform& getTransform() const; const Transform& getTransform() const;
virtual Type getType() const = 0; virtual Type getType() const = 0;
bool hasFillColor() const;
bool hasOutlineColor() const;
bool isVisible() const; bool isVisible() const;
void setIsVisible(bool isVisible); void setIsVisible(bool isVisible);
void updateUniformColor(const Color& color); void setOutlineColor(const Color& color);
void setFillColor(const Color& color);
void updateTransform(const Transform& transform); void updateTransform(const Transform& transform);
@ -46,7 +54,12 @@ public:
protected: protected:
Transform mTransform; Transform mTransform;
Color mUniformColor;
bool mHasFillColor{ false };
Color mFillColor;
bool mHasOutlineColor{ false };
Color mOutlineColor;
bool mColorIsDirty{true}; bool mColorIsDirty{true};
bool mTransformIsDirty{true}; bool mTransformIsDirty{true};

View file

@ -18,13 +18,14 @@
TEST_CASE(TestD2dOffScreenRendering, "graphics") TEST_CASE(TestD2dOffScreenRendering, "graphics")
{ {
auto surface = std::make_unique<DrawingSurface>(); auto surface = std::make_unique<DrawingSurface>();
surface->setSize(100, 100); surface->setSize(800, 800);
auto drawing_context = std::make_unique<DrawingContext>(surface.get()); auto drawing_context = std::make_unique<DrawingContext>(surface.get());
auto rect = std::make_unique<RectangleNode>(DiscretePoint(10, 10), 10.0, 20.0); auto rect = std::make_unique<RectangleNode>(Point(10, 10), 200.0, 200.0);
auto scene = surface->getScene(); auto scene = surface->getScene();
//scene->setBackgroundColor(Color(100, 100, 0));
scene->addNode(rect.get()); scene->addNode(rect.get());
drawing_context->paint(); drawing_context->paint();

View file

@ -2,6 +2,7 @@ set(PUBLISHING_UNIT_TEST_FILES
publishing/TestPdfWriter.cpp publishing/TestPdfWriter.cpp
publishing/TestDocumentConverter.cpp publishing/TestDocumentConverter.cpp
publishing/TestSvgConverter.cpp publishing/TestSvgConverter.cpp
publishing/TestLatexConverter.cpp
PARENT_SCOPE PARENT_SCOPE
) )

View file

@ -0,0 +1,22 @@
#include "TestFramework.h"
#include "TestUtils.h"
#include "StringUtils.h"
#include "File.h"
#include <iostream>
TEST_CASE(TestLatexConverter, "publishing")
{
std::wstring out = L"\u03A8";
std::wcout << out << std::endl;
std::string out_c = StringUtils::convert(out);
File file(TestUtils::getTestOutputDir(__FILE__) / "utf8_render.dat");
file.writeText(out_c);
//std::cout << out_c << std::endl;
};