Skip to content

Commit

Permalink
Update transform on render, fix parsing and text
Browse files Browse the repository at this point in the history
  • Loading branch information
hoangfitus committed Nov 27, 2023
1 parent 109bcd5 commit 1040a95
Show file tree
Hide file tree
Showing 16 changed files with 223 additions and 141 deletions.
9 changes: 9 additions & 0 deletions external/samples/mixed/sample10.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions external/samples/mixed/sample8.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions external/samples/mixed/sample9.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
176 changes: 85 additions & 91 deletions src/Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ Parser::Parser(const std::string &file_name) {
parseSVG();
}

std::string Parser::parseSVG(const std::string &filePath) {
std::ifstream file(filePath);
std::string Parser::parseSVG(const std::string &file_name) {
std::ifstream file(file_name);
if (!file.is_open()) {
std::cerr << "Failed to open file: " << filePath << std::endl;
std::cerr << "Failed to open file: " << file_name << std::endl;
return "";
}
std::string line;
Expand Down Expand Up @@ -63,6 +63,32 @@ Attributes Parser::parseAttributes(std::string attributes) {
return attributes_vector;
}

std::string removeExtraSpaces(const std::string &input) {
std::string result;
bool spaceDetected = false;
bool firstSpace = true;
for (char ch : input) {
if (ch == ' ') {
if (!spaceDetected) {
if (!firstSpace)
result.push_back(ch);
else
firstSpace = false;
spaceDetected = true;
}
} else {
result.push_back(ch);
spaceDetected = false;
}
}

if (!result.empty() && result.back() == ' ') {
result.pop_back();
}

return result;
}

Tags Parser::parseTags(std::string svg) {
std::vector< std::pair< std::string, std::string > > tags;
std::string line;
Expand All @@ -72,6 +98,19 @@ Tags Parser::parseTags(std::string svg) {
if (start_pos == std::string::npos) {
continue;
}
if (line[start_pos + 1] == '!') {
while (line.find("-->") == std::string::npos) {
std::getline(ss, line);
}
continue;
}
if (line.find("text") != std::string::npos) {
while (line.find("/text") == std::string::npos) {
std::string next_line;
std::getline(ss, next_line);
line += " " + next_line;
}
}
int end_pos = line.find(">");
while (end_pos == std::string::npos) {
std::string next_line;
Expand All @@ -93,6 +132,7 @@ Tags Parser::parseTags(std::string svg) {
std::stringstream ss2(line);
std::getline(ss2, text, '>');
std::getline(ss2, text, '<');
text = removeExtraSpaces(text);
attributes += " text=\"" + text + "\"";
}
tags.push_back(std::make_pair(name, attributes));
Expand All @@ -101,8 +141,8 @@ Tags Parser::parseTags(std::string svg) {
return tags;
}

void Parser::parseObjects(std::string filePath) {
std::string svg = parseSVG(filePath);
void Parser::parseObjects(std::string file_name) {
std::string svg = parseSVG(file_name);
Tags tags = parseTags(svg);

for (auto tag : tags) {
Expand All @@ -117,7 +157,7 @@ void Parser::parseObjects(std::string filePath) {
std::string name = object.first;
if (name == "/g") {
group--;
group_attributes.pop_front();
group_attributes.pop_back();
}
if (group > 0 && name != "g" && name != "/g") {
for (Attributes attributes : group_attributes) {
Expand Down Expand Up @@ -239,12 +279,16 @@ Color Parser::parseColor(Attributes attributes, std::string name) {
Color result;
if (color.find("#") != std::string::npos) {
result = getHexColor(color);
} else if (color.find("rgb") == std::string::npos) {
} else if (color.find("rgb") != std::string::npos) {
result = getRgbColor(color);
} else {
auto color_code = color_map.find(color);
if (color_code == color_map.end()) exit(-1);
if (color_code == color_map.end()) {
std::cout << "Color " << color << " not found" << std::endl;
exit(-1);
}
result = color_code->second;
} else
result = getRgbColor(color);
}

result.a = result.a * getFloatAttribute(attributes, name + "-opacity") *
getFloatAttribute(attributes, "opacity");
Expand Down Expand Up @@ -362,68 +406,44 @@ std::vector< std::string > Parser::getTransformOrder(Attributes attributes) {
return order;
}

std::pair< float, float > Parser::getTranslate(std::string transform_value) {
float trans_x = 0, trans_y = 0;
sscanf(transform_value.c_str(), "translate(%f, %f)", &trans_x, &trans_y);
return std::pair< float, float >(trans_x, trans_y);
}

float Parser::getRotate(std::string transform_value) {
float degree = 0;
sscanf(transform_value.c_str(), "rotate(%f)", &degree);
return degree;
}

float getScale(std::string transform_value) {
float scale = 0;
sscanf(transform_value.c_str(), "scale(%f)", &scale);
return scale;
}

std::pair< float, float > getScaleXY(std::string transform_value) {
float scale_x = 0, scale_y = 0;
sscanf(transform_value.c_str(), "scale(%f, %f)", &scale_x, &scale_y);
return std::pair< float, float >(scale_x, scale_y);
}

void Parser::applyTransform(Shape *shape,
const std::vector< std::string > &transform_order) {
for (auto type : transform_order) {
if (type.find("translate") != std::string::npos) {
float trans_x = getTranslate(type).first,
trans_y = getTranslate(type).second;
shape->translate(trans_x, trans_y);
} else if (type.find("rotate") != std::string::npos) {
float degree = getRotate(type);
shape->rotate(degree);
} else if (type.find("scale") != std::string::npos) {
if (type.find(",") != std::string::npos) {
float scale_x = getScaleXY(type).first,
scale_y = getScaleXY(type).second;
shape->scale(scale_x, scale_y);
} else {
float scale = getScale(type);
shape->scale(scale);
}
void Parser::parseSVG() {
printObjects();
for (auto object : objects) {
std::string name = object.first;
Attributes attributes = object.second;
if (name == "line") {
parseLine(attributes);
} else if (name == "rect") {
parseRect(attributes);
} else if (name == "circle") {
parseCircle(attributes);
} else if (name == "ellipse") {
parseEllipse(attributes);
} else if (name == "polygon") {
parsePolygon(attributes);
} else if (name == "polyline") {
parsePolyline(attributes);
} else if (name == "text") {
parseText(attributes);
} else if (name == "path") {
parsePath(attributes);
}
}
}

void Parser::parseLine(Attributes attributes) {
std::vector< std::string > transform_order = getTransformOrder(attributes);
Color stroke_color = parseColor(attributes, "stroke");
float stroke_width = getFloatAttribute(attributes, "stroke-width");
Line *shape = new Line(Vector2Df(getFloatAttribute(attributes, "x1"),
getFloatAttribute(attributes, "y1")),
Vector2Df(getFloatAttribute(attributes, "x2"),
getFloatAttribute(attributes, "y2")),
stroke_color, stroke_width);
applyTransform(shape, transform_order);
shape->setTransforms(getTransformOrder(attributes));
shapes.push_back(shape);
}

void Parser::parseRect(Attributes attributes) {
std::vector< std::string > transform_order = getTransformOrder(attributes);
Color stroke_color = parseColor(attributes, "stroke");
Color fill_color = parseColor(attributes, "fill");
float stroke_width = getFloatAttribute(attributes, "stroke-width");
Expand All @@ -435,12 +455,11 @@ void Parser::parseRect(Attributes attributes) {
new Rect(getFloatAttribute(attributes, "width"),
getFloatAttribute(attributes, "height"), Vector2Df(x, y),
Vector2Df(rx, ry), fill_color, stroke_color, stroke_width);
applyTransform(shape, transform_order);
shape->setTransforms(getTransformOrder(attributes));
shapes.push_back(shape);
}

void Parser::parseCircle(Attributes attributes) {
std::vector< std::string > transform_order = getTransformOrder(attributes);
Color stroke_color = parseColor(attributes, "stroke");
Color fill_color = parseColor(attributes, "fill");
float stroke_width = getFloatAttribute(attributes, "stroke-width");
Expand All @@ -449,12 +468,11 @@ void Parser::parseCircle(Attributes attributes) {
float radius = getFloatAttribute(attributes, "r");
Circle *shape = new Circle(radius, Vector2Df(cx, cy), fill_color,
stroke_color, stroke_width);
applyTransform(shape, transform_order);
shape->setTransforms(getTransformOrder(attributes));
shapes.push_back(shape);
}

void Parser::parseEllipse(Attributes attributes) {
std::vector< std::string > transform_order = getTransformOrder(attributes);
Color stroke_color = parseColor(attributes, "stroke");
Color fill_color = parseColor(attributes, "fill");
float stroke_width = getFloatAttribute(attributes, "stroke-width");
Expand All @@ -465,7 +483,7 @@ void Parser::parseEllipse(Attributes attributes) {
Ellipse *shape =
new Ellipse(Vector2Df(radius_x, radius_y), Vector2Df(cx, cy),
fill_color, stroke_color, stroke_width);
applyTransform(shape, transform_order);
shape->setTransforms(getTransformOrder(attributes));
shapes.push_back(shape);
}

Expand All @@ -478,6 +496,7 @@ void Parser::parsePolygon(Attributes attributes) {
for (auto point : points) {
shape->addPoint(point);
}
shape->setTransforms(getTransformOrder(attributes));
shapes.push_back(shape);
}

Expand All @@ -494,20 +513,20 @@ void Parser::parsePolyline(Attributes attributes) {
}

void Parser::parseText(Attributes attributes) {
std::vector< std::string > transform_order = getTransformOrder(attributes);
Color stroke_color = parseColor(attributes, "stroke");
Color fill_color = parseColor(attributes, "fill");
float stroke_width = getFloatAttribute(attributes, "stroke-width");
float x = getFloatAttribute(attributes, "x");
float y = getFloatAttribute(attributes, "y");
float font_size = getFloatAttribute(attributes, "font-size");
std::string text = getAttribute(attributes, "text");
Text *shape =
new Text(Vector2Df(x, y - font_size), text, fill_color, font_size);
applyTransform(shape, transform_order);
Text *shape = new Text(Vector2Df(x, y - font_size), text, font_size,
fill_color, stroke_color, stroke_width);
shape->setTransforms(getTransformOrder(attributes));
shapes.push_back(shape);
}

void Parser::parsePath(Attributes attributes) {
std::vector< std::string > transform_order = getTransformOrder(attributes);
Color stroke_color = parseColor(attributes, "stroke");
Color fill_color = parseColor(attributes, "fill");
float stroke_width = getFloatAttribute(attributes, "stroke-width");
Expand All @@ -516,34 +535,9 @@ void Parser::parsePath(Attributes attributes) {
for (auto point : points) {
shape->addPoint(point);
}
applyTransform(shape, transform_order);
shapes.push_back(shape);
}

void Parser::parseSVG() {
for (auto object : objects) {
std::string name = object.first;
Attributes attributes = object.second;
if (name == "line") {
parseLine(attributes);
} else if (name == "rect") {
parseRect(attributes);
} else if (name == "circle") {
parseCircle(attributes);
} else if (name == "ellipse") {
parseEllipse(attributes);
} else if (name == "polygon") {
parsePolygon(attributes);
} else if (name == "polyline") {
parsePolyline(attributes);
} else if (name == "text") {
parseText(attributes);
} else if (name == "path") {
parsePath(attributes);
}
}
}

void Parser::renderSVG(Renderer &renderer) {
for (auto shape : shapes) {
renderer.draw(shape);
Expand Down
11 changes: 2 additions & 9 deletions src/Parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ class Parser {
*/
Parser(const std::string& file_name);

std::string parseSVG(const std::string& filePath);
std::string parseSVG(const std::string& file_name);

Attributes parseAttributes(std::string attributes);

Tags parseTags(std::string svg);

void parseObjects(std::string filePath);
void parseObjects(std::string file_name);

std::string getAttribute(Attributes attributes, std::string name);

Expand All @@ -52,13 +52,6 @@ class Parser {

std::vector< std::string > getTransformOrder(Attributes attributes);

std::pair< float, float > getTranslate(std::string transform_value);

float getRotate(std::string transform_value);

void applyTransform(Shape* shape,
const std::vector< std::string >& transform_order);

void parseLine(Attributes attributes);

void parseRect(Attributes attributes);
Expand Down
Loading

0 comments on commit 1040a95

Please sign in to comment.