(C++) Canvas
January 25, 2018 · View on GitHub
(C++) Canvas




Canvas is the (abstract) base class of an ASCII art canvas. derived classes are, among others, DrawCanvas, ImageCanvas and TextCanvas.
Technical facts
./CppCanvas/CppCanvas.pri
INCLUDEPATH += \ ../../Classes/CppCanvas SOURCES += \ ../../Classes/CppCanvas/canvas.cpp \ ../../Classes/CppCanvas/canvascolorsystem.cpp \ ../../Classes/CppCanvas/canvascoordinatsystem.cpp \ ../../Classes/CppCanvas/canvascoordinatsystems.cpp \ ../../Classes/CppCanvas/canvascolorsystems.cpp HEADERS += \ ../../Classes/CppCanvas/canvas.h \ ../../Classes/CppCanvas/canvascolorsystem.h \ ../../Classes/CppCanvas/canvascoordinatsystem.h \ ../../Classes/CppCanvas/canvascoordinatsystems.h \ ../../Classes/CppCanvas/canvascolorsystems.h OTHER_FILES += \ ../../Classes/CppCanvas/Licence.txt
./CppCanvas/canvas.h
//--------------------------------------------------------------------------- /* Canvas, ASCII art painting surface class Copyright 2008-2015 Richel Bilderbeek This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ //--------------------------------------------------------------------------- // From http://www.richelbilderbeek.nl/CppCanvas.htm //--------------------------------------------------------------------------- #ifndef RIBI_CANVAS_H #define RIBI_CANVAS_H #include <iosfwd> #include <string> #include <vector> #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Weffc++" #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #include <boost/signals2.hpp> #include "canvascolorsystem.h" #include "canvascoordinatsystem.h" #pragma GCC diagnostic pop struct QRegExp; namespace ribi { ///A Canvas is an ASCII art class for drawing (DrawCanvas), ///displaying images (ImageCanvas) and displaying text (TextCanvas) struct Canvas { Canvas(); virtual ~Canvas() noexcept {} //From http://www.richelbilderbeek.nl/CppGetAsciiArtGradient.htm static std::vector<char> GetAsciiArtGradient() noexcept; ///Obtain the height of the canvas is characters virtual int GetHeight() const noexcept = 0; ///Obtain the version of this class static std::string GetVersion() noexcept; ///Obtain the version history of this class static std::vector<std::string> GetVersionHistory() noexcept; ///Obtain the width of the canvas is characters virtual int GetWidth() const noexcept = 0; ///Load a Canvas from std::strings ///DON'T: make it a constructor instead ///virtual void Load(const std::vector<std::string>& v) = 0; ///Convert the Canvas to std::strings virtual std::vector<std::string> ToStrings() const noexcept = 0; ///This signal is emitted when any member variable changes boost::signals2::signal<void(Canvas*)> m_signal_changed; private: ///From http://www.richelbilderbeek.nl/CppGetRegexMatches.htm //static std::vector<std::string> GetRegexMatches( // const std::string& s, // const QRegExp& r //) noexcept; ///Check if a coordinat is in the range of the Canvas bool IsInRange(const int x, const int y) const; //Obtains the minimum element of a 2D container //From http://www.richelbilderbeek.nl/CppMinElement.htm template <class Container> static typename Container::value_type::value_type MinElement(const Container& v); //Obtains the maximal element of a 2D container //From http://www.richelbilderbeek.nl/CppMaxElement.htm template <class Container> static typename Container::value_type::value_type MaxElement(const Container& v); #ifndef NDEBUG static void Test() noexcept; #endif }; } //~namespace ribi #endif // RIBI_CANVAS_H
./CppCanvas/canvas.cpp
//--------------------------------------------------------------------------- /* Canvas, ASCII art painting surface class Copyright 2008-2015 Richel Bilderbeek This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ //--------------------------------------------------------------------------- // From http://www.richelbilderbeek.nl/CppCanvas.htm //--------------------------------------------------------------------------- #include "canvas.h" #include <iostream> #include <cassert> #include <cmath> #include <algorithm> #include <functional> #include <iterator> #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Weffc++" #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-but-set-parameter" #include <boost/math/constants/constants.hpp> #include <boost/algorithm/string/split.hpp> #include <QString> #include <QRegExp> #include "canvascolorsystems.h" #include "canvascoordinatsystems.h" #include "fileio.h" #include "trace.h" #pragma GCC diagnostic pop ribi::Canvas::Canvas() : m_signal_changed{} { } std::vector<char> ribi::Canvas::GetAsciiArtGradient() noexcept { return { 'M','N','m','d','h','y','s','o','+','/',':','-','.','`',' ' }; } std::string ribi::Canvas::GetVersion() noexcept { return "1.0"; } std::vector<std::string> ribi::Canvas::GetVersionHistory() noexcept { return { "2014-01-10: version 1.0: initial version, split up from DrawCanvas" }; } template <class Container> typename Container::value_type::value_type ribi::Canvas::MinElement(const Container& v) { assert(v.empty() == false && "Container must have a size"); //Obtain an initial lowest value typename Container::value_type::value_type minValue = *(std::min_element(v[0].begin(),v[0].end())); //Set the iterators const typename Container::const_iterator rowEnd = v.end(); typename Container::const_iterator row = v.begin(); ++row; //Move to the next position, as index 0 is already read from for ( ; row != rowEnd; ++row) //row is already initialized { const typename Container::value_type::value_type localMinVal = *(std::min_element(row->begin(),row->end())); if (localMinVal < minValue) minValue = localMinVal; } return minValue; } template <class Container> typename Container::value_type::value_type ribi::Canvas::MaxElement(const Container& v) { assert(v.empty() == false && "Container must have a size"); //Obtain an initial heighest value typename Container::value_type::value_type maxValue = *(std::max_element(v[0].begin(),v[0].end())); //Set the iterators const typename Container::const_iterator rowEnd = v.end(); typename Container::const_iterator row = v.begin(); ++row; //Move to the next position, as index 0 is already read from for ( ; row != rowEnd; ++row) //row is already initialized { const typename Container::value_type::value_type localMaxVal = *(std::max_element(row->begin(),row->end())); if (localMaxVal > maxValue) maxValue = localMaxVal; } return maxValue; }
./CppCanvas/canvascolorsystem.h
#ifndef RIBI_CANVASCOLORSYSTEM_H #define RIBI_CANVASCOLORSYSTEM_H namespace ribi { ///The color system used to draw on a Canvas: ///- normal: full/drawn is displayed by M ///- invert: empty/non-drawn is displayed by M enum class CanvasColorSystem { normal, invert, n_types //Used for testing }; } //~namespace ribi #endif // RIBI_CANVASCOLORSYSTEM_H
./CppCanvas/canvascolorsystem.cpp
#include "canvascolorsystem.h"
./CppCanvas/canvascolorsystems.h
#ifndef RIBI_CANVASCOLORSYSTEMS_H #define RIBI_CANVASCOLORSYSTEMS_H #include <string> #include <vector> #include "canvascolorsystem.h" #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Weffc++" #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #include <boost/bimap.hpp> #pragma GCC diagnostic pop namespace ribi { struct CanvasColorSystems { CanvasColorSystems(); std::vector<CanvasColorSystem> GetAll() const noexcept; std::string ToStr(const CanvasColorSystem s) const noexcept; CanvasColorSystem ToType(const std::string& s) const; private: static boost::bimap<CanvasColorSystem,std::string> m_map; static boost::bimap<CanvasColorSystem,std::string> CreateMap(); #ifndef NDEBUG static void Test() noexcept; #endif }; } //~namespace ribi #endif // RIBI_CANVASCOLORSYSTEMS_H
./CppCanvas/canvascolorsystems.cpp
#include "canvascolorsystems.h" #include <cassert> #include "testtimer.h" #include "trace.h" boost::bimap<ribi::CanvasColorSystem,std::string> ribi::CanvasColorSystems::m_map; ribi::CanvasColorSystems::CanvasColorSystems() { #ifndef NDEBUG Test(); #endif } boost::bimap<ribi::CanvasColorSystem,std::string> ribi::CanvasColorSystems::CreateMap() { boost::bimap<CanvasColorSystem,std::string> m; m.insert(boost::bimap<CanvasColorSystem,std::string>::value_type( CanvasColorSystem::invert,"invert")); m.insert(boost::bimap<CanvasColorSystem,std::string>::value_type( CanvasColorSystem::normal,"normal")); return m; } std::vector<ribi::CanvasColorSystem> ribi::CanvasColorSystems::GetAll() const noexcept { const std::vector<CanvasColorSystem> v { CanvasColorSystem::invert, CanvasColorSystem::normal }; assert(static_cast<int>(v.size()) == static_cast<int>(CanvasColorSystem::n_types)); return v; } #ifndef NDEBUG void ribi::CanvasColorSystems::Test() noexcept { { static bool is_tested{false}; if (is_tested) return; is_tested = true; } const TestTimer test_timer(__func__,__FILE__,1.0); const std::vector<CanvasColorSystem> v = CanvasColorSystems().GetAll(); const std::size_t sz = v.size(); for (std::size_t i=0; i!=sz; ++i) { assert(i < v.size()); const CanvasColorSystem t = v[i]; const std::string s = CanvasColorSystems().ToStr(t); assert(!s.empty()); const CanvasColorSystem u = CanvasColorSystems().ToType(s); assert(u == t); } } #endif std::string ribi::CanvasColorSystems::ToStr(const CanvasColorSystem type) const noexcept { if (m_map.left.empty()) m_map = CreateMap(); assert(!m_map.left.empty()); assert(m_map.left.count(type)); const std::string s = m_map.left.find(type)->second; return s; } ribi::CanvasColorSystem ribi::CanvasColorSystems::ToType(const std::string& s) const { if (m_map.right.empty()) m_map = CreateMap(); assert(!m_map.right.empty()); assert(m_map.right.count(s) == 1); const CanvasColorSystem t = m_map.right.find(s)->second; return t; }
./CppCanvas/canvascoordinatsystem.h
#ifndef RIBI_CANVASCOORDINATSYSTEM_H #define RIBI_CANVASCOORDINATSYSTEM_H namespace ribi { ///The coordinat system used in displayal: ///- screen: origin is at top-left of the screen ///- graph: origin is at bottom-left of the screen enum class CanvasCoordinatSystem { graph, screen, n_types //Used for testing }; ///View canvascoordinatsystem.h for functions to work with this enum class } //~namespace ribi #endif // RIBI_CANVASCOORDINATSYSTEM_H
./CppCanvas/canvascoordinatsystem.cpp
#include "canvascoordinatsystem.h"
./CppCanvas/canvascoordinatsystems.h
#ifndef RIBI_CANVASCOORDINATSYSTEMS_H #define RIBI_CANVASCOORDINATSYSTEMS_H #include <string> #include <vector> #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Weffc++" #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #include <boost/bimap.hpp> #include "canvascoordinatsystem.h" #pragma GCC diagnostic pop namespace ribi { struct CanvasCoordinatSystems { CanvasCoordinatSystems(); std::vector<CanvasCoordinatSystem> GetAll() const noexcept; std::string ToStr(const CanvasCoordinatSystem s) const noexcept; CanvasCoordinatSystem ToType(const std::string& s) const; private: static boost::bimap<CanvasCoordinatSystem,std::string> m_map; static boost::bimap<CanvasCoordinatSystem,std::string> CreateMap(); #ifndef NDEBUG static void Test() noexcept; #endif }; } //~namespace ribi #endif // RIBI_CANVASCOORDINATSYSTEMS_H
./CppCanvas/canvascoordinatsystems.cpp
#include "canvascoordinatsystems.h" #include <cassert> #include "testtimer.h" #include "trace.h" boost::bimap<ribi::CanvasCoordinatSystem,std::string> ribi::CanvasCoordinatSystems::m_map; ribi::CanvasCoordinatSystems::CanvasCoordinatSystems() { #ifndef NDEBUG Test(); #endif } boost::bimap<ribi::CanvasCoordinatSystem,std::string> ribi::CanvasCoordinatSystems::CreateMap() { boost::bimap<CanvasCoordinatSystem,std::string> m; m.insert(boost::bimap<CanvasCoordinatSystem,std::string>::value_type( CanvasCoordinatSystem::graph,"graph")); m.insert(boost::bimap<CanvasCoordinatSystem,std::string>::value_type( CanvasCoordinatSystem::screen,"screen")); return m; } std::vector<ribi::CanvasCoordinatSystem> ribi::CanvasCoordinatSystems::GetAll() const noexcept { const std::vector<CanvasCoordinatSystem> v { CanvasCoordinatSystem::graph, CanvasCoordinatSystem::screen }; assert(static_cast<int>(v.size()) == static_cast<int>(CanvasCoordinatSystem::n_types)); return v; } #ifndef NDEBUG void ribi::CanvasCoordinatSystems::Test() noexcept { { static bool is_tested{false}; if (is_tested) return; is_tested = true; } const TestTimer test_timer(__func__,__FILE__,1.0); const std::vector<CanvasCoordinatSystem> v = CanvasCoordinatSystems().GetAll(); const std::size_t sz = v.size(); for (std::size_t i=0; i!=sz; ++i) { assert(i < v.size()); const CanvasCoordinatSystem t = v[i]; const std::string s = CanvasCoordinatSystems().ToStr(t); assert(!s.empty()); const CanvasCoordinatSystem u = CanvasCoordinatSystems().ToType(s); assert(u == t); } } #endif std::string ribi::CanvasCoordinatSystems::ToStr(const CanvasCoordinatSystem type) const noexcept { if (m_map.left.empty()) m_map = CreateMap(); assert(!m_map.left.empty()); assert(m_map.left.count(type)); const std::string s = m_map.left.find(type)->second; return s; } ribi::CanvasCoordinatSystem ribi::CanvasCoordinatSystems::ToType(const std::string& s) const { if (m_map.right.empty()) m_map = CreateMap(); assert(!m_map.right.empty()); assert(m_map.right.count(s) == 1); const CanvasCoordinatSystem t = m_map.right.find(s)->second; return t; }