Skip to content

Commit

Permalink
Fix text outline and add viewbox
Browse files Browse the repository at this point in the history
  • Loading branch information
hoangfitus committed Dec 24, 2023
1 parent 75ed38f commit b7f5cef
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 29 deletions.
32 changes: 18 additions & 14 deletions src/Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,13 +187,13 @@ SVGElement *Parser::parseElements(std::string file_name) {
doc.parse< 0 >(&buffer[0]);

rapidxml::xml_node<> *svg = doc.first_node();
viewBox.second.x = getFloatAttribute(svg, "width");
viewBox.second.y = getFloatAttribute(svg, "height");
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;
viewport.x = getFloatAttribute(svg, "width");
viewport.y = getFloatAttribute(svg, "height");
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;
}
rapidxml::xml_node<> *node = svg->first_node();
rapidxml::xml_node<> *prev = NULL;
Expand Down Expand Up @@ -321,19 +321,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.second.x
: 0.5 * this->viewbox.second.y;
else if (name == "r") {
result = sqrt((pow(this->viewBox.second.x, 2) +
pow(this->viewBox.second.y, 2)) /
result = sqrt((pow(this->viewbox.second.x, 2) +
pow(this->viewbox.second.y, 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.second.x
: this->viewbox.second.y;
} else {
if (name == "stroke-width" || name == "stroke-opacity" ||
name == "fill-opacity" || name == "opacity" ||
Expand Down Expand Up @@ -814,4 +814,8 @@ Parser::~Parser() {
}
}

void Parser::printShapesData() { root->printData(); }
void Parser::printShapesData() { root->printData(); }

std::pair< Vector2Df, Vector2Df > Parser::getViewBox() const { return viewbox; }

Vector2Df Parser::getViewPort() const { return viewport; }
46 changes: 38 additions & 8 deletions src/Parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,31 @@ typedef std::vector< std::pair< std::string, std::string > > Attributes;
*/
class Parser {
public:
static Parser* getInstance(
const std::string&
file_name); ///< Gets the singleton instance of the Parser class.
/**
* @brief Gets the singleton instance of the Parser class.
*
* @param file_name The name of the file to be parsed.
*
* @return The singleton instance of the Parser class.
*/
static Parser* getInstance(const std::string& file_name);

Parser(const Parser&) =
delete; ///< Deleted copy constructor to enforce the singleton pattern.
/**
* @brief Deleted copy constructor to enforce the singleton pattern.
*/
Parser(const Parser&) = delete;

~Parser(); ///< Destructor.
/**
* @brief Destructor for the Parser class.
*/
~Parser();

Group* getRoot(); ///< Gets the root of the SVG file.
/**
* @brief Gets the root of the tree of SVGElements.
*
* @return The root of the tree of SVGElements.
*/
Group* getRoot();

/**
* @brief Prints the data of the shapes.
Expand All @@ -41,6 +56,20 @@ class Parser {
*/
void printShapesData();

/**
* @brief Gets the viewbox of the SVG file.
*
* @return The viewbox of the SVG file.
*/
std::pair< Vector2Df, Vector2Df > getViewBox() const;

/**
* @brief Gets the viewport of the SVG file.
*
* @return The viewport of the SVG file.
*/
Vector2Df getViewPort() const;

private:
/**
* @brief Construct a new Parser object.
Expand Down Expand Up @@ -248,7 +277,8 @@ class Parser {
std::map< std::string, Gradient* > gradients; ///< The gradients of the SVG
///< file.
std::pair< Vector2Df, Vector2Df >
viewBox; ///< The viewbox of the SVG file.
viewbox; ///< The viewbox of the SVG file.
Vector2Df viewport; ///< The viewport of the SVG file.
};

#endif // PARSER_HPP_
7 changes: 6 additions & 1 deletion src/Renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,12 @@ void Renderer::drawText(Gdiplus::Graphics& graphics, Text* text) const {
graphics.FillPath(&corner_fill, &path);
}
graphics.FillPath(text_fill, &path);
if (text->getOutlineColor().a == text->getFillColor().a) {
text_outline.SetColor(Gdiplus::Color(255, 255, 255, 255));
graphics.DrawPath(&text_outline, &path);
text_outline.SetColor(Gdiplus::Color(outline_color.a, outline_color.r,
outline_color.g, outline_color.b));
}
graphics.DrawPath(&text_outline, &path);
delete text_fill;
}
Expand Down Expand Up @@ -586,7 +592,6 @@ Gdiplus::Brush* Renderer::getBrush(SVGElement* shape,
bound, colors[0], colors[stop_size - 1],
Gdiplus::LinearGradientMode::LinearGradientModeHorizontal);
fill->SetInterpolationColors(colors, offsets, stop_size);
fill->SetWrapMode(Gdiplus::WrapModeTileFlipXY);
applyTransformsOnBrush(gradient->getTransforms(), fill);
delete[] colors;
delete[] offsets;
Expand Down
7 changes: 7 additions & 0 deletions src/Viewer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,11 @@ void Viewer::handleKeyDown(WPARAM wParam) {
rotate_angle += 1.0f;
break;
}
}

void Viewer::getWindowSize(HWND hWnd) const {
RECT rect;
GetClientRect(hWnd, &rect);
instance->window_size.x = static_cast< float >(rect.right - rect.left);
instance->window_size.y = static_cast< float >(rect.bottom - rect.top);
}
20 changes: 14 additions & 6 deletions src/Viewer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@
*/
class Viewer {
public:
float offset_x; ///< X-coordinate offset of the viewer
float offset_y; ///< Y-coordinate offset of the viewer
float zoom_factor; ///< Zoom factor for scaling the view
float rotate_angle; ///< Rotation angle of the view
bool needs_repaint; ///< Flag indicating whether the view needs to be
///< repainted
float offset_x; ///< X-coordinate offset of the viewer
float offset_y; ///< Y-coordinate offset of the viewer
float zoom_factor; ///< Zoom factor for scaling the view
float rotate_angle; ///< Rotation angle of the view
bool needs_repaint; ///< Flag indicating whether the view needs to be
///< repainted
Vector2Df window_size; ///< Size of the window

/**
* @brief Gets the singleton instance of the Viewer class.
Expand Down Expand Up @@ -51,6 +52,13 @@ class Viewer {
*/
void handleKeyEvent(WPARAM wParam);

/**
* @brief Get the current window size.
*
* @param hWnd The handle to the window.
*/
void getWindowSize(HWND hWnd) const;

private:
static Viewer* instance; ///< Singleton instance of the Viewer class

Expand Down
8 changes: 8 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ void OnPaint(HDC hdc, const std::string& filePath, Viewer& viewer) {
if (!parser) {
parser = Parser::getInstance(filePath);
}
Vector2Df viewport = parser->getViewPort();
std::pair< Vector2Df, Vector2Df > viewbox = parser->getViewBox();
float scale_x = viewer.window_size.x / viewbox.second.x;
float scale_y = viewer.window_size.y / viewbox.second.y;
float scale = std::min(scale_x, scale_y);

graphics.ScaleTransform(scale, scale);
graphics.RotateTransform(viewer.rotate_angle);
graphics.ScaleTransform(viewer.zoom_factor, viewer.zoom_factor);
graphics.TranslateTransform(viewer.offset_x, viewer.offset_y);
Expand Down Expand Up @@ -92,6 +99,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam,
switch (message) {
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
viewer->getWindowSize(hWnd);
OnPaint(hdc, filePath, *viewer);
EndPaint(hWnd, &ps);
return 0;
Expand Down

0 comments on commit b7f5cef

Please sign in to comment.