#ifndef DOC_SVG_H
#define DOC_SVG_H
#include <vector>
#include <map>
#include "tinyxml.h"
#include "DocStyle.h"
#include "DocTemplate.h"
#include "DocOutput.h"
#include "hpdf.h"
class SVGOperation
{
public:
enum PathOperation {
MoveToAbs,
LineToAbs,
HorizontalLineToAbs,
VerticalLineToAbs,
CurveToAbs,
SmoothCurveToAbs,
QuadraticBezierCurveToAbs,
SmoothQuadraticBezierCurveToAbs,
EllipticalArcToAbs,
ClosePath,
MoveToRel,
LineToRel,
HorizontalLineToRel,
VerticalLineToRel,
CurveToRel,
SmoothCurveToRel,
QuadraticBezierCurveToRel,
SmoothQuadraticBezierCurveToRel,
EllipticalArcToRel,
AltClosePath,
BadOperation,
BeginPathOperation,
EndPathOperation
};
static const char PathOperationChar[];
static const int PathOperationArgs[];
static PathOperation getOperationForChar(char a_ch)
{
for (int i = 0; i < BadOperation; i++)
if (PathOperationChar[i] == a_ch)
return (PathOperation)i;
return BadOperation;
}
int getArgCount()
{
return PathOperationArgs[m_type];
}
void dump()
{
fprintf(stderr, " OP: -%c- ARGS: ", PathOperationChar[m_type]);
for (int i = 0; i < PathOperationArgs[m_type]; i++)
fprintf(stderr, " -%f- ", m_values[i]);
fprintf(stderr, "\n");
}
void scale(double a_scale)
{
for (int i = 0; i < PathOperationArgs[m_type]; i++)
m_values[i] *= a_scale;
}
void output(HPDF_Page page, float curPos[2], bool /*fill*/, PathOperation prevOp, float pathStartPos[2]);
PathOperation m_type;
double m_values[7];
};
class DocSVG : public TiXmlVisitor
{
public:
DocSVG(double scale);
virtual ~DocSVG();
/// Visit a document.
virtual bool VisitEnter( const TiXmlDocument& doc );
/// Visit a document.
virtual bool VisitExit( const TiXmlDocument& doc );
/// Visit a declaration
virtual bool Visit( const TiXmlDeclaration& declaration );
/// Visit a stylesheet reference
virtual bool Visit( const TiXmlStylesheetReference& stylesheet );
/// Visit a comment node
virtual bool Visit( const TiXmlComment& comment );
/// Visit an unknow node
virtual bool Visit( const TiXmlUnknown& unknown );
/// Visit an element.
virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute );
/// Visit an element.
virtual bool VisitExit( const TiXmlElement& element );
/// Visit a text node
virtual bool Visit( const TiXmlText& text );
void DumpOperations()
{
for (size_t p = 0; p < paths.size(); ++p)
for (size_t i = 0; i < paths[p].operations.size(); i++)
paths[p].operations[i].dump();
}
void WriteTo(DocOutputPage* outputPage);
private:
struct SVGStyle
{
float opacity;
float fillOpacity;
uint32_t fillColor;
std::string fillString; // url/gradient etc
std::string strokeString; // none | #color
float strokeOpacity;
uint32_t strokeColor;
float strokeWidth;
uint32_t strokeLineCap;
uint32_t strokeLineJoin;
};
struct SVGPath
{
std::vector<SVGOperation> operations;
SVGStyle style;
};
struct SVGColorStop
{
float offset;
uint32_t color;
float opacity;
};
struct SVGGradient
{
std::string name;
std::vector<SVGColorStop> stops;
float x1, y1, x2, y2;
};
static SVGStyle parseStyle(const char* a_str);
static uint32_t parseLineCap(const std::string& s);
static uint32_t parseLineJoin(const std::string& s);
static uint32_t parseColor(const char* a_str);
static std::vector<SVGOperation> ParsePath(const char* a_pathData);
SVGGradient* currentGradient;
std::map<std::string, SVGGradient> gradients;
std::vector<SVGPath> paths;
double m_scale;
};
#endif // DOC_SVG_H