Add geometry handling.

This commit is contained in:
jmsgrogan 2022-05-15 14:58:31 +01:00
parent 9c116b1efd
commit c1389218f2
37 changed files with 294 additions and 278 deletions

View file

@ -3,11 +3,6 @@
class Color class Color
{ {
unsigned mR;
unsigned mG;
unsigned mB;
double mAlpha;
public: public:
Color(unsigned r, unsigned g, unsigned b, double a = 1.0); Color(unsigned r, unsigned g, unsigned b, double a = 1.0);
@ -19,6 +14,12 @@ public:
unsigned GetG() const; unsigned GetG() const;
unsigned GetB() const; unsigned GetB() const;
double GetAlpha() const; double GetAlpha() const;
private:
unsigned mR{0};
unsigned mG{0};
unsigned mB{0};
double mAlpha{0.0};
}; };
using ColorPtr = std::shared_ptr<Color>; using ColorPtr = std::shared_ptr<Color>;

View file

@ -0,0 +1,13 @@
#pragma once
class Rectangle;
class Grid;
class AbstractGeometricItem
{
public:
Rectangle GetBounds() const = 0;
void Sample(Grid* grid) const = 0;
};

View file

@ -1,7 +1,21 @@
list(APPEND geometry_LIB_INCLUDES list(APPEND geometry_LIB_INCLUDES
AbstractGeometricItem.h
Circle.h
Circle.cpp
DiscretePoint.h
DiscretePoint.cpp DiscretePoint.cpp
Grid.h
Grid.cpp
Line.h
Line.cpp
Path.h
Path.cpp
Point.h
Point.cpp Point.cpp
Rectangle.cpp) Rectangle.h
Rectangle.cpp
Triangle.h
Triangle.cpp)
# add the library # add the library

0
src/geometry/Circle.cpp Normal file
View file

0
src/geometry/Circle.h Normal file
View file

0
src/geometry/Grid.cpp Normal file
View file

56
src/geometry/Grid.h Normal file
View file

@ -0,0 +1,56 @@
#pragma once
#include "Rectangle.h"
#include <vector>
class Grid
{
public:
Grid(const Rectangle& bounds)
: mBounds(bounds)
{
mValues = std::vector<double>(mNumX*mNumY, 0.0);
}
Rectangle GetBounds() const
{
return mBounds;
}
double GetXSpacing() const
{
return mBounds.GetWidth()/double(mNumX);
}
double GetYSpacing() const
{
return mBounds.GetHeight()/double(mNumY);
}
std::vector<double> GetValues() const
{
return mValues;
}
void ResetBounds(const Rectangle& bounds)
{
mBounds = bounds;
mValues = std::vector<double>(mNumX*mNumY, 0.0);
}
void SetValues(const std::vector<std::size_t>& indices, double value)
{
for (auto index : indices)
{
mValues[index] = value;
}
}
private:
Rectangle mBounds;
std::vector<double> mValues;
unsigned mNumX{5};
unsigned mNumY{5};
};

0
src/geometry/Line.cpp Normal file
View file

0
src/geometry/Line.h Normal file
View file

0
src/geometry/Path.cpp Normal file
View file

0
src/geometry/Path.h Normal file
View file

View file

@ -1,12 +1,10 @@
#pragma once #pragma once
#include <memory> #include <memory>
#include <cmath>
class Point class Point
{ {
double mX;
double mY;
public: public:
Point(double x, double y); Point(double x, double y);
@ -14,6 +12,36 @@ public:
~Point(); ~Point();
std::shared_ptr<Point> Create(double x, double y); std::shared_ptr<Point> Create(double x, double y);
double GetX() const
{
return mX;
}
double GetY() const
{
return mY;
}
double GetDistance(const Point& point) const
{
return std::sqrt(mX*point.GetX() + mY*point.GetY());
}
double GetDeltaX(const Point& point) const
{
return point.GetX() - mX;
}
double GetDeltaY(const Point& point) const
{
return point.GetY() - mY;
}
private:
double mX;
double mY;
}; };
using PointPtr = std::shared_ptr<Point>; using PointPtr = std::shared_ptr<Point>;

View file

@ -1,7 +1,40 @@
#pragma once #pragma once
#include "AbstractGeometricItem.h"
#include "Point.h"
class Rectangle class Rectangle : public AbstractGeometricItem
{
public:
Rectangle(const Point& bottomLeft, const Point& topRight)
: mBottomLeft(bottomLeft),
mTopRight(topRight)
{ {
}
Rectangle GetBounds() const override
{
return Rectangle(mBottomLeft, mTopRight);
}
void Sample(Grid* grid) const override
{
}
double GetHeight() const
{
return mBottomLeft.GetDeltaY(mTopRight);
}
double GetWidth() const
{
return mBottomLeft.GetDeltaX(mTopRight);
}
private:
Point mBottomLeft;
Point mTopRight;
}; };

View file

0
src/geometry/Triangle.h Normal file
View file

View file

@ -4,33 +4,7 @@ set(platform_HEADERS "")
set(platform_LIBS "") set(platform_LIBS "")
if (UNIX) if (UNIX)
find_package(PkgConfig) list(APPEND platform_LIBSs
PKG_CHECK_MODULES(PC_CAIRO cairo)
FIND_PATH(CAIRO_INCLUDE_DIRS
NAMES cairo.h
HINTS ${PC_CAIRO_INCLUDEDIR}
${PC_CAIRO_INCLUDE_DIRS}
PATH_SUFFIXES cairo
)
FIND_LIBRARY(CAIRO_LIBRARIES
NAMES cairo
HINTS ${PC_CAIRO_LIBDIR}
${PC_CAIRO_LIBRARY_DIRS}
)
list(APPEND platform_LIB_INCLUDES
cairo/CairoInterface.cpp
cairo/CairoDrawingSurface.cpp
cairo/CairoDrawingContext.cpp
)
list(APPEND platform_INCLUDE_DIRS
${CAIRO_INCLUDE_DIRS}
)
list(APPEND platform_HEADERS
cairo/CairoInterface.h
)
list(APPEND platform_LIBS
${CAIRO_LIBRARIES}
GL GL
) )
else() else()
@ -43,6 +17,7 @@ list(APPEND graphics_LIB_INCLUDES
DrawingContext.cpp DrawingContext.cpp
DrawingManager.cpp DrawingManager.cpp
DrawingSurface.cpp DrawingSurface.cpp
Rasterizer.cpp
opengl/OpenGlInterface.cpp opengl/OpenGlInterface.cpp
${platform_LIB_INCLUDES} ${platform_LIB_INCLUDES}
) )
@ -50,6 +25,7 @@ list(APPEND graphics_LIB_INCLUDES
list(APPEND graphics_HEADERS list(APPEND graphics_HEADERS
opengl/OpenGlInterface.h opengl/OpenGlInterface.h
${platform_HEADERS} ${platform_HEADERS}
Rasterizer.h
INativeDrawingSurface.h INativeDrawingSurface.h
INativeDrawingContext.h) INativeDrawingContext.h)

View file

@ -1,6 +1,7 @@
#include "DrawingContext.h" #include "DrawingContext.h"
#include "INativeDrawingContext.h" #include "INativeDrawingContext.h"
#include "AbstractGeometricItem.h"
std::unique_ptr<DrawingContext> DrawingContext::Create() std::unique_ptr<DrawingContext> DrawingContext::Create()
{ {
@ -16,3 +17,18 @@ INativeDrawingContext* DrawingContext::GetNativeContext()
{ {
return mNativeDrawingContext.get(); return mNativeDrawingContext.get();
} }
void DrawingContext::AddDrawable(AbstractGeometricItemPtr item)
{
mItems.push_back(std::move(item));
}
unsigned DrawingContext::GetNumItems() const
{
return mItems.size();
}
AbstractGeometricItem* DrawingContext::GetDrawable(unsigned idx) const
{
return mItems[idx].get();
}

View file

@ -1,8 +1,11 @@
#pragma once #pragma once
#include <memory> #include <memory>
#include <vector>
class INativeDrawingContext; class INativeDrawingContext;
class AbstractGeometricItem;
using AbstractGeometricItemPtr = std::unique_ptr<AbstractGeometricItem>;
class DrawingContext class DrawingContext
{ {
@ -15,8 +18,15 @@ public:
INativeDrawingContext* GetNativeContext(); INativeDrawingContext* GetNativeContext();
unsigned GetNumItems() const;
void AddDrawable(AbstractGeometricItemPtr item);
AbstractGeometricItem* GetDrawable(unsigned idx) const;
private: private:
std::vector<std::unique_ptr<AbstractGeometricItem> > mItems;
std::unique_ptr<INativeDrawingContext> mNativeDrawingContext; std::unique_ptr<INativeDrawingContext> mNativeDrawingContext;
}; };

View file

@ -3,15 +3,12 @@
#include "INativeDrawingContext.h" #include "INativeDrawingContext.h"
#include "DrawingSurface.h" #include "DrawingSurface.h"
#include "DrawingContext.h" #include "DrawingContext.h"
#ifdef __linux__ #include "Rasterizer.h"
#include "CairoInterface.h"
#endif
DrawingManager::DrawingManager() DrawingManager::DrawingManager()
: mRasterizer(std::make_unique<Rasterizer>())
{ {
#ifdef __linux__
mCairoInterface = CairoInterface::Create();
#endif
} }
std::unique_ptr<DrawingManager> DrawingManager::Create() std::unique_ptr<DrawingManager> DrawingManager::Create()
@ -23,23 +20,11 @@ void DrawingManager::InitalizeSurface(unsigned width, unsigned height)
{ {
mDrawingSurface = DrawingSurface::Create(); mDrawingSurface = DrawingSurface::Create();
mDrawingSurface->SetSize(width, height); mDrawingSurface->SetSize(width, height);
#ifdef __linux__
if (mCairoInterface)
{
mCairoInterface->InitializeSurface(mDrawingSurface.get());
}
#endif
} }
void DrawingManager::InitializeContext() void DrawingManager::InitializeContext()
{ {
mDrawingContext = DrawingContext::Create(); mDrawingContext = DrawingContext::Create();
#ifdef __linux__
if (mCairoInterface && mDrawingSurface)
{
mCairoInterface->InitializeContext(mDrawingContext.get(), mDrawingSurface.get());
}
#endif
} }
void DrawingManager::AddText(TextElement* text) void DrawingManager::AddText(TextElement* text)
@ -53,20 +38,9 @@ void DrawingManager::AddText(TextElement* text)
{ {
return; return;
} }
#ifdef __linux__
if (mCairoInterface)
{
mCairoInterface->AddText(text, mDrawingContext.get());
}
#endif
} }
void DrawingManager::RenderToFile(const std::string& path) void DrawingManager::RenderToFile(const std::string& path)
{ {
#ifdef __linux__
if (mDrawingSurface && mCairoInterface)
{
mCairoInterface->RenderToFile(mDrawingSurface.get(), path);
}
#endif
} }

View file

@ -4,9 +4,6 @@
#include <string> #include <string>
#include "INativeDrawingContext.h" #include "INativeDrawingContext.h"
#include "INativeDrawingSurface.h" #include "INativeDrawingSurface.h"
#ifdef __linux__
#include "CairoInterface.h"
#endif
class TextElement; class TextElement;
@ -15,6 +12,8 @@ using DrawingSurfacePtr = std::unique_ptr<DrawingSurface>;
class DrawingContext; class DrawingContext;
using DrawingContextPtr = std::unique_ptr<DrawingContext>; using DrawingContextPtr = std::unique_ptr<DrawingContext>;
class Rasterizer;
class DrawingManager class DrawingManager
{ {
public: public:
@ -26,11 +25,9 @@ public:
void RenderToFile(const std::string& path); void RenderToFile(const std::string& path);
private: private:
std::unique_ptr<Rasterizer> mRasterizer;
DrawingSurfacePtr mDrawingSurface {nullptr}; DrawingSurfacePtr mDrawingSurface {nullptr};
DrawingContextPtr mDrawingContext {nullptr}; DrawingContextPtr mDrawingContext {nullptr};
#ifdef __linux__
CairoInterfacePtr mCairoInterface {nullptr};
#endif
}; };
using DrawingManagerPtr = std::unique_ptr<DrawingManager>; using DrawingManagerPtr = std::unique_ptr<DrawingManager>;

View file

@ -38,3 +38,8 @@ unsigned DrawingSurface::GetHeight() const
{ {
return mHeight; return mHeight;
} }
void DrawingSurface::Paint(Grid* grid)
{
mImageBuffer = std::make_unique<Image>();
}

View file

@ -4,6 +4,9 @@
#include "INativeDrawingSurface.h" #include "INativeDrawingSurface.h"
class Grid;
class Image;
class DrawingSurface class DrawingSurface
{ {
public: public:
@ -21,9 +24,14 @@ public:
unsigned GetHeight() const; unsigned GetHeight() const;
void Paint(Grid* grid);
Image* GetAsImage() const;
private: private:
unsigned mWidth = 0; unsigned mWidth = 0;
unsigned mHeight = 0; unsigned mHeight = 0;
std::unique_ptr<Image> mImageBuffer;
std::unique_ptr<INativeDrawingSurface> mNativeDrawingSurface; std::unique_ptr<INativeDrawingSurface> mNativeDrawingSurface;
}; };

View file

@ -0,0 +1,25 @@
#include "Rasterizer.h"
#include "DrawingSurface.h"
#include "DrawingContext.h"
#include "Grid.h"
Rasterizer::Rasterizer()
: mGrid(std::make_unique<Grid>(Rectangle(Point(0, 0), Point(100, 100))))
{
}
void Rasterizer::Paint(DrawingSurface* surface, DrawingContext* context)
{
const auto width = surface->GetWidth();
const auto height = surface->GetHeight();
mGrid->ResetBounds(Rectangle(Point(0, 0), Point(width, height)));
for (unsigned idx=0; idx< context->GetNumItems(); idx++)
{
context->GetDrawable(idx)->Sample(mGrid.get());
}
surface->Paint(mGrid.get());
}

18
src/graphics/Rasterizer.h Normal file
View file

@ -0,0 +1,18 @@
#pragma once
#include <memory>
class DrawingSurface;
class DrawingContext;
class Grid;
class Rasterizer
{
public:
Rasterizer();
void Paint(DrawingSurface* surface, DrawingContext* context);
private:
std::unique_ptr<Grid> mGrid;
};

View file

@ -1,31 +0,0 @@
#include "CairoDrawingContext.h"
cairo_t* CairoDrawingContext::GetNativeContext()
{
return mNativeContext;
}
CairoDrawingContext::CairoDrawingContext(cairo_t* context)
: mNativeContext(context)
{
}
CairoDrawingContext::~CairoDrawingContext()
{
DestroyNativeContext();
}
std::unique_ptr<CairoDrawingContext> CairoDrawingContext::Create(cairo_t* context)
{
return std::make_unique<CairoDrawingContext>(context);
}
void CairoDrawingContext::DestroyNativeContext()
{
if (mNativeContext)
{
cairo_destroy (mNativeContext);
mNativeContext = nullptr;
}
}

View file

@ -1,27 +0,0 @@
#pragma once
#include "INativeDrawingContext.h"
#include <memory>
#include <cairo.h>
class CairoDrawingContext : public INativeDrawingContext
{
public:
CairoDrawingContext(cairo_t* context);
virtual ~CairoDrawingContext();
static std::unique_ptr<CairoDrawingContext> Create(cairo_t* context);
cairo_t* GetNativeContext();
void DestroyNativeContext();
private:
cairo_t* mNativeContext;
};
using CairoDrawingContextPtr = std::unique_ptr<CairoDrawingContext>;

View file

@ -1,31 +0,0 @@
#include "CairoDrawingSurface.h"
CairoDrawingSurface::CairoDrawingSurface(cairo_surface_t* surface)
: mNativeSurface(surface)
{
}
CairoDrawingSurface::~CairoDrawingSurface()
{
DestroyNativeSurface();
}
std::unique_ptr<CairoDrawingSurface> CairoDrawingSurface::Create(cairo_surface_t* surface)
{
return std::make_unique<CairoDrawingSurface>(surface);
}
cairo_surface_t* CairoDrawingSurface::GetNativeSurface()
{
return mNativeSurface;
}
void CairoDrawingSurface::DestroyNativeSurface()
{
if (mNativeSurface)
{
cairo_surface_destroy (mNativeSurface);
mNativeSurface = nullptr;
}
}

View file

@ -1,27 +0,0 @@
#pragma once
#include "INativeDrawingSurface.h"
#include <cairo.h>
#include <memory>
class CairoDrawingSurface : public INativeDrawingSurface
{
public:
CairoDrawingSurface(cairo_surface_t* surface);
virtual ~CairoDrawingSurface();
static std::unique_ptr<CairoDrawingSurface> Create(cairo_surface_t* surface);
cairo_surface_t* GetNativeSurface();
void DestroyNativeSurface() override;
private:
cairo_surface_t* mNativeSurface;
};
using CairoDrawingSurfacePtr = std::unique_ptr<CairoDrawingSurface>;

View file

@ -1,51 +0,0 @@
#include "CairoInterface.h"
#include "DrawingSurface.h"
#include "DrawingContext.h"
#include "CairoDrawingSurface.h"
#include "CairoDrawingContext.h"
#include "TextElement.h"
#include <cairo.h>
std::unique_ptr<CairoInterface> CairoInterface::Create()
{
return std::make_unique<CairoInterface>();
}
void CairoInterface::InitializeSurface(DrawingSurface* surface)
{
auto native_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
surface->GetWidth(), surface->GetHeight());
auto cairo_surface = CairoDrawingSurface::Create(native_surface);
surface->SetNativeSurface(std::move(cairo_surface));
}
void CairoInterface::InitializeContext(DrawingContext* context, DrawingSurface* surface)
{
auto cairo_surface = dynamic_cast<CairoDrawingSurface*>(surface->GetNativeSurface());
auto native_context = cairo_create(cairo_surface->GetNativeSurface());
auto cairo_context = CairoDrawingContext::Create(native_context);
context->SetNativeContext(std::move(cairo_context));
}
void CairoInterface::RenderToFile(DrawingSurface* surface, const std::string& path)
{
auto cairo_surface = dynamic_cast<CairoDrawingSurface*>(surface->GetNativeSurface());
cairo_surface_write_to_png (cairo_surface->GetNativeSurface(), path.c_str());
}
void CairoInterface::AddText(TextElement* text, DrawingContext* context)
{
auto cairo_context = dynamic_cast<CairoDrawingContext*>(context->GetNativeContext());
auto native_context = cairo_context->GetNativeContext();
cairo_select_font_face (native_context, "serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
cairo_set_font_size (native_context, 32.0);
cairo_set_source_rgb (native_context, 0.0, 0.0, 1.0);
cairo_move_to(native_context, 10.0, 50.0);
cairo_show_text(native_context, text->GetContent().c_str());
}

View file

@ -1,26 +0,0 @@
#pragma once
#include <memory>
#include <string>
class DrawingSurface;
class DrawingContext;
class TextElement;
class CairoInterface
{
public:
CairoInterface() = default;
static std::unique_ptr<CairoInterface> Create();
void InitializeSurface(DrawingSurface* surface);
void InitializeContext(DrawingContext* context, DrawingSurface* surface);
void AddText(TextElement* text, DrawingContext* context);
void RenderToFile(DrawingSurface* surface, const std::string& path);
};
using CairoInterfacePtr = std::unique_ptr<CairoInterface>;

View file

@ -16,6 +16,6 @@ target_include_directories(image PUBLIC
set_target_properties( image PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON ) set_target_properties( image PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON )
find_package(PNG REQUIRED) find_package(PNG REQUIRED)
target_link_libraries( image PUBLIC PNG::PNG) target_link_libraries( image PUBLIC PNG::PNG core)
set_property(TARGET image PROPERTY FOLDER src) set_property(TARGET image PROPERTY FOLDER src)

View file

@ -7,6 +7,23 @@ Image::Image(unsigned width, unsigned height)
} }
void Image::Initialize()
{
mData = std::vector<unsigned char>(GetBytesPerRow()*mHeight, 0);
}
void Image::SetPixelValue(unsigned idx, unsigned jdx, const Color& color)
{
if (mData.empty())
{
Initialize();
}
mData[jdx*GetBytesPerRow() + idx*3] = static_cast<unsigned char>(color.GetR());
mData[jdx*GetBytesPerRow() + idx*3 + 1] = static_cast<unsigned char>(color.GetG());
mData[jdx*GetBytesPerRow() + idx*3 + 2] = static_cast<unsigned char>(color.GetB());
}
std::unique_ptr<Image> Image::Create(unsigned width, unsigned height) std::unique_ptr<Image> Image::Create(unsigned width, unsigned height)
{ {
return std::make_unique<Image>(width, height); return std::make_unique<Image>(width, height);

View file

@ -1,5 +1,7 @@
#pragma once #pragma once
#include "Color.h"
#include <memory> #include <memory>
#include <vector> #include <vector>
@ -16,6 +18,9 @@ public:
unsigned GetHeight() const; unsigned GetHeight() const;
unsigned GetBitDepth() const; unsigned GetBitDepth() const;
unsigned GetNumChannels() const; unsigned GetNumChannels() const;
void SetPixelValue(unsigned idx, unsigned jdx, const Color& color);
unsigned char GetByte(unsigned idx, unsigned jdx) const; unsigned char GetByte(unsigned idx, unsigned jdx) const;
void SetData(const std::vector<unsigned char>& data); void SetData(const std::vector<unsigned char>& data);
@ -25,6 +30,8 @@ public:
void SetNumChannels(unsigned numChannels); void SetNumChannels(unsigned numChannels);
private: private:
void Initialize();
unsigned mWidth{1}; unsigned mWidth{1};
unsigned mHeight{1}; unsigned mHeight{1};
unsigned mBitDepth{8}; unsigned mBitDepth{8};

View file

@ -12,6 +12,7 @@ list(APPEND TestFiles
audio/TestMidiReader.cpp audio/TestMidiReader.cpp
database/TestDatabase.cpp database/TestDatabase.cpp
graphics/TestOpenGlRendering.cpp graphics/TestOpenGlRendering.cpp
graphics/TestRasterizer.cpp
ipc/TestDbus.cpp ipc/TestDbus.cpp
image/TestPngWriter.cpp image/TestPngWriter.cpp
publishing/TestPdfWriter.cpp publishing/TestPdfWriter.cpp
@ -24,6 +25,7 @@ list(APPEND TestNames
TestMidiReader TestMidiReader
TestDatabase TestDatabase
TestOpenGlRendering TestOpenGlRendering
TestRasterizer
TestDbus TestDbus
TestPngWriter TestPngWriter
TestPdfWriter TestPdfWriter

View file

@ -51,7 +51,7 @@ int main()
#endif #endif
std::cout << "into entry point" << std::endl; std::cout << "into entry point" << std::endl;
TestCaseRunner runner; TestCaseRunner runner;
//runner.AddTestCase("TestWriteNav", std::make_unique<TestWriteWav>()); runner.AddTestCase("TestWriteNav", std::make_unique<TestWriteWav>());
runner.AddTestCase("TestAudioRender", std::make_unique<TestAudioRender>()); runner.AddTestCase("TestAudioRender", std::make_unique<TestAudioRender>());
const auto testsPassed = runner.Run(); const auto testsPassed = runner.Run();

View file

@ -0,0 +1,9 @@
#include "Image.h"
#include "PngWriter.h"
#include "DrawingManager.h"
int main()
{
DrawingManager manager;
return 0;
}