Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -----------------------------------------------------------------------
- svg.h
- -----------------------------------------------------------------------
- #pragma once
- #include <cstdint>
- #include <iostream>
- #include <memory>
- #include <string>
- #include <vector>
- namespace svg {
- struct Point {
- Point() = default;
- Point(double x, double y) : x(x)
- , y(y) {}
- double x = 0;
- double y = 0;
- };
- struct RenderContext {
- RenderContext(std::ostream& out) : out(out) {}
- RenderContext(std::ostream& out, int indent_step, int indent = 0) : out(out)
- , indent_step(indent_step)
- , indent(indent) {}
- RenderContext Indented() const {
- return {out,
- indent_step,
- indent + indent_step};
- }
- void RenderIndent() const {
- for (int i = 0; i < indent; ++i) {
- out.put(' ');
- }
- }
- std::ostream& out;
- int indent_step = 0;
- int indent = 0;
- };
- class Object {
- public:
- void Render(const RenderContext& context) const;
- virtual ~Object() = default;
- private:
- virtual void RenderObject(const RenderContext& context) const = 0;
- };
- class Circle final : public Object {
- public:
- Circle& SetCenter(Point center);
- Circle& SetRadius(double radius);
- private:
- Point center_;
- double radius_ = 1.0;
- void RenderObject(const RenderContext& context) const override;
- };
- class Polyline final : public Object {
- public:
- Polyline& AddPoint(Point point);
- private:
- std::vector<Point> points_;
- void RenderObject(const RenderContext& context) const override;
- };
- class Text final : public Object{
- public:
- Text& SetPosition(Point pos);
- Text& SetOffset(Point offset);
- Text& SetFontSize(uint32_t size);
- Text& SetFontFamily(std::string font_family);
- Text& SetFontWeight(std::string font_weight);
- Text& SetData(std::string data);
- private:
- Point position_;
- Point offset_;
- std::string font_family_;
- std::string font_weight_;
- uint32_t font_size_ = 1;
- std::string data_;
- static std::string delete_spaces(const std::string& str);
- static std::string uniq_symbols(const std::string& str);
- void RenderObject(const RenderContext& context) const override;
- };
- class Document {
- public:
- template <typename Obj>
- void Add(Obj obj) {
- objects_.emplace_back(std::make_unique<Obj>(std::move(obj)));
- }
- void AddPtr(std::unique_ptr<Object>&& obj);
- void Render(std::ostream& out) const;
- private:
- std::vector<std::unique_ptr<Object>> objects_;
- };
- }//end namespace svg
- -----------------------------------------------------------------------
- svg.cpp
- -----------------------------------------------------------------------
- #include "svg.h"
- namespace svg {
- using namespace std::literals;
- void Object::Render(const RenderContext& context) const {
- context.RenderIndent();
- RenderObject(context);
- context.out << std::endl;
- }
- // ---------- Circle ------------------
- Circle& Circle::SetCenter(Point center) {
- center_ = center;
- return *this;
- }
- Circle& Circle::SetRadius(double radius) {
- radius_ = radius;
- return *this;
- }
- void Circle::RenderObject(const RenderContext& context) const {
- std::ostream& out = context.out;
- out << R"(<circle cx=")"
- << center_.x << R"(" cy=")"
- << center_.y << R"(" )"
- << R"(r=")"
- << radius_ << R"(" )" << "/>"sv;
- }
- // ---------- Polyline ------------------
- Polyline& Polyline::AddPoint(Point point) {
- points_.emplace_back(point);
- return *this;
- }
- void Polyline::RenderObject(const RenderContext& context) const {
- std::ostream& out = context.out;
- out << R"(<polyline points=")";
- for (size_t i = 0; i < points_.size(); ++i) {
- out << points_[i].x << ","sv << points_[i].y;
- if (i+1 != points_.size()) {
- out << " "sv;
- }
- }
- out << R"(")" << " />"sv;
- }
- // ---------- Text ------------------
- Text& Text::SetPosition(Point pos) {
- position_ = pos;
- return *this;
- }
- Text& Text::SetOffset(Point offset) {
- offset_ = offset;
- return *this;
- }
- Text& Text::SetFontSize(uint32_t size) {
- font_size_ = size;
- return *this;
- }
- Text& Text::SetFontFamily(std::string font_family) {
- font_family_ = std::move(font_family);
- return *this;
- }
- Text& Text::SetFontWeight(std::string font_weight) {
- font_weight_ = std::move(font_weight);
- return *this;
- }
- Text& Text::SetData(std::string data) {
- data_ = std::move(data);
- return *this;
- }
- std::string Text::delete_spaces(const std::string& str) {
- if (str.empty()) {
- return {};
- } else {
- auto left = str.find_first_not_of(' ');
- auto right = str.find_last_not_of(' ');
- return str.substr(left, right - left + 1);
- }
- }
- std::string Text::uniq_symbols(const std::string& str) {
- std::string out;
- for (char ch : str) {
- if (ch == '"') {
- out += """sv;
- continue;
- } else if (ch == '`' || ch == '\'') {
- out += "'"sv;
- continue;
- } else if (ch == '<') {
- out += "<"sv;
- continue;
- } else if (ch == '>') {
- out += ">"sv;
- continue;
- } else if (ch == '&') {
- out += "&"sv;
- continue;
- } else {}
- out += ch;
- }
- return out;
- }
- void Text::RenderObject(const RenderContext& context) const {
- std::ostream& out = context.out;
- out << R"(<text x=")"
- << position_.x << R"(" y=")"
- << position_.y << R"(" )"
- << R"(dx=")"
- << offset_.x << R"(" dy=")"
- << offset_.y << R"(" )"
- << R"(font-size=")"
- << font_size_ << R"(")";
- if (!font_family_.empty()) {
- out << R"( font-family=")" << font_family_ << R"(")";
- }
- if (!font_weight_.empty()) {
- out << R"( font-weight=")" << font_weight_ << R"(")";
- }
- out << ">"sv << delete_spaces(uniq_symbols(data_)) << "</text>"sv;
- }
- // ---------- Document ------------------
- void Document::AddPtr(std::unique_ptr<Object> &&obj) {
- objects_.emplace_back(std::move(obj));
- }
- void Document::Render(std::ostream &out) const {
- int indent = 2;
- int indent_step = 2;
- RenderContext context(out, indent_step, indent);
- const std::string_view xml = R"(<?xml version="1.0" encoding="UTF-8" ?>)";
- const std::string_view svg = R"(<svg xmlns="http://www.w3.org/2000/svg" version="1.1">)";
- out << xml << "\n"sv << svg << "\n"sv;
- for (const auto& object : objects_) {
- object->Render(context);
- }
- out << "</svg>"sv;
- }
- } // namespace svg
- -----------------------------------------------------------------------
- main.cpp
- -----------------------------------------------------------------------
- #define _USE_MATH_DEFINES
- #include "svg.h" // Объявления классов библиотеки должны быть расположены в файле svg.h
- #include <cmath>
- using namespace std::literals;
- using namespace svg;
- Polyline CreateStar(Point center, double outer_rad, double inner_rad, int num_rays) {
- Polyline polyline;
- for (int i = 0; i <= num_rays; ++i) {
- double angle = 2 * M_PI * (i % num_rays) / num_rays;
- polyline.AddPoint({center.x + outer_rad * sin(angle), center.y - outer_rad * cos(angle)});
- if (i == num_rays) {
- break;
- }
- angle += M_PI / num_rays;
- polyline.AddPoint({center.x + inner_rad * sin(angle), center.y - inner_rad * cos(angle)});
- }
- return polyline;
- }
- int main() {
- Document doc;
- doc.Add(Circle().SetCenter({20, 20}).SetRadius(10));
- doc.Add(Text()
- .SetFontFamily("Verdana"s)
- .SetPosition({35, 20})
- .SetOffset({0, 6})
- .SetFontSize(12)
- .SetFontWeight("bold"s)
- .SetData("Hello C++"s));
- doc.Add(CreateStar({20, 50}, 10, 5, 5));
- doc.Render(std::cout);
- }
Advertisement
Add Comment
Please, Sign In to add comment