Skip to content

Commit

Permalink
Add viewbox class and handle some input cases (#34)
Browse files Browse the repository at this point in the history
authored-by: hoangfitus <[email protected]>
  • Loading branch information
ntkwan authored Jan 6, 2024
1 parent 86f374d commit 1252624
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 23 deletions.
1 change: 1 addition & 0 deletions src/Graphics.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@
#include "graphics/RadialGradient.hpp"
#include "graphics/Rect.hpp"
#include "graphics/Text.hpp"
#include "graphics/ViewBox.hpp"

#endif // GRAPHICS_HPP_
21 changes: 11 additions & 10 deletions src/Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,8 +209,9 @@ SVGElement *Parser::parseElements(std::string file_name) {
std::string viewbox = getAttribute(svg, "viewBox");
if (viewbox != "") {
std::stringstream ss(viewbox);
ss >> this->viewbox.first.x >> this->viewbox.first.y >>
this->viewbox.second.x >> this->viewbox.second.y;
float x, y, w, h;
ss >> x >> y >> w >> h;
this->viewbox = ViewBox(x, y, w, h);
}
rapidxml::xml_node<> *node = svg->first_node();
rapidxml::xml_node<> *prev = NULL;
Expand Down Expand Up @@ -355,19 +356,19 @@ float Parser::getFloatAttribute(rapidxml::xml_node<> *node, std::string name) {
if (name == "x1" || name == "y1" || name == "fr")
result = 0;
else if (name == "cx" || name == "cy")
result = name == "cx" ? 0.5 * this->viewbox.second.x
: 0.5 * this->viewbox.second.y;
result = name == "cx" ? 0.5 * this->viewbox.getWidth()
: 0.5 * this->viewbox.getHeight();
else if (name == "r") {
result = sqrt((pow(this->viewbox.second.x, 2) +
pow(this->viewbox.second.y, 2)) /
result = sqrt((pow(this->viewbox.getWidth(), 2) +
pow(this->viewbox.getHeight(), 2)) /
2) /
2;
} else if (name == "fx" || name == "fy")
result = name == "fx" ? getFloatAttribute(node, "cx")
: getFloatAttribute(node, "cy");
else
result = name == "x2" ? this->viewbox.second.x
: this->viewbox.second.y;
result = name == "x2" ? this->viewbox.getWidth()
: this->viewbox.getHeight();
} else {
// Handle default float attribute values for other elements
if (name == "stroke-width" || name == "stroke-opacity" ||
Expand All @@ -383,7 +384,7 @@ float Parser::getFloatAttribute(rapidxml::xml_node<> *node, std::string name) {
std::string value = node->first_attribute(name.c_str())->value();
if (value.find("%") != std::string::npos) {
result = std::stof(value.substr(0, value.find("%"))) *
this->viewbox.second.x / 100;
this->viewbox.getWidth() / 100;
} else if (value.find("pt") != std::string::npos) {
result = std::stof(value.substr(0, value.find("pt"))) * 1.33;
} else {
Expand Down Expand Up @@ -907,7 +908,7 @@ Parser::~Parser() {
void Parser::printShapesData() { root->printData(); }

// Get the viewBox of the SVG document
std::pair< Vector2Df, Vector2Df > Parser::getViewBox() const { return viewbox; }
ViewBox Parser::getViewBox() const { return viewbox; }

// Get the viewport of the SVG document
Vector2Df Parser::getViewPort() const { return viewport; }
5 changes: 2 additions & 3 deletions src/Parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class Parser {
*
* @return The viewbox of the SVG file.
*/
std::pair< Vector2Df, Vector2Df > getViewBox() const;
ViewBox getViewBox() const;

/**
* @brief Gets the viewport of the SVG file.
Expand Down Expand Up @@ -278,8 +278,7 @@ class Parser {
SVGElement* root; ///< The root of the SVG file.
std::map< std::string, Gradient* > gradients; ///< The gradients of the SVG
///< file.
std::pair< Vector2Df, Vector2Df >
viewbox; ///< The viewbox of the SVG file.
ViewBox viewbox; ///< The viewbox of the SVG file.
Vector2Df viewport; ///< The viewport of the SVG file.
};

Expand Down
13 changes: 13 additions & 0 deletions src/graphics/ViewBox.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include "ViewBox.hpp"

ViewBox::ViewBox() : x(0), y(0), w(0), h(0) {}

ViewBox::ViewBox(float X, float Y, float W, float H) : x(X), y(Y), w(W), h(H) {}

float ViewBox::getX() const { return x; }

float ViewBox::getY() const { return y; }

float ViewBox::getWidth() const { return w; }

float ViewBox::getHeight() const { return h; }
58 changes: 58 additions & 0 deletions src/graphics/ViewBox.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#ifndef VIEWBOX_HPP_
#define VIEWBOX_HPP_

class ViewBox {
public:
/**
* @brief Default constructor
*
* Creates a ViewBox(0, 0, 0, 0).
*/
ViewBox();

/**
* @brief Construct the ViewBox from its coordinates
*
* @param X X coordinate
* @param Y Y coordinate
* @param W Width
* @param H Height
*/
ViewBox(float X, float Y, float W, float H);

/**
* @brief Get the X coordinate of the ViewBox
*
* @return X coordinate of the ViewBox
*/
float getX() const;

/**
* @brief Get the Y coordinate of the ViewBox
*
* @return Y coordinate of the ViewBox
*/
float getY() const;

/**
* @brief Get the width of the ViewBox
*
* @return Width of the ViewBox
*/
float getWidth() const;

/**
* @brief Get the height of the ViewBox
*
* @return Height of the ViewBox
*/
float getHeight() const;

private:
float x; ///< X coordinate of the ViewBox
float y; ///< Y coordinate of the ViewBox
float w; ///< Width of the ViewBox
float h; ///< Height of the ViewBox
};

#endif // VIEWBOX_HPP_
33 changes: 23 additions & 10 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ void OnPaint(HDC hdc, const std::string& filePath, Viewer& viewer) {

// Set up Viewbox and Viewport
Vector2Df viewport = parser->getViewPort();
std::pair< Vector2Df, Vector2Df > viewbox = parser->getViewBox();
ViewBox viewbox = parser->getViewBox();
if (viewport.x == 0 && viewport.y == 0) {
viewport.x = viewer.window_size.x;
viewport.y = viewer.window_size.y;
Expand All @@ -35,23 +35,24 @@ void OnPaint(HDC hdc, const std::string& filePath, Viewer& viewer) {
graphics.SetInterpolationMode(Gdiplus::InterpolationModeHighQuality);

graphics.SetClip(Gdiplus::Rect(0, 0, viewport.x, viewport.y));
if ((viewport.x != viewbox.second.x || viewport.y != viewbox.second.y) &&
viewbox.second.x != 0 && viewbox.second.y != 0) {
float scale_x = viewport.x / viewbox.second.x;
float scale_y = viewport.y / viewbox.second.y;
if ((viewport.x != viewbox.getWidth() ||
viewport.y != viewbox.getHeight()) &&
viewbox.getWidth() != 0 && viewbox.getHeight() != 0) {
float scale_x = viewport.x / viewbox.getWidth();
float scale_y = viewport.y / viewbox.getHeight();
float scale = std::min(scale_x, scale_y);
graphics.ScaleTransform(scale, scale);
float offset_x = 0.0f;
float offset_y = 0.0f;
if (viewport.x > viewbox.second.x) {
offset_x = (viewport.x - viewbox.second.x * scale) / 2 / scale;
if (viewport.x > viewbox.getWidth()) {
offset_x = (viewport.x - viewbox.getWidth() * scale) / 2 / scale;
}
if (viewport.y > viewbox.second.y) {
offset_y = (viewport.y - viewbox.second.y * scale) / 2 / scale;
if (viewport.y > viewbox.getHeight()) {
offset_y = (viewport.y - viewbox.getHeight() * scale) / 2 / scale;
}
graphics.TranslateTransform(offset_x, offset_y);
}
graphics.TranslateTransform(-viewbox.first.x, -viewbox.first.y);
graphics.TranslateTransform(-viewbox.getX(), -viewbox.getY());

Gdiplus::Matrix matrix;
Gdiplus::Region region;
Expand Down Expand Up @@ -124,6 +125,18 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam,
std::string filePath;
if (__argc > 1) {
filePath = __argv[1];
std::ifstream file(filePath);
if (!file.good()) {
std::cerr << "Error: File path is invalid or does not exist."
<< std::endl;
PostQuitMessage(0);
return 0;
}
file.close();
} else {
std::cerr << "Error: No file path provided." << std::endl;
PostQuitMessage(0);
return 0;
}
Viewer* viewer = Viewer::getInstance();
switch (message) {
Expand Down

0 comments on commit 1252624

Please sign in to comment.