1782 lines
60 KiB
C++
1782 lines
60 KiB
C++
#ifdef USE_SVG
|
|
#include "SVG_Manager.h"
|
|
|
|
extern char CamcamCCM[];
|
|
|
|
void scaleSvgWorld(MAD_World* svgMad);
|
|
void createStroke(MAD_World* svgMad)
|
|
void addObjectInMadWorld(MAD_World* svgMad, int parentHierIndex, bool isAGroupNode)
|
|
void initSvgMad(MAD_World* svgMad)
|
|
void madPath(TiXmlNode* node, MAD_World* svgMad)
|
|
bool svg2mad(char* svgFilename, char* destMadFilename)
|
|
void browseNode(TiXmlNode* node, MAD_World* svgMad, int parentHierIndex)
|
|
SvgFillType svgFillType(const char* fillString)
|
|
void cleanPointsList(std::vector<PointF>& pointsList)
|
|
void closePath()
|
|
void moveTo(float x, float y)
|
|
void lineTo(float x, float y)
|
|
void cubicTo(PointF c1, PointF c2, PointF e)
|
|
void quadTo(PointF c, PointF e)
|
|
void pathArc(float rx, float ry, float xAxisRotation, int largeArcFlag,
|
|
int sweepFlag, float ex, float ey, float curx, float cury)
|
|
float atoh(const char* Decode, bool findFloat)
|
|
void CleanDirectory(TCHAR * directoryPath, bool deleteFilesButNotDirectories)
|
|
char* getCleanedString(char* string)
|
|
void removeAllShit(char* filename)
|
|
float getFloat(char* &Decode)
|
|
void checkMemIntegrity(void* ptr, int Size)
|
|
void* malloc2(u32 Size)
|
|
void* realloc2(void* ptr, u32 Size)
|
|
void free2(void* ptr)
|
|
|
|
|
|
|
|
//nombre d'allocations mémoire
|
|
int nbAlloc = 0;
|
|
//tableau des tailles des zones mémoire allouées
|
|
unsigned int* allocSizes = (unsigned int*)ZeroAlloc(sizeof(unsigned int));
|
|
//tableau des pointeurs vers les zones mémoire allouées
|
|
void** allocStack = (void**)ZeroAlloc(sizeof(void*));
|
|
|
|
|
|
//nombre de pixels SVG par unité 3DSMax
|
|
float PIXELS_PER_UNIT = 30;
|
|
//chemin du répertoire image à générer pour les textures du MAD
|
|
char svgTexturesDir[512] = "";
|
|
//relation entre l'index SVG et son pointeur dans la structure tinyXML
|
|
std::vector<TiXmlElement*> svgNodes;
|
|
//id de l'objet SVG courant
|
|
char svgObjectID[260];
|
|
//nouveaux points à créer
|
|
char** textureFilenames = (char**)malloc2(sizeof(char*));
|
|
//point courant du path SVG
|
|
PointF CP(0,0);
|
|
//point initial du path SVG
|
|
PointF SP(0,0);
|
|
//nouveau path SVG à créer
|
|
char* startOfPathOut;
|
|
char* pathOut;
|
|
//longueur du path à créer
|
|
long int pathLen;
|
|
//nouveaux points à créer
|
|
std::vector<PointF> pointsList;
|
|
//nombre de points composant l'objet SVG
|
|
int svgNbPoints;
|
|
//noeud SVG courant
|
|
TiXmlElement* cNode;
|
|
//liste des textures du document SVG
|
|
SvgTexture* svgTextures = (SvgTexture*)malloc2(sizeof(SvgTexture));
|
|
//nombre de textures SVG du document SVG
|
|
int numberOfSvgTextures = 0;
|
|
//limites de la forme SVG courante
|
|
float svgxmin, svgymin, svgxmax, svgymax, svgz;
|
|
//centre de l'objet SVG en cours
|
|
PointF objectCenter;
|
|
//liste des objets SVG créés
|
|
MAD_GeometricObject** svgObjects = (MAD_GeometricObject**)malloc2(sizeof(MAD_GeometricObject*));
|
|
//monde SVG à créer
|
|
SvgWorld svgWorld;
|
|
//bounding box du monde SVG à créer
|
|
float svgWorld_Xmin, svgWorld_Ymin, svgWorld_Xmax, svgWorld_Ymax;
|
|
|
|
//debug
|
|
MAD_Simple3DVertex* saveMadPointsList;
|
|
|
|
|
|
/*****************************************************************************************/
|
|
void scaleSvgWorld(MAD_World* svgMad)
|
|
{
|
|
//récupération des limites du monde
|
|
svgWorld_Xmin = svgWorld_Xmin/PIXELS_PER_UNIT;
|
|
svgWorld_Xmax = svgWorld_Xmax/PIXELS_PER_UNIT;
|
|
svgWorld_Ymin = svgWorld_Ymin/PIXELS_PER_UNIT;
|
|
svgWorld_Ymax = svgWorld_Ymax/PIXELS_PER_UNIT;
|
|
|
|
//placement de la camera "CP"
|
|
float width = (svgWorld_Xmax - svgWorld_Xmin);
|
|
float height = (svgWorld_Ymax - svgWorld_Ymin);
|
|
svgMad->Hierarchie[1].Matrix.Translation.x = width/2;
|
|
svgMad->Hierarchie[1].Matrix.Translation.y = -height/2;
|
|
svgMad->Hierarchie[1].Matrix.Translation.z = (max(width, height)/2.0)*3.0;
|
|
|
|
//centrage sur l'origine des pivots des objets
|
|
for(int h=2; h<svgMad->NumberOfHierarchieNodes; h++)
|
|
{
|
|
svgMad->Hierarchie[h].Pivot.x = svgMad->Hierarchie[h].Pivot.x/PIXELS_PER_UNIT;
|
|
svgMad->Hierarchie[h].Pivot.y = svgMad->Hierarchie[h].Pivot.y/PIXELS_PER_UNIT;
|
|
}
|
|
|
|
//mise à l'échelle de Camcam et centrage sur l'origine des objets
|
|
for(int h=2; h<svgMad->NumberOfHierarchieNodes; h++)
|
|
{
|
|
int o = svgMad->Hierarchie[h].Object;
|
|
if(o != MAD_NULL_INDEX)
|
|
{
|
|
o--;
|
|
for(int n=0; n<svgObjects[o]->NumberOfPoints; n++)
|
|
{
|
|
svgObjects[o]->OBJ_PointList[n].Point.x = svgObjects[o]->OBJ_PointList[n].Point.x/PIXELS_PER_UNIT
|
|
- svgMad->Hierarchie[h].Pivot.x;
|
|
svgObjects[o]->OBJ_PointList[n].Point.y = svgObjects[o]->OBJ_PointList[n].Point.y/PIXELS_PER_UNIT
|
|
- svgMad->Hierarchie[h].Pivot.y;
|
|
}
|
|
}
|
|
}
|
|
|
|
//positionnement des matrices globales
|
|
for(int h=2; h<svgMad->NumberOfHierarchieNodes; h++)
|
|
{
|
|
svgMad->Hierarchie[h].Matrix.Translation.x = svgMad->Hierarchie[h].Pivot.x - svgWorld_Xmin;
|
|
svgMad->Hierarchie[h].Matrix.Translation.y = svgMad->Hierarchie[h].Pivot.y - svgWorld_Ymax;
|
|
svgMad->Hierarchie[h].Matrix.Translation.z = svgMad->Hierarchie[h].Pivot.z;
|
|
}
|
|
|
|
//positionnement des matrices locales
|
|
for(int h=2; h<svgMad->NumberOfHierarchieNodes; h++)
|
|
{
|
|
int p = svgMad->Hierarchie[h].Parent;
|
|
svgMad->Hierarchie[h].RelativeMatrix.Translation.x = svgMad->Hierarchie[h].Matrix.Translation.x
|
|
- svgMad->Hierarchie[p].Matrix.Translation.x;
|
|
svgMad->Hierarchie[h].RelativeMatrix.Translation.y = svgMad->Hierarchie[h].Matrix.Translation.y
|
|
- svgMad->Hierarchie[p].Matrix.Translation.y;
|
|
svgMad->Hierarchie[h].RelativeMatrix.Translation.z = svgMad->Hierarchie[h].Matrix.Translation.z
|
|
- svgMad->Hierarchie[p].Matrix.Translation.z;
|
|
}
|
|
|
|
//remise à zéro des points de pivots
|
|
for(int h=2; h<svgMad->NumberOfHierarchieNodes; h++)
|
|
{
|
|
svgMad->Hierarchie[h].Pivot.x = 0;
|
|
svgMad->Hierarchie[h].Pivot.y = 0;
|
|
svgMad->Hierarchie[h].Pivot.z = 0;
|
|
}
|
|
}
|
|
|
|
void createStroke(MAD_World* svgMad)
|
|
{
|
|
//initialisations
|
|
svgNbPoints = pointsList.size();
|
|
std::vector<PointF> innerPointsList;
|
|
std::vector<PointF> outerPointsList;
|
|
int strokeWidth = 1; if(cNode->Attribute("stroke-width")) strokeWidth = atoi(cNode->Attribute("stroke-width"));
|
|
strokeWidth *= 2; //TO IMPROVE
|
|
float strokeOpacity = 1.0; if(cNode->Attribute("stroke-opacity")) strokeOpacity = atof(cNode->Attribute("stroke-opacity"));
|
|
int deltaSup = strokeWidth - strokeWidth/2;
|
|
int deltaInf = strokeWidth/2;
|
|
|
|
//création des points du contour du path
|
|
PointF s0; PointF i0;
|
|
for(int i=0; i<svgNbPoints; i++)
|
|
{
|
|
//récupération des points de deux segments consécutifs
|
|
float xa = pointsList.at((i+0)%(svgNbPoints)).x; float ya = pointsList.at((i+0)%(svgNbPoints)).y;
|
|
float xb = pointsList.at((i+1)%(svgNbPoints)).x; float yb = pointsList.at((i+1)%(svgNbPoints)).y;
|
|
float xc = pointsList.at((i+2)%(svgNbPoints)).x; float yc = pointsList.at((i+2)%(svgNbPoints)).y;
|
|
|
|
//calcul des pentes de ces deux segments
|
|
float d1 = 1e30*signe(yb-ya); if(xa!=xb) d1 = (ya-yb)/(xa-xb);
|
|
float d2 = 1e30*signe(yc-yb); if(xb!=xc) d2 = (yb-yc)/(xb-xc);
|
|
|
|
//calcul des angles correspondants
|
|
float alpha1 = atan2(yb-ya, xb-xa);
|
|
float alpha2 = atan2(yc-yb, xc-xb);
|
|
|
|
//calcul des positions des quatres points sur le stroke (un intérieur et un extérieur pour chaque segment)
|
|
float xes = deltaSup*sin(alpha1) + xb; float yes = - deltaSup*cos(alpha1) + yb;
|
|
float xfs = deltaSup*sin(alpha2) + xb; float yfs = - deltaSup*cos(alpha2) + yb;
|
|
float xei = - deltaInf*sin(alpha1) + xb; float yei = deltaInf*cos(alpha1) + yb;
|
|
float xfi = - deltaInf*sin(alpha2) + xb; float yfi = deltaInf*cos(alpha2) + yb;
|
|
|
|
//calcul des ordonnées à l'origine des segments intérieurs et extérieurs du contour
|
|
float c3i = yei - d1*xei;
|
|
float c4i = yfi - d2*xfi;
|
|
float c3s = yes - d1*xes;
|
|
float c4s = yfs - d2*xfs;
|
|
|
|
//calcul des deux points d'intersection des segments intérieurs et extérieurs du contour
|
|
float xi = (c4i-c3i)/(d1-d2);
|
|
if(xa==xb)
|
|
xi = xb - signe(yb-ya)*deltaInf;
|
|
if(xb==xc)
|
|
xi = xb - signe(yc-yb)*deltaInf;
|
|
float yi = d1*xi + c3i;
|
|
if(xa==xb)
|
|
yi = d2*xi + c4i;
|
|
float xs = (c4s-c3s)/(d1-d2);
|
|
if(xa==xb)
|
|
xs = xb + signe(yb-ya)*deltaSup;
|
|
if(xb==xc)
|
|
xs = xb + signe(yc-yb)*deltaSup;
|
|
float ys = d1*xs + c3s;
|
|
if(xa==xb)
|
|
ys = d2*xs + c4s;
|
|
|
|
//ajout de ces deux points intérieur et extérieur au stroke
|
|
innerPointsList.push_back(PointF(xi, -yi));
|
|
outerPointsList.push_back(PointF(xs, -ys));
|
|
|
|
//mémorisation des premiers points intérieur et extérieur pour fermer le stroke
|
|
if(i==0)
|
|
{
|
|
i0 = PointF(xi, -yi);
|
|
s0 = PointF(xs, -ys);
|
|
}
|
|
}
|
|
//nettoyage des points colinéaires des contours intérieur et extérieur du stroke
|
|
cleanPointsList(innerPointsList);
|
|
cleanPointsList(outerPointsList);
|
|
|
|
//suppression des croisements dans le contour intérieur du stroke
|
|
PointF i1, i2, A, B;
|
|
for(int i=0; false && i<innerPointsList.size(); i++)
|
|
{
|
|
i1 = innerPointsList.at((i+0)%innerPointsList.size());
|
|
i2 = innerPointsList.at((i+1)%innerPointsList.size());
|
|
A = pointsList.at((i+1)%pointsList.size());
|
|
B = pointsList.at((i+2)%pointsList.size());
|
|
if((i1.x-i2.x)*(A.x-B.x) + (i1.y-i2.y)*(A.y-B.y) < 0)
|
|
{
|
|
PointF IA1(pointsList.at((i+0)%pointsList.size()));
|
|
PointF IB1(pointsList.at((i+1)%pointsList.size()));
|
|
PointF IA2(pointsList.at((i+1)%pointsList.size()));
|
|
PointF IB2(pointsList.at((i+2)%pointsList.size()));
|
|
//calcul du point d'intersection de (1) et (2)
|
|
//calcul des angles de (1) et (2)
|
|
float alpha1 = atan2(IB1.y - IA1.y, IB1.x - IA1.x);
|
|
float alpha2 = atan2(IB2.y - IA2.y, IB2.x - IA2.x);
|
|
//calcul des pentes de ces deux droites
|
|
float d1 = 1e30*signe(IB1.y-IA1.y); if(IB1.x!=IA1.x) d1 = (IA1.y-IB1.y)/(IA1.x-IB1.x);
|
|
float d2 = 1e30*signe(IB2.y-IA2.y); if(IB2.x!=IA2.x) d1 = (IA2.y-IB2.y)/(IA2.x-IB2.x);
|
|
//calcul des ordonnées à l'origine des segments intérieurs et extérieurs du contour
|
|
float c1 = i1.y - d1*i1.x;
|
|
float c2 = i2.y - d2*i2.x;
|
|
//calcul des deux points d'intersection des segments intérieurs et extérieurs du contour
|
|
float xi = (c2-c1)/(d1-d2);
|
|
/*
|
|
if(xa==xb)
|
|
xi = xb - signe(yb-ya)*deltaInf;
|
|
if(xb==xc)
|
|
xi = xb - signe(yc-yb)*deltaInf;
|
|
*/
|
|
float yi = d1*xi + c1;
|
|
/*
|
|
if(xa==xb)
|
|
yi = d2*xi + c4i;
|
|
*/
|
|
//i1 ou i2 devient ce point
|
|
innerPointsList.at((i+0)%innerPointsList.size()) = PointF(xi, yi);
|
|
}
|
|
}
|
|
cleanPointsList(innerPointsList);
|
|
//+idem dans l'autre sens //cleanage seulement après ???
|
|
|
|
//association des points du contour
|
|
std::vector<PointF> strokePointsList;
|
|
//strokePointsList.push_back(i0);
|
|
for(int i=0; i<innerPointsList.size(); i++) strokePointsList.push_back(innerPointsList.at(innerPointsList.size()-1-i));
|
|
//for(int i=0; i<outerPointsList.size(); i++) strokePointsList.push_back(outerPointsList.at(i));
|
|
//strokePointsList.push_back(s0);
|
|
|
|
//changement des points du path vers ceux de son contour
|
|
pointsList = strokePointsList;
|
|
svgNbPoints = strokePointsList.size();
|
|
|
|
//changement des propriétés de remplissage du path dans le node SVG pour devenir ceux du contour
|
|
cNode->SetAttribute("opacity", strokeOpacity);
|
|
cNode->SetAttribute("fill", cNode->Attribute("stroke"));
|
|
|
|
//ajout du contour au monde SVG
|
|
numberOfSvgTextures++;
|
|
addObjectInMadWorld(svgMad);
|
|
|
|
//inversion des 'z' du stroke et du contenu
|
|
///**
|
|
int objIndex = svgMad->NumberOfObjects-3;
|
|
float newSvgZ = (float)(objIndex+1)/100;
|
|
svgMad->Hierarchie[objIndex+1].Pivot.z = newSvgZ;
|
|
for(int n=0; n<svgObjects[objIndex]->NumberOfPoints; n++)
|
|
{
|
|
svgObjects[objIndex]->OBJ_PointList[n].Point.z = newSvgZ;
|
|
}
|
|
objIndex = svgMad->NumberOfObjects-2;
|
|
newSvgZ = (float)(objIndex-1)/100;
|
|
svgMad->Hierarchie[objIndex+1].Pivot.z = newSvgZ;
|
|
for(int n=0; n<svgObjects[objIndex]->NumberOfPoints; n++)
|
|
{
|
|
svgObjects[objIndex]->OBJ_PointList[n].Point.z = newSvgZ;
|
|
}
|
|
//**/
|
|
}
|
|
|
|
void addObjectInMadWorld(MAD_World* svgMad, int parentHierIndex, bool isAGroupNode)
|
|
{
|
|
bool isAnObject = !isAGroupNode;
|
|
//initialisations
|
|
int hieIndex = (svgMad->NumberOfHierarchieNodes)++;
|
|
int objIndex = MAD_NULL_INDEX;
|
|
int matIndex = MAD_NULL_INDEX;
|
|
int texIndex = MAD_NULL_INDEX;
|
|
if(isAnObject)
|
|
{
|
|
objIndex = (svgMad->NumberOfObjects)++;
|
|
matIndex = (svgMad->NumberOfMaterials)++;
|
|
texIndex = (svgMad->NumberOftexture)++;
|
|
}
|
|
|
|
//récupération de l'identifiant de l'objet sous illustrator
|
|
char textureFilename[260] = "";
|
|
if(cNode->Attribute("id") && cNode->Attribute("id")[0])
|
|
sprintf(svgObjectID, "%s\0", cNode->Attribute("id"));
|
|
else
|
|
sprintf(svgObjectID, "unnamed%d\0", svgMad->NumberOfHierarchieNodes-1);
|
|
//restitution des espaces
|
|
for(int i=0; i<strlen(svgObjectID); i++)
|
|
{
|
|
if(svgObjectID[i] == '_')
|
|
{
|
|
svgObjectID[i] = ' ';
|
|
}
|
|
}
|
|
//restitution des underscores
|
|
for(int i=0; i<strlen(svgObjectID)-5; i++)
|
|
{
|
|
if(strncmp(svgObjectID+i, " x5F ", 5)==0)
|
|
{
|
|
svgObjectID[i] = '_';
|
|
memmove(svgObjectID+i+1, svgObjectID+i+5, strlen(svgObjectID)+1-(i+5));
|
|
}
|
|
}
|
|
//correction de la multiplicité des identifiants
|
|
if(svgObjectID[strlen(svgObjectID)-1] == ' ')
|
|
{
|
|
svgObjectID[strlen(svgObjectID)-1] = ')';
|
|
for(int i=strlen(svgObjectID)-1; i>=0; i--)
|
|
{
|
|
if(svgObjectID[i] == ' ')
|
|
{
|
|
svgObjectID[i] = '(';
|
|
i = -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(isAnObject)
|
|
{
|
|
//position infinitésimale en z de l'objet pour éviter les problèmes de rendu de superposition
|
|
svgz = (float)objIndex/100;
|
|
|
|
//triangulation des points de l'objet en vertices
|
|
MAD_Simple3DVertex* madPointsList = (MAD_Simple3DVertex*)malloc2(svgNbPoints*sizeof(MAD_Simple3DVertex));
|
|
MAD_GeometricObjectElement* madTrianglesList = (MAD_GeometricObjectElement*)malloc2(sizeof(MAD_GeometricObjectElement));
|
|
triangulatePath(madPointsList, madTrianglesList);
|
|
|
|
//création des coordonnées de texture
|
|
MAD_Vertex* madUVList = (MAD_Vertex*)malloc2(svgNbPoints*sizeof(MAD_Vertex));
|
|
createUVCoords(madUVList);
|
|
|
|
//création du matérial à ajouter
|
|
//création du fichier image de la texture
|
|
sprintf(textureFilename, "%s\\%s - texture.tga", svgTexturesDir, svgObjectID);
|
|
SvgTextureType textureType = svgTextures[numberOfSvgTextures-1].type;
|
|
if(textureType == PNG_IMAGE || textureType == JPEG_IMAGE)
|
|
createImageTexture(textureFilename);
|
|
else
|
|
createShapeTexture(textureFilename);
|
|
|
|
//création de la structure de la texture
|
|
MAD_texture* texture = (MAD_texture*)malloc2(sizeof(MAD_texture));
|
|
texture->ID.IDType = ID_MAD_Texture;
|
|
memset(texture->ID.Name, 0, 256);
|
|
sprintf(texture->ID.Name, "%s - texture.tga", svgObjectID);
|
|
memset(texture->Texturefile, 0, 260);
|
|
char appliPath[260] = "";
|
|
GetModuleFileName(NULL, appliPath, 2048);
|
|
*(strrchr(appliPath, '\\')+1) = '\0';
|
|
sprintf(texture->Texturefile, "%s%s", appliPath, textureFilename);
|
|
textureFilenames = (char**)realloc2(textureFilenames, svgMad->NumberOfObjects*sizeof(char*));
|
|
textureFilenames[svgMad->NumberOfObjects-1] = (char*)malloc2(261);
|
|
strcpy(textureFilenames[svgMad->NumberOfObjects-1], textureFilename);
|
|
//affectation de la texture au MadWorld
|
|
svgMad->AllTextures = (MAD_texture**)realloc2(svgMad->AllTextures, (svgMad->NumberOftexture)*sizeof(MAD_texture*));
|
|
svgMad->AllTextures[texIndex] = texture;
|
|
//création du MAD_StandarMaterial
|
|
MAD_StandarMaterial* material = (MAD_StandarMaterial*)malloc2(sizeof(MAD_StandarMaterial));
|
|
material->Diffuse = -1;
|
|
material->Ambient = 0;
|
|
material->Specular = 0;
|
|
material->SelfIllum = 1.0;
|
|
if(cNode->Attribute("opacity") && cNode->Attribute("opacity")[0])
|
|
material->Opacity = (float)atof(cNode->Attribute("opacity"));
|
|
else material->Opacity = 1.0;
|
|
material->MaterialFlag = MAD_MTF_PerspectivCorrection | MAD_MTF_Trans_Alpha; //TO CHECK
|
|
material->MadTexture = texIndex;
|
|
material->MatRef.MaterialType = ID_MAT_Standard;
|
|
memset(material->MatRef.Name, 0, 256);
|
|
sprintf(material->MatRef.Name, "%s - material", svgObjectID);
|
|
//réallocation de la liste des materiaux du MAD_World
|
|
svgMad->AllMaterial = (MAD_MAT_MatID**)realloc2(svgMad->AllMaterial, (svgMad->NumberOfMaterials)*sizeof(MAD_MAT_MatID*));
|
|
//affectation du MatID
|
|
svgMad->AllMaterial[matIndex] = &material->MatRef;
|
|
|
|
//création du GeometricObject à ajouter
|
|
MAD_GeometricObject* vectorialObject;
|
|
vectorialObject = (MAD_GeometricObject*)malloc2(sizeof(MAD_GeometricObject));
|
|
vectorialObject->ID.IDType = ID_MAD_GeometricObject_V0;
|
|
vectorialObject->ID.SizeOfThisOne = sizeof(MAD_GeometricObject);
|
|
memset(vectorialObject->ID.Name, 0, 256);
|
|
sprintf(vectorialObject->ID.Name, "%s - mesh", svgObjectID);
|
|
vectorialObject->NumberOfPoints = svgNbPoints;
|
|
vectorialObject->OBJ_PointList = madPointsList;
|
|
if(objIndex==1)
|
|
saveMadPointsList = vectorialObject->OBJ_PointList;
|
|
vectorialObject->NumberOfUV = svgNbPoints;
|
|
vectorialObject->OBJ_UVtextureList = madUVList;
|
|
//ajout des éléments
|
|
vectorialObject->NumberOfElements = 1;
|
|
vectorialObject->Elements = (MAD_GeometricObjectElement**)malloc2((vectorialObject->NumberOfElements)*sizeof(MAD_GeometricObjectElement*));
|
|
//ajout des triangles à l'objet
|
|
vectorialObject->Elements[0] = madTrianglesList;
|
|
vectorialObject->SecondRLIField = 0;
|
|
vectorialObject->Colors = 0;
|
|
//mémorisation de l'adresse de l'objet
|
|
svgObjects = (MAD_GeometricObject**)realloc2(svgObjects, (objIndex)*sizeof(MAD_GeometricObject*));
|
|
svgObjects[objIndex-1] = vectorialObject;
|
|
|
|
//réallocation de la liste des objects du MAD_World
|
|
svgMad->AllObjects = (MAD_NodeID**)realloc2(svgMad->AllObjects, (svgMad->NumberOfObjects)*sizeof(MAD_NodeID*));
|
|
svgMad->AllObjects[objIndex] = &vectorialObject->ID;
|
|
}
|
|
|
|
//réallocation de la hiérarchie
|
|
svgMad->Hierarchie = (MAD_WorldNode*)realloc2(svgMad->Hierarchie, (svgMad->NumberOfHierarchieNodes)*sizeof(MAD_WorldNode));
|
|
MAD_WorldNode* hierarchie = svgMad->Hierarchie;
|
|
memset(&hierarchie[hieIndex], 0, sizeof(MAD_WorldNode));
|
|
//ajout du noeud SVG à la hierarchie
|
|
svgNodes.push_back(cNode);
|
|
//recherche de la visibilité de l'objet //TO CHECK
|
|
int visible = 1;
|
|
int indexInHier = 0;
|
|
TiXmlElement* node = cNode;
|
|
do
|
|
{
|
|
if(node->Attribute("display") && strcmp(node->Attribute("display"), "none")==0)
|
|
visible = -1;
|
|
node = node->Parent()->ToElement();
|
|
} while(node);
|
|
|
|
//ajout d'un objet à la hiérarchie
|
|
//ID
|
|
hierarchie[hieIndex].ID.IDType = ID_MAD_Dummy; //de type "boite vide"
|
|
if(isAnObject) hierarchie[hieIndex].ID.IDType = ID_MAD_Shape; //de type "objet"
|
|
hierarchie[hieIndex].ID.SizeOfThisOne = 0;
|
|
memset(hierarchie[hieIndex].ID.Name, 0, 256);
|
|
sprintf(hierarchie[hieIndex].ID.Name, "%s", svgObjectID);
|
|
//Matrix
|
|
hierarchie[hieIndex].Matrix.ID.IDType = ID_MAD_Matrix;
|
|
hierarchie[hieIndex].Matrix.ID.SizeOfThisOne = sizeof(hierarchie[hieIndex].Matrix);
|
|
memset(hierarchie[hieIndex].Matrix.ID.Name, 0, 256);
|
|
sprintf(hierarchie[hieIndex].Matrix.ID.Name, "%s - GlobalMatrix", svgObjectID);
|
|
|
|
hierarchie[hieIndex].Matrix.Translation.x = 0;
|
|
hierarchie[hieIndex].Matrix.Translation.y = 0;
|
|
hierarchie[hieIndex].Matrix.Translation.z = 0;
|
|
|
|
hierarchie[hieIndex].Matrix.I.x = 1;
|
|
hierarchie[hieIndex].Matrix.I.y = 0;
|
|
hierarchie[hieIndex].Matrix.I.z = 0;
|
|
|
|
hierarchie[hieIndex].Matrix.J.x = 0;
|
|
hierarchie[hieIndex].Matrix.J.y = visible*1;
|
|
hierarchie[hieIndex].Matrix.J.z = 0;
|
|
|
|
hierarchie[hieIndex].Matrix.K.x = 0;
|
|
hierarchie[hieIndex].Matrix.K.y = 0;
|
|
hierarchie[hieIndex].Matrix.K.z = visible*1;
|
|
//RelativeMatrix
|
|
hierarchie[hieIndex].RelativeMatrix.ID.IDType = ID_MAD_Matrix;
|
|
hierarchie[hieIndex].RelativeMatrix.ID.SizeOfThisOne = sizeof(hierarchie[hieIndex].RelativeMatrix);
|
|
memset(hierarchie[hieIndex].RelativeMatrix.ID.Name, 0, 256);
|
|
sprintf(hierarchie[hieIndex].RelativeMatrix.ID.Name, "%s - LocalMatrix", svgObjectID);
|
|
|
|
hierarchie[hieIndex].RelativeMatrix.Translation.x = 0;
|
|
hierarchie[hieIndex].RelativeMatrix.Translation.y = 0;
|
|
hierarchie[hieIndex].RelativeMatrix.Translation.z = 0;
|
|
|
|
hierarchie[hieIndex].RelativeMatrix.I.x = 1;
|
|
hierarchie[hieIndex].RelativeMatrix.I.y = 0;
|
|
hierarchie[hieIndex].RelativeMatrix.I.z = 0;
|
|
|
|
hierarchie[hieIndex].RelativeMatrix.J.x = 0;
|
|
hierarchie[hieIndex].RelativeMatrix.J.y = visible*1;
|
|
hierarchie[hieIndex].RelativeMatrix.J.z = 0;
|
|
|
|
hierarchie[hieIndex].RelativeMatrix.K.x = 0;
|
|
hierarchie[hieIndex].RelativeMatrix.K.y = 0;
|
|
hierarchie[hieIndex].RelativeMatrix.K.z = visible*1;
|
|
//Pivot
|
|
hierarchie[hieIndex].Pivot.x = 0;
|
|
hierarchie[hieIndex].Pivot.y = 0;
|
|
hierarchie[hieIndex].Pivot.z = 0;
|
|
if(isAnObject)
|
|
{
|
|
hierarchie[hieIndex].Pivot.x = objectCenter.x;
|
|
hierarchie[hieIndex].Pivot.y = objectCenter.y;
|
|
hierarchie[hieIndex].Pivot.z = svgz;
|
|
}
|
|
//le reste
|
|
hierarchie[hieIndex].WiredColor = 0xff00ff; //blanc sous MAX //TO CHECK (couleur des meshes sous MAX ?)
|
|
hierarchie[hieIndex].Object = objIndex;
|
|
hierarchie[hieIndex].ObjectWithRadiosity = MAD_NULL_INDEX;
|
|
hierarchie[hieIndex].Parent = parentHierIndex;
|
|
hierarchie[hieIndex].Target = MAD_NULL_INDEX;
|
|
hierarchie[hieIndex].Material = matIndex;
|
|
hierarchie[hieIndex].RLIOfObject = 0;
|
|
}
|
|
|
|
void initSvgMad(MAD_World* svgMad)
|
|
{
|
|
//initialisation de la bounding box du monde SVG à créer
|
|
svgWorld_Xmin = 1e30; svgWorld_Ymin = 1e30;
|
|
svgWorld_Xmax = -1e30; svgWorld_Ymax = -1e30;
|
|
|
|
//remplissage du MAD_World
|
|
svgMad->MAD_Version = 0xc0de0000;
|
|
svgMad->ID.IDType = ID_MAD_World;
|
|
svgMad->ID.SizeOfThisOne = sizeof(MAD_World);
|
|
strcpy(svgMad->ID.Name, "svgWorld");
|
|
svgMad->AmbientColor = 0;
|
|
svgMad->NumberOftexture = 0;
|
|
svgMad->AllTextures = (MAD_texture**)malloc2(sizeof(MAD_texture*));
|
|
svgMad->NumberOfMaterials = 0;
|
|
svgMad->AllMaterial = (MAD_MAT_MatID**)malloc2(sizeof(MAD_MAT_MatID*));
|
|
svgMad->NumberOfObjects = 1;
|
|
svgMad->AllObjects = (MAD_NodeID**)malloc2(sizeof(MAD_NodeID*));
|
|
svgMad->NumberOfHierarchieNodes = 2;
|
|
svgMad->Hierarchie = (MAD_WorldNode*)malloc2((svgMad->NumberOfHierarchieNodes)*sizeof(MAD_WorldNode));
|
|
|
|
//création de la hiérarchie pour l'objet "Scene Root"
|
|
svgMad->Hierarchie[0].ID.IDType = ID_MAD_UNDEFINED;
|
|
svgMad->Hierarchie[0].ID.SizeOfThisOne = 0;
|
|
strcpy(svgMad->Hierarchie[0].ID.Name, "Scene Root");
|
|
svgMad->Hierarchie[0].Object = MAD_NULL_INDEX;
|
|
svgMad->Hierarchie[0].ObjectWithRadiosity = MAD_NULL_INDEX;
|
|
svgMad->Hierarchie[0].Parent = MAD_NULL_INDEX;
|
|
svgMad->Hierarchie[0].Target = MAD_NULL_INDEX;
|
|
svgMad->Hierarchie[0].Material = MAD_NULL_INDEX;
|
|
svgMad->Hierarchie[0].RLIOfObject = 0;
|
|
//Matrix
|
|
svgMad->Hierarchie[0].Matrix.ID.IDType = ID_MAD_Matrix;
|
|
svgMad->Hierarchie[0].Matrix.ID.SizeOfThisOne = sizeof(svgMad->Hierarchie[0].Matrix);
|
|
memset(svgMad->Hierarchie[0].Matrix.ID.Name, 0, 256);
|
|
sprintf(svgMad->Hierarchie[0].Matrix.ID.Name, "Scene Root_GlobalMatrix");
|
|
svgMad->Hierarchie[0].Matrix.Translation.x = 0;
|
|
svgMad->Hierarchie[0].Matrix.Translation.y = 0;
|
|
svgMad->Hierarchie[0].Matrix.Translation.z = 0;
|
|
svgMad->Hierarchie[0].Matrix.I.x = 1;
|
|
svgMad->Hierarchie[0].Matrix.I.y = 0;
|
|
svgMad->Hierarchie[0].Matrix.I.z = 0;
|
|
svgMad->Hierarchie[0].Matrix.J.x = 0;
|
|
svgMad->Hierarchie[0].Matrix.J.y = 1;
|
|
svgMad->Hierarchie[0].Matrix.J.z = 0;
|
|
svgMad->Hierarchie[0].Matrix.K.x = 0;
|
|
svgMad->Hierarchie[0].Matrix.K.y = 0;
|
|
svgMad->Hierarchie[0].Matrix.K.z = 1;
|
|
//RelativeMatrix
|
|
svgMad->Hierarchie[0].RelativeMatrix.ID.IDType = ID_MAD_Matrix;
|
|
svgMad->Hierarchie[0].RelativeMatrix.ID.SizeOfThisOne = sizeof(svgMad->Hierarchie[0].RelativeMatrix);
|
|
memset(svgMad->Hierarchie[0].RelativeMatrix.ID.Name, 0, 256);
|
|
sprintf(svgMad->Hierarchie[0].RelativeMatrix.ID.Name, "Scene Root_LocalMatrix");
|
|
svgMad->Hierarchie[0].RelativeMatrix.Translation.x = 0;
|
|
svgMad->Hierarchie[0].RelativeMatrix.Translation.y = 0;
|
|
svgMad->Hierarchie[0].RelativeMatrix.Translation.z = 0;
|
|
svgMad->Hierarchie[0].RelativeMatrix.I.x = 0;
|
|
svgMad->Hierarchie[0].RelativeMatrix.I.y = 1;
|
|
svgMad->Hierarchie[0].RelativeMatrix.I.z = 0;
|
|
svgMad->Hierarchie[0].RelativeMatrix.J.x = 1;
|
|
svgMad->Hierarchie[0].RelativeMatrix.J.y = 0;
|
|
svgMad->Hierarchie[0].RelativeMatrix.J.z = 0;
|
|
svgMad->Hierarchie[0].RelativeMatrix.K.x = 0;
|
|
svgMad->Hierarchie[0].RelativeMatrix.K.y = 0;
|
|
svgMad->Hierarchie[0].RelativeMatrix.K.z = 1;
|
|
//Pivot
|
|
svgMad->Hierarchie[0].Pivot.x = 0;
|
|
svgMad->Hierarchie[0].Pivot.y = 0;
|
|
svgMad->Hierarchie[0].Pivot.z = 0;
|
|
|
|
//création de la caméra
|
|
MAD_Camera* camera = (MAD_Camera*)malloc2(sizeof(MAD_Camera));
|
|
camera->CameraType = MAD_e_PerspCamera;
|
|
camera->ID.IDType = ID_MAD_Camera;
|
|
strcpy(camera->ID.Name, "CP\0");
|
|
camera->ID.SizeOfThisOne = sizeof(MAD_Camera);
|
|
camera->PerspInf.Fov = 0.25;
|
|
camera->PerspInf.Znear = -100.0f;
|
|
camera->PerspInf.Zfar = 1000.0f;
|
|
svgMad->AllObjects[0] = &camera->ID;
|
|
//création de sa hiérarchie
|
|
svgMad->Hierarchie[1].ID.IDType = ID_MAD_Camera;
|
|
svgMad->Hierarchie[1].ID.SizeOfThisOne = sizeof(MAD_Camera);
|
|
strcpy(svgMad->Hierarchie[1].ID.Name, "CP\0");
|
|
svgMad->Hierarchie[1].Object = 0;
|
|
svgMad->Hierarchie[1].Parent = MAD_NULL_INDEX;
|
|
//Matrix
|
|
svgMad->Hierarchie[1].Matrix.ID.IDType = ID_MAD_Matrix;
|
|
svgMad->Hierarchie[1].Matrix.ID.SizeOfThisOne = sizeof(svgMad->Hierarchie[1].Matrix);
|
|
memset(svgMad->Hierarchie[1].Matrix.ID.Name, 0, 256);
|
|
sprintf(svgMad->Hierarchie[1].Matrix.ID.Name, "CP_GlobalMatrix");
|
|
svgMad->Hierarchie[1].Matrix.I.x = 1;
|
|
svgMad->Hierarchie[1].Matrix.I.y = 0;
|
|
svgMad->Hierarchie[1].Matrix.I.z = 0;
|
|
svgMad->Hierarchie[1].Matrix.J.x = 0;
|
|
svgMad->Hierarchie[1].Matrix.J.y = 1;
|
|
svgMad->Hierarchie[1].Matrix.J.z = 0;
|
|
svgMad->Hierarchie[1].Matrix.K.x = 0;
|
|
svgMad->Hierarchie[1].Matrix.K.y = 0;
|
|
svgMad->Hierarchie[1].Matrix.K.z = 1;
|
|
}
|
|
|
|
void madPath(TiXmlNode* node, MAD_World* svgMad)
|
|
{
|
|
//initialisation des variables globales
|
|
{
|
|
//longueur du path
|
|
pathLen = strlen(node->ToElement()->Attribute("d"))+1;
|
|
|
|
//allocation du nouveau path
|
|
pathOut = (char*)malloc2(pathLen);
|
|
startOfPathOut = pathOut;
|
|
|
|
//initialisation de la liste de points
|
|
pointsList.clear();
|
|
}
|
|
|
|
//traitement des fonctions path
|
|
char* path = (char*)malloc2(pathLen);
|
|
strcpy(path, node->ToElement()->Attribute("d"));
|
|
float x0 = 0, y0 = 0; //starting point
|
|
float x = 0, y = 0; //toward point
|
|
char lastMode = 0;
|
|
PointF ctrlPt;
|
|
char *str = path;
|
|
char *end = str + pathLen;
|
|
while (*str != 0 && str != end) {
|
|
char pathElem = *str;
|
|
str++;
|
|
|
|
//création de la file des arguments flottants pour les fonctions du path
|
|
std::vector<float> arg;
|
|
float f = 0;
|
|
while((f=getFloat(str))!=0 || *str==',' || *str==' ' || *str=='\n')
|
|
{
|
|
if(f)
|
|
{
|
|
if(f==1e-30) arg.push_back(0);
|
|
else arg.push_back(f);
|
|
}
|
|
else str++;
|
|
}
|
|
|
|
if (pathElem == 'z' || pathElem == 'Z')
|
|
arg.push_back(0);
|
|
while (!arg.empty()) {
|
|
float offsetX = x; // correction offsets
|
|
float offsetY = y; // for relative commands
|
|
CP = PointF(x,y);
|
|
SP = PointF(x0,y0);
|
|
switch (pathElem) {
|
|
case 'm': {
|
|
if (arg.size() < 2) {
|
|
arg.erase(arg.begin());
|
|
break;
|
|
}
|
|
x = x0 = arg[0] + offsetX;
|
|
y = y0 = arg[1] + offsetY;
|
|
moveTo(x0, y0);
|
|
arg.erase(arg.begin()); arg.erase(arg.begin());
|
|
}
|
|
break;
|
|
case 'M': {
|
|
if (arg.size() < 2) {
|
|
arg.erase(arg.begin());
|
|
break;
|
|
}
|
|
x = x0 = arg[0];
|
|
y = y0 = arg[1];
|
|
|
|
moveTo(x0, y0);
|
|
arg.erase(arg.begin()); arg.erase(arg.begin());
|
|
}
|
|
break;
|
|
case 'z':
|
|
case 'Z': {
|
|
x = x0;
|
|
y = y0;
|
|
closePath();
|
|
arg.erase(arg.begin());
|
|
}
|
|
break;
|
|
case 'l': {
|
|
if (arg.size() < 2) {
|
|
arg.erase(arg.begin());
|
|
break;
|
|
}
|
|
x = arg.front() + offsetX;
|
|
arg.erase(arg.begin());
|
|
y = arg.front() + offsetY;
|
|
arg.erase(arg.begin());
|
|
lineTo(x, y);
|
|
|
|
}
|
|
break;
|
|
case 'L': {
|
|
if (arg.size() < 2) {
|
|
arg.erase(arg.begin());
|
|
break;
|
|
}
|
|
x = arg.front(); arg.erase(arg.begin());
|
|
y = arg.front(); arg.erase(arg.begin());
|
|
lineTo(x, y);
|
|
}
|
|
break;
|
|
case 'h': {
|
|
x = arg.front() + offsetX; arg.erase(arg.begin());
|
|
lineTo(x, y);
|
|
}
|
|
break;
|
|
case 'H': {
|
|
x = arg[0];
|
|
lineTo(x, y);
|
|
arg.erase(arg.begin());
|
|
}
|
|
break;
|
|
case 'v': {
|
|
y = arg[0] + offsetY;
|
|
lineTo(x, y);
|
|
arg.erase(arg.begin());
|
|
}
|
|
break;
|
|
case 'V': {
|
|
y = arg[0];
|
|
lineTo(x, y);
|
|
arg.erase(arg.begin());
|
|
}
|
|
break;
|
|
case 'c': {
|
|
if (arg.size() < 6) {
|
|
while (arg.size())
|
|
arg.erase(arg.begin());
|
|
break;
|
|
}
|
|
PointF c1(arg[0]+offsetX, arg[1]+offsetY);
|
|
PointF c2(arg[2]+offsetX, arg[3]+offsetY);
|
|
PointF e(arg[4]+offsetX, arg[5]+offsetY);
|
|
cubicTo(c1, c2, e);
|
|
ctrlPt = c2;
|
|
x = e.x;
|
|
y = e.y;
|
|
arg.erase(arg.begin()); arg.erase(arg.begin());
|
|
arg.erase(arg.begin()); arg.erase(arg.begin());
|
|
arg.erase(arg.begin()); arg.erase(arg.begin());
|
|
break;
|
|
}
|
|
case 'C': {
|
|
if (arg.size() < 6) {
|
|
while (arg.size())
|
|
arg.erase(arg.begin());
|
|
break;
|
|
}
|
|
PointF c1(arg[0], arg[1]);
|
|
PointF c2(arg[2], arg[3]);
|
|
PointF e(arg[4], arg[5]);
|
|
cubicTo(c1, c2, e);
|
|
ctrlPt = c2;
|
|
x = e.x;
|
|
y = e.y;
|
|
arg.erase(arg.begin()); arg.erase(arg.begin());
|
|
arg.erase(arg.begin()); arg.erase(arg.begin());
|
|
arg.erase(arg.begin()); arg.erase(arg.begin());
|
|
break;
|
|
}
|
|
case 's': {
|
|
if (arg.size() < 4) {
|
|
while (arg.size())
|
|
arg.erase(arg.begin());
|
|
break;
|
|
}
|
|
PointF c1;
|
|
if (lastMode == 'c' || lastMode == 'C' ||
|
|
lastMode == 's' || lastMode == 'S')
|
|
c1 = PointF(2*x-ctrlPt.x, 2*y-ctrlPt.y);
|
|
else
|
|
c1 = PointF(x, y);
|
|
PointF c2(arg[0]+offsetX, arg[1]+offsetY);
|
|
PointF e(arg[2]+offsetX, arg[3]+offsetY);
|
|
cubicTo(c1, c2, e);
|
|
ctrlPt = c2;
|
|
x = e.x;
|
|
y = e.y;
|
|
arg.erase(arg.begin()); arg.erase(arg.begin());
|
|
arg.erase(arg.begin()); arg.erase(arg.begin());
|
|
break;
|
|
}
|
|
case 'S': {
|
|
if (arg.size() < 4) {
|
|
while (arg.size())
|
|
arg.erase(arg.begin());
|
|
break;
|
|
}
|
|
PointF c1;
|
|
if (lastMode == 'c' || lastMode == 'C' ||
|
|
lastMode == 's' || lastMode == 'S')
|
|
c1 = PointF(2*x-ctrlPt.x, 2*y-ctrlPt.y);
|
|
else
|
|
c1 = PointF(x, y);
|
|
PointF c2(arg[0], arg[1]);
|
|
PointF e(arg[2], arg[3]);
|
|
cubicTo(c1, c2, e);
|
|
ctrlPt = c2;
|
|
x = e.x;
|
|
y = e.y;
|
|
arg.erase(arg.begin()); arg.erase(arg.begin());
|
|
arg.erase(arg.begin()); arg.erase(arg.begin());
|
|
break;
|
|
}
|
|
case 'q': {
|
|
if (arg.size() < 4) {
|
|
while (arg.size())
|
|
arg.erase(arg.begin());
|
|
break;
|
|
}
|
|
PointF c(arg[0]+offsetX, arg[1]+offsetY);
|
|
PointF e(arg[2]+offsetX, arg[3]+offsetY);
|
|
quadTo(c, e);
|
|
ctrlPt = c;
|
|
x = e.x;
|
|
y = e.y;
|
|
arg.erase(arg.begin()); arg.erase(arg.begin());
|
|
arg.erase(arg.begin()); arg.erase(arg.begin());
|
|
break;
|
|
}
|
|
case 'Q': {
|
|
if (arg.size() < 4) {
|
|
while (arg.size())
|
|
arg.erase(arg.begin());
|
|
break;
|
|
}
|
|
PointF c(arg[0], arg[1]);
|
|
PointF e(arg[2], arg[3]);
|
|
quadTo(c, e);
|
|
ctrlPt = c;
|
|
x = e.x;
|
|
y = e.y;
|
|
arg.erase(arg.begin()); arg.erase(arg.begin());
|
|
arg.erase(arg.begin()); arg.erase(arg.begin());
|
|
break;
|
|
}
|
|
case 't': {
|
|
if (arg.size() < 2) {
|
|
while (arg.size())
|
|
arg.erase(arg.begin());
|
|
break;
|
|
}
|
|
PointF e(arg[0]+offsetX, arg[1]+offsetY);
|
|
PointF c;
|
|
if (lastMode == 'q' || lastMode == 'Q' ||
|
|
lastMode == 't' || lastMode == 'T')
|
|
c = PointF(2*x-ctrlPt.x, 2*y-ctrlPt.y);
|
|
else
|
|
c = PointF(x, y);
|
|
quadTo(c, e);
|
|
ctrlPt = c;
|
|
x = e.x;
|
|
y = e.y;
|
|
arg.erase(arg.begin()); arg.erase(arg.begin());
|
|
break;
|
|
}
|
|
case 'T': {
|
|
if (arg.size() < 2) {
|
|
while (arg.size())
|
|
arg.erase(arg.begin());
|
|
break;
|
|
}
|
|
PointF e(arg[0], arg[1]);
|
|
PointF c;
|
|
if (lastMode == 'q' || lastMode == 'Q' ||
|
|
lastMode == 't' || lastMode == 'T')
|
|
c = PointF(2*x-ctrlPt.x, 2*y-ctrlPt.y);
|
|
else
|
|
c = PointF(x, y);
|
|
quadTo(c, e);
|
|
ctrlPt = c;
|
|
x = e.x;
|
|
y = e.y;
|
|
arg.erase(arg.begin()); arg.erase(arg.begin());
|
|
break;
|
|
}
|
|
case 'a': {
|
|
if (arg.size() < 7) {
|
|
while (arg.size())
|
|
arg.erase(arg.begin());
|
|
break;
|
|
}
|
|
float rx = arg[0];
|
|
float ry = arg[1];
|
|
float xAxisRotation = arg[2];
|
|
float largeArcFlag = arg[3];
|
|
float sweepFlag = arg[4];
|
|
float ex = arg[5] + offsetX;
|
|
float ey = arg[6] + offsetY;
|
|
float curx = x;
|
|
float cury = y;
|
|
pathArc(rx, ry, xAxisRotation, int(largeArcFlag), int(sweepFlag), ex, ey, curx, cury);
|
|
|
|
x = ex;
|
|
y = ey;
|
|
|
|
arg.erase(arg.begin()); arg.erase(arg.begin());
|
|
arg.erase(arg.begin()); arg.erase(arg.begin());
|
|
arg.erase(arg.begin()); arg.erase(arg.begin());
|
|
arg.erase(arg.begin());
|
|
}
|
|
break;
|
|
case 'A': {
|
|
if (arg.size() < 7) {
|
|
while (arg.size())
|
|
arg.erase(arg.begin());
|
|
break;
|
|
}
|
|
float rx = arg[0];
|
|
float ry = arg[1];
|
|
float xAxisRotation = arg[2];
|
|
float largeArcFlag = arg[3];
|
|
float sweepFlag = arg[4];
|
|
float ex = arg[5];
|
|
float ey = arg[6];
|
|
float curx = x;
|
|
float cury = y;
|
|
pathArc(rx, ry, xAxisRotation, int(largeArcFlag), int(sweepFlag), ex, ey, curx, cury);
|
|
x = ex;
|
|
y = ey;
|
|
arg.erase(arg.begin()); arg.erase(arg.begin());
|
|
arg.erase(arg.begin()); arg.erase(arg.begin());
|
|
arg.erase(arg.begin()); arg.erase(arg.begin());
|
|
arg.erase(arg.begin());
|
|
}
|
|
break;
|
|
}
|
|
lastMode = pathElem;
|
|
}
|
|
}
|
|
|
|
//suppression des points successifs colinéaires
|
|
cleanPointsList(pointsList);
|
|
svgNbPoints = pointsList.size();
|
|
|
|
//réallocation de l'attribut d modifié
|
|
node->ToElement()->SetAttribute("d", startOfPathOut);
|
|
|
|
//ajout de la forme au madWorld
|
|
addObjectInMadWorld(svgMad);
|
|
|
|
//ajout du contour de la forme au madWorld
|
|
//TO FINISH:
|
|
//if(cNode->Attribute("stroke")) createStroke(svgMad);
|
|
|
|
//libération de la mémoire
|
|
free2(path);
|
|
if(startOfPathOut) free2(startOfPathOut);
|
|
}
|
|
|
|
bool svg2mad(char* svgFilename, char* destMadFilename)
|
|
{
|
|
//récupération du facteur de conversion d'unités entre Illustrator et Camcam
|
|
char factorConv[10] = "30";
|
|
if(TheScene->GetIniValue(CamcamCCM, "svgPixelsPer3DSMaxUnit"))
|
|
TheScene->GetIniValue(CamcamCCM, "svgPixelsPer3DSMaxUnit", factorConv);
|
|
PIXELS_PER_UNIT = (float)atof(factorConv);
|
|
|
|
//précaution sur les fichiers d'entrée et de sortie de la conversion
|
|
if(lengthOfFile(svgFilename)==-1 ||
|
|
strcmp(strlwr(svgFilename+strlen(svgFilename)-4), ".svg") ||
|
|
strcmp(strlwr(destMadFilename+strlen(destMadFilename)-4), ".mad"))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
//création du répertoire hébergeant les fichiers images des textures
|
|
char destFilename[500] = "";
|
|
strcpy(destFilename, destMadFilename);
|
|
destFilename[strlen(destMadFilename)-4] = 0;
|
|
sprintf(svgTexturesDir, "%s - textures", destFilename);
|
|
CreateDirectory(svgTexturesDir, NULL);
|
|
CleanDirectory(svgTexturesDir);
|
|
|
|
//travail sur une copie du fichier SVG original pour raison de sécurité
|
|
char tmpSvgFilename[] = "Mads\\tmpSvg.txt";
|
|
CopyFile(svgFilename, tmpSvgFilename, 0);
|
|
|
|
//suppression du header XML pour éviter les crashs de la librairie
|
|
long int posHead = findText(tmpSvgFilename, 0, "?>");
|
|
posHead = findText(tmpSvgFilename, posHead, "<");
|
|
long int posSvg = findText(tmpSvgFilename, 0, "<svg");
|
|
posSvg = 1 + findText(tmpSvgFilename, posSvg-4, "\n");
|
|
char* xmlHeader = (char*)malloc2(posSvg-posHead+10);
|
|
getText(tmpSvgFilename, posHead, posSvg, xmlHeader);
|
|
deleteText(tmpSvgFilename, posHead, posSvg);
|
|
|
|
//parcours et conversion des formes vectorielles du document SVG en structure MAD
|
|
MAD_World* svgMad = (MAD_World*)malloc2(sizeof(MAD_World));
|
|
TiXmlDocument doc(tmpSvgFilename);
|
|
bool svgFileLoaded = doc.LoadFile();
|
|
if(svgFileLoaded)
|
|
{
|
|
TiXmlNode* svgNode = doc.FirstChild("svg");
|
|
initSvgMad(svgMad);
|
|
browseNode(svgNode, svgMad);
|
|
scaleSvgWorld(svgMad);
|
|
}
|
|
|
|
//sauvegarde de la structure MAD puis suppression de celle-ci
|
|
if(svgFileLoaded)
|
|
{
|
|
FILE* svgMadFile = CC_fopen(destMadFilename, "w+b");
|
|
if(svgMadFile)
|
|
{
|
|
//sauvegarde du svgMadWorld
|
|
MAD_Save(svgMad, svgMadFile, MAD_SaveTextureFiles); //TO GET OPTIONAL
|
|
|
|
//fermeture du flux
|
|
CC_fclose(svgMadFile);
|
|
}
|
|
}
|
|
free2(svgMad);
|
|
|
|
//sauvegarde du document SVG généré
|
|
if(svgFileLoaded && TheScene->GetIniValue(CamcamCCM, "generateSVG"))
|
|
{
|
|
//création du chemin du fichier SVG de sortie
|
|
char* destSvgFilename = (char*)malloc2(strlen(svgFilename)+5);
|
|
strncpy(destSvgFilename, svgFilename, strlen(svgFilename)-4);
|
|
strcat(destSvgFilename, "_out.svg");
|
|
|
|
//écriture du node xml <svg> généré dans le fichier de sortie
|
|
doc.SaveFile(destSvgFilename);
|
|
|
|
//correction des problèmes d'écriture de la librairie xml
|
|
char tmpChar[50] = "xmlns=\"ns_svg;\" xmlns:xlink=\"ns_xlink;\"";
|
|
int pos = findText(destSvgFilename, 0, tmpChar);
|
|
if(pos!=-1)
|
|
{
|
|
deleteText(destSvgFilename, pos, pos+strlen(tmpChar));
|
|
insertText(destSvgFilename, pos, "xmlns=\"&ns_svg;\" xmlns:xlink=\"&ns_xlink;\"");
|
|
}
|
|
insertText(destSvgFilename, posHead, xmlHeader);
|
|
|
|
//libération des ressources utilisées
|
|
free2(destSvgFilename);
|
|
}
|
|
|
|
//libération des ressources utilisées
|
|
remove(tmpSvgFilename);
|
|
free2(xmlHeader);
|
|
|
|
//s'il y a eu un problème lors du chargement du document SVG, on renvoie FALSE
|
|
if(!svgFileLoaded) return false;
|
|
|
|
//on quitte l'application si on voulait juste convertir un fichier SVG
|
|
if(TheScene->GetIniValue(CamcamCCM, "svg2MadOnly")) exit(0);
|
|
|
|
//on renvoie TRUE si la conversion s'est passée sans encombre jusqu'au bout
|
|
return true;
|
|
}
|
|
|
|
void browseNode(TiXmlNode* node, MAD_World* svgMad, int parentHierIndex)
|
|
{
|
|
//mémorisation du pointeur vers le noeud SVG courant
|
|
cNode = node->ToElement();
|
|
|
|
//Affichage récursif des sous-balises
|
|
TiXmlNode* child = 0;
|
|
int hierIndex = svgMad->NumberOfHierarchieNodes;
|
|
if(strcmp(node->Value(), "svg") == 0) hierIndex = 0;
|
|
|
|
//traitement des balises "g"
|
|
if(strcmp(node->Value(), "g") == 0)
|
|
{
|
|
addObjectInMadWorld(svgMad, parentHierIndex, true);
|
|
}
|
|
|
|
//traitement des balises "image"
|
|
if(strcmp(node->Value(), "image") == 0)
|
|
{
|
|
numberOfSvgTextures++;
|
|
svgTextures = (SvgTexture*)realloc2(svgTextures, numberOfSvgTextures*sizeof(SvgTexture));
|
|
|
|
//récupération des données de l'image
|
|
svgTextures[numberOfSvgTextures-1].data = (char*)malloc2(1+strlen(node->ToElement()->Attribute("xlink:href")));
|
|
char* data = svgTextures[numberOfSvgTextures-1].data;
|
|
strcpy(data, node->ToElement()->Attribute("xlink:href"));
|
|
sprintf(svgTextures[numberOfSvgTextures-1].name, "imageTexture_%d", svgMad->NumberOfObjects-1);
|
|
int imageTypeStartPos = strstr(data, "/") + 1 - data;
|
|
int imageTypeEndPos = strstr(data, ";") - data;
|
|
if(strncmp(data+imageTypeStartPos, "png", imageTypeEndPos-imageTypeStartPos)==0)
|
|
svgTextures[numberOfSvgTextures-1].type = PNG_IMAGE;
|
|
else
|
|
svgTextures[numberOfSvgTextures-1].type = JPEG_IMAGE;
|
|
data = strstr(data, ",") + 1;
|
|
|
|
//récupération des coordonnées x, y et des proportions de l'image
|
|
float& x = svgTextures[numberOfSvgTextures-1].x;
|
|
float& y = svgTextures[numberOfSvgTextures-1].y;
|
|
float& w = svgTextures[numberOfSvgTextures-1].width;
|
|
float& h = svgTextures[numberOfSvgTextures-1].height;
|
|
if(node->ToElement()->Attribute("x")) x = (float)atof(node->ToElement()->Attribute("x")); else x = 0;
|
|
if(node->ToElement()->Attribute("y")) y = (float)atof(node->ToElement()->Attribute("y")); else y = 0;
|
|
w = atoi(node->ToElement()->Attribute("width"));
|
|
h = atoi(node->ToElement()->Attribute("height"));
|
|
if(node->ToElement()->Attribute("transform"))
|
|
{
|
|
char* transformation = (char*)malloc2(1000);
|
|
strcpy(transformation, node->ToElement()->Attribute("transform"));
|
|
if(strncmp("matrix(", transformation, strlen("matrix("))==0)
|
|
{
|
|
transformation = transformation + strlen("matrix(");
|
|
float a = 1.0; float b = 0.0; float c = 0.0; float d = 1.0; float e = 0.0; float f = 1.0;
|
|
sscanf(transformation, "%f %f %f %f %f %f", &a, &b, &c, &d, &e, &f);
|
|
float lx = x;
|
|
float ly = y;
|
|
float lw = w;
|
|
float lh = h;
|
|
x = a*lx+c*ly+e;
|
|
y = b*lx+d*ly+f;
|
|
w = a*(lw+lx)+c*(lh+ly)+e-x;
|
|
h = b*(lw+lx)+d*(lh+ly)+f-y;
|
|
}
|
|
}
|
|
|
|
//création des points de la forme
|
|
pointsList.clear();
|
|
svgNbPoints = 4;
|
|
//P0:
|
|
PointF P0(x, y+h); pointsList.push_back(P0);
|
|
//P1:
|
|
PointF P1(x, y); pointsList.push_back(P1);
|
|
//P2:
|
|
PointF P2(x+w, y); pointsList.push_back(P2);
|
|
//P3:
|
|
PointF P3(x+w, y+h); pointsList.push_back(P3);
|
|
|
|
//ajout de la forme au madWorld
|
|
addObjectInMadWorld(svgMad, parentHierIndex);
|
|
}
|
|
|
|
//traitement des balises "linearGradient"
|
|
if(strcmp(node->Value(), "linearGradient") == 0)
|
|
{
|
|
numberOfSvgTextures++;
|
|
svgTextures = (SvgTexture*)realloc2(svgTextures, numberOfSvgTextures*sizeof(SvgTexture));
|
|
|
|
strcpy(svgTextures[numberOfSvgTextures-1].name, node->ToElement()->Attribute("id"));
|
|
svgTextures[numberOfSvgTextures-1].type = LINEAR_GRADIENT;
|
|
|
|
float& x1 = svgTextures[numberOfSvgTextures-1].x1;
|
|
float& y1 = svgTextures[numberOfSvgTextures-1].y1;
|
|
float& x2 = svgTextures[numberOfSvgTextures-1].x2;
|
|
float& y2 = svgTextures[numberOfSvgTextures-1].y2;
|
|
|
|
if(node->ToElement()->Attribute("x1")) x1 = (float)atof(node->ToElement()->Attribute("x1")); else x1 = 0;
|
|
if(node->ToElement()->Attribute("y1")) y1 = (float)atof(node->ToElement()->Attribute("y1")); else y1 = 0;
|
|
if(node->ToElement()->Attribute("x2")) x2 = (float)atof(node->ToElement()->Attribute("x2")); else x2 = 0;
|
|
if(node->ToElement()->Attribute("y2")) y2 = (float)atof(node->ToElement()->Attribute("y2")); else y2 = 0;
|
|
|
|
if(node->ToElement()->Attribute("gradientTransform"))
|
|
{
|
|
char* transformation = (char*)malloc2(1000);
|
|
strcpy(transformation, node->ToElement()->Attribute("gradientTransform"));
|
|
if(strncmp("matrix(", transformation, strlen("matrix("))==0)
|
|
{
|
|
transformation = transformation + strlen("matrix(");
|
|
float a = 1.0; float b = 0.0; float c = 0.0; float d = 1.0; float e = 0.0; float f = 1.0;
|
|
sscanf(transformation, "%f %f %f %f %f %f", &a, &b, &c, &d, &e, &f);
|
|
float lx1 = x1;
|
|
float lx2 = x2;
|
|
float ly1 = y1;
|
|
float ly2 = y2;
|
|
x1 = a*lx1+c*ly1+e;
|
|
y1 = b*lx1+d*ly1+f;
|
|
x2 = a*lx2+c*ly2+e;
|
|
y2 = b*lx2+d*ly2+f;
|
|
}
|
|
}
|
|
|
|
TiXmlNode* stopChild = 0;
|
|
memset(svgTextures[numberOfSvgTextures-1].stopColors, 0, 2000);
|
|
int indOffset = 0;
|
|
while(stopChild = node->IterateChildren(stopChild))
|
|
{
|
|
if(strcmp(stopChild->Value(), "stop") == 0)
|
|
{
|
|
float offset = (float)(atof(stopChild->ToElement()->Attribute("offset")));
|
|
int color = (int)atoh(stopChild->ToElement()->Attribute("style")+strlen("stop-color:#"));
|
|
svgTextures[numberOfSvgTextures-1].stopColors[indOffset++] = (int)(OFFSET_PRECISION*offset);
|
|
svgTextures[numberOfSvgTextures-1].stopColors[indOffset++] = color;
|
|
}
|
|
}
|
|
}
|
|
|
|
//traitement des balises "radialGradient"
|
|
if(false && strcmp(node->Value(), "radialGradient") == 0)
|
|
{
|
|
numberOfSvgTextures++;
|
|
svgTextures = (SvgTexture*)realloc2(svgTextures, numberOfSvgTextures*sizeof(SvgTexture));
|
|
|
|
strcpy(svgTextures[numberOfSvgTextures-1].name, node->ToElement()->Attribute("id"));
|
|
svgTextures[numberOfSvgTextures-1].type = RADIAL_GRADIENT;
|
|
|
|
float& cx = svgTextures[numberOfSvgTextures-1].cx;
|
|
float& cy = svgTextures[numberOfSvgTextures-1].cy;
|
|
float& r = svgTextures[numberOfSvgTextures-1].r;
|
|
float& fx = svgTextures[numberOfSvgTextures-1].fx;
|
|
float& fy = svgTextures[numberOfSvgTextures-1].fy;
|
|
|
|
if(node->ToElement()->Attribute("cx")) cx = (float)atof(node->ToElement()->Attribute("cx")); else cx = 1e-30;
|
|
if(node->ToElement()->Attribute("cy")) cy = (float)atof(node->ToElement()->Attribute("cy")); else cy = 1e-30;
|
|
if(node->ToElement()->Attribute("r")) r = (float)atof(node->ToElement()->Attribute("r")); else r = 1e-30;
|
|
if(node->ToElement()->Attribute("fx")) fx = (float)atof(node->ToElement()->Attribute("fx")); else fx = 1e-30;
|
|
if(node->ToElement()->Attribute("fy")) fy = (float)atof(node->ToElement()->Attribute("fy")); else fy = 1e-30;
|
|
|
|
if(node->ToElement()->Attribute("gradientTransform"))
|
|
{
|
|
char* transformation = (char*)malloc2(1000);
|
|
strcpy(transformation, node->ToElement()->Attribute("gradientTransform"));
|
|
if(strncmp("matrix(", transformation, strlen("matrix("))==0)
|
|
{
|
|
transformation = transformation + strlen("matrix(");
|
|
float a = 1.0; float b = 0.0; float c = 0.0; float d = 1.0; float e = 0.0; float f = 1.0;
|
|
sscanf(transformation, "%f %f %f %f %f %f", &a, &b, &c, &d, &e, &f);
|
|
float lcx = cx;
|
|
float lcy = cy;
|
|
float lfx = fx;
|
|
float lfy = fy;
|
|
cx = a*lcx+c*lcy+e;
|
|
cy = b*lcx+d*lcy+f;
|
|
fx = a*lfx+c*lfy+e;
|
|
fy = b*lfx+d*lfy+f;
|
|
}
|
|
}
|
|
|
|
TiXmlNode* stopChild = 0;
|
|
memset(svgTextures[numberOfSvgTextures-1].stopColors, 0, 2000);
|
|
int indOffset = 0;
|
|
while(stopChild = node->IterateChildren(stopChild))
|
|
{
|
|
if(strcmp(stopChild->Value(), "stop") == 0)
|
|
{
|
|
float offset = (float)(atof(stopChild->ToElement()->Attribute("offset")));
|
|
int color = (int)atoh(stopChild->ToElement()->Attribute("style")+strlen("stop-color:#"));
|
|
svgTextures[numberOfSvgTextures-1].stopColors[indOffset++] = (int)(OFFSET_PRECISION*offset);
|
|
svgTextures[numberOfSvgTextures-1].stopColors[indOffset++] = color;
|
|
}
|
|
}
|
|
}
|
|
|
|
//traitement des balises "rect"
|
|
if(strcmp(node->Value(), "rect") == 0)
|
|
{
|
|
//madRect(node, svgMad);
|
|
}
|
|
|
|
//traitement des balises "path"
|
|
if(strcmp(node->Value(), "path") == 0)
|
|
{
|
|
if(svgFillType(cNode->Attribute("fill"))!=FILL_URL) numberOfSvgTextures++;
|
|
madPath(node, svgMad);
|
|
}
|
|
|
|
while(child = node->IterateChildren(child))
|
|
{
|
|
browseNode(child, svgMad, hierIndex);
|
|
}
|
|
}
|
|
|
|
SvgFillType svgFillType(const char* fillString)
|
|
{
|
|
if(!fillString || !fillString[0]) return FILL_EMPTY;
|
|
if(strcmp(fillString, "none")==0) return FILL_NONE;
|
|
if(atoh(fillString+1)) return FILL_COLOR;
|
|
return FILL_URL;
|
|
}
|
|
|
|
void cleanPointsList(std::vector<PointF>& pointsList)
|
|
{
|
|
PointF A, B, C;
|
|
//suppression des points successifs identiques
|
|
int i = 0;
|
|
while(i < pointsList.size() && pointsList.size()>=2)
|
|
{
|
|
A = pointsList.at(i); B = pointsList.at((i+1)%pointsList.size());
|
|
//si le point courant et son suivant sont colinéaires
|
|
if(A.x==B.x && A.y==B.y)
|
|
{
|
|
std::vector<PointF>::iterator it = pointsList.begin();
|
|
for(int j=0; j!=i; j++) it++;
|
|
pointsList.erase(it);
|
|
}
|
|
else i++;
|
|
}
|
|
//suppression des points successifs colinéaires
|
|
i = 0;
|
|
while(i < pointsList.size() && pointsList.size()>=3)
|
|
{
|
|
A = pointsList.at(i); B = pointsList.at((i+1)%pointsList.size()); C = pointsList.at((i+2)%pointsList.size());
|
|
//si le point courant et son suivant sont colinéaires
|
|
if((A.x-B.x)*(B.y-C.y) == (A.y-B.y)*(B.x-C.x))
|
|
{
|
|
std::vector<PointF>::iterator it = pointsList.begin();
|
|
for(int j=0; j!=(i+1)%pointsList.size(); j++) it++;
|
|
pointsList.erase(it);
|
|
}
|
|
else i++;
|
|
}
|
|
}
|
|
/*****************************************************************************************/
|
|
void closePath()
|
|
{
|
|
//remplissage du nouveau path
|
|
pathLen += 1;
|
|
pathOut += sprintf(pathOut, "z");
|
|
|
|
//remplissage de la liste de points
|
|
pointsList.push_back(SP);
|
|
}
|
|
|
|
void moveTo(float x, float y)
|
|
{
|
|
//remplissage du nouveau path
|
|
pathLen += 2 * COORD_DIGIT;
|
|
if(startOfPathOut) free2(startOfPathOut);
|
|
startOfPathOut = (char*)malloc2(pathLen);
|
|
pathOut = startOfPathOut + strlen(startOfPathOut);
|
|
pathOut += sprintf(pathOut, "M%.3f %.3f L ", x, y);
|
|
|
|
//remplissage de la liste de points
|
|
pointsList.push_back(PointF(x, y));
|
|
}
|
|
|
|
void lineTo(float x, float y)
|
|
{
|
|
//remplissage du nouveau path
|
|
pathLen += 2 * COORD_DIGIT;
|
|
if(startOfPathOut) free2(startOfPathOut);
|
|
startOfPathOut = (char*)malloc2(pathLen);
|
|
pathOut = startOfPathOut + strlen(startOfPathOut);
|
|
pathOut += sprintf(pathOut, "%.3f %.3f ", x, y);
|
|
|
|
//remplissage de la liste de points
|
|
pointsList.push_back(PointF(x, y));
|
|
}
|
|
|
|
void cubicTo(PointF c1, PointF c2, PointF e)
|
|
{
|
|
//initialisations
|
|
PointF A = CP; PointF B = c1; PointF C = c2; PointF D = e;
|
|
|
|
//calcul du nombre de segments nécessaire pour synthétiser la courbe
|
|
float curveLenSup = sqrt(((B-A).x)*((B-A).x)+((B-A).y)*((B-A).y))
|
|
+ sqrt(((C-B).x)*((C-B).x)+((C-B).y)*((C-B).y))
|
|
+ sqrt(((D-C).x)*((D-C).x)+((D-C).y)*((D-C).y));
|
|
float nbSeg = curveLenSup*nbSegPerLen + 1;
|
|
|
|
//remplissage du nouveau path
|
|
pathLen += (nbSeg * 2) * COORD_DIGIT;
|
|
if(startOfPathOut) free2(startOfPathOut);
|
|
startOfPathOut = (char*)malloc2(pathLen);
|
|
pathOut = startOfPathOut + strlen(startOfPathOut);
|
|
for(float i=1; i<nbSeg; i++)
|
|
{
|
|
float t = i/nbSeg;
|
|
PointF Ap = A + ((B-A)*t); PointF Bp = B + ((C-B)*t); PointF Cp = C + ((D-C)*t);
|
|
PointF As = Ap + ((Bp-Ap)*t); PointF Bs = Bp + ((Cp-Bp)*t);
|
|
PointF R = As + ((Bs-As)*t);
|
|
pathOut += sprintf(pathOut, "%.3f %.3f ", R.x, R.y);
|
|
//remplissage de la liste de points
|
|
pointsList.push_back(R);
|
|
}
|
|
pathOut += sprintf(pathOut, "%.3f %.3f ", e.x, e.y);
|
|
//remplissage de la liste de points
|
|
pointsList.push_back(e);
|
|
}
|
|
|
|
void quadTo(PointF c, PointF e)
|
|
{
|
|
|
|
}
|
|
|
|
void pathArc(float rx, float ry, float xAxisRotation, int largeArcFlag,
|
|
int sweepFlag, float ex, float ey, float curx, float cury)
|
|
{
|
|
|
|
}
|
|
/*****************************************************************************************/
|
|
float atoh(const char* Decode, bool findFloat)
|
|
{
|
|
const char * strOffset = Decode;
|
|
if(findFloat)
|
|
{
|
|
while(*strOffset && !IsHex(*strOffset))
|
|
{
|
|
strOffset++;
|
|
}
|
|
}
|
|
|
|
float RetValue = 0.0f;
|
|
bool findHex = false;
|
|
while(*strOffset && IsHex(*strOffset))
|
|
{
|
|
RetValue *= 16.0f;
|
|
RetValue += (float)(IsHex(*strOffset)-1);
|
|
strOffset++;
|
|
findHex = true;
|
|
}
|
|
if(RetValue==0 && findHex) RetValue = 1e-30;
|
|
|
|
return RetValue;
|
|
}
|
|
|
|
float atoh(const char* Decode)
|
|
{
|
|
return atoh(Decode, false);
|
|
}
|
|
|
|
float getFloat(char* &Decode)
|
|
{
|
|
float RetValue;
|
|
float Neg;
|
|
Neg = 1.0f;
|
|
RetValue = 0.0f;
|
|
bool findFloat = false;
|
|
if (*Decode == '-')
|
|
{
|
|
Neg = -1.0f;
|
|
Decode++;
|
|
findFloat = true;
|
|
}
|
|
if (*Decode == '+')
|
|
{
|
|
Decode++;
|
|
findFloat = true;
|
|
}
|
|
while ((*Decode >= '0') && (*Decode <= '9'))
|
|
{
|
|
RetValue *= 10.0f;
|
|
RetValue += (float)(*(Decode++) - '0');
|
|
findFloat = true;
|
|
}
|
|
if (*(Decode) == '.')
|
|
{
|
|
float Div = 0.1f;
|
|
Decode++;
|
|
findFloat = true;
|
|
while ((*Decode >= '0') && (*Decode <= '9'))
|
|
{
|
|
RetValue += (float)(*(Decode++) - '0') * Div;
|
|
Div /= 10.0f;
|
|
}
|
|
}
|
|
RetValue *= Neg;
|
|
if(RetValue==0 && findFloat)
|
|
RetValue = 1e-30;
|
|
|
|
return RetValue;
|
|
}
|
|
|
|
void removeAllShit(char* filename)
|
|
{
|
|
//allocation des buffers
|
|
long fileLen = lengthOfFile(filename);
|
|
char* buffer = (char*)malloc2(fileLen+1);
|
|
getText(filename, 0, fileLen, buffer);
|
|
char* result = (char*)malloc2(fileLen+1);
|
|
|
|
//copie dans le buffer résultat du buffer source sans les chaines à enlever
|
|
char* offset = buffer;
|
|
long start = 0;
|
|
long dest = 0;
|
|
while(*offset!=0)
|
|
{
|
|
if(strncmp("	", offset, 6)==0 || strncmp("
", offset, 6)==0 || strncmp("
", offset, 6)==0)
|
|
{
|
|
strncpy(result+dest, buffer+start, offset-buffer-start);
|
|
dest += offset-buffer-start;
|
|
start = offset-buffer+6;
|
|
}
|
|
offset++;
|
|
}
|
|
strncpy(result+dest, buffer+start, fileLen-start);
|
|
|
|
//copie du résultat nettoyé dans le fichier source
|
|
FILE* file = CC_fopen(filename,"wb");
|
|
fwrite(result, 1, strlen(result), file);
|
|
CC_fclose(file);
|
|
|
|
//libération de la mémoire
|
|
free2(result);
|
|
free2(buffer);
|
|
}
|
|
|
|
char* getCleanedString(char* string)
|
|
{
|
|
//création de la chaine de sortie
|
|
char* cleanedString = (char*)malloc2(1+strlen(string));
|
|
strcpy(cleanedString, string);
|
|
//suppression des sauts de lignes et des tabulations
|
|
for(int i=0; i<strlen(cleanedString); i++)
|
|
{
|
|
if(cleanedString[i]=='\t' || cleanedString[i]==10 || cleanedString[i]==13)
|
|
{
|
|
memmove(cleanedString + i, cleanedString + i + 1, strlen(cleanedString) - i);
|
|
i--;
|
|
}
|
|
}
|
|
//renvoi de la chaine nettoyée
|
|
return cleanedString;
|
|
}
|
|
|
|
//fonction permettant la suppression du contenu d'un répertoire sans le supprimer
|
|
void CleanDirectory(TCHAR * directoryPath, bool deleteFilesButNotDirectories)
|
|
{
|
|
TCHAR Path[MAX_PATH] ;
|
|
_tcscpy(Path, directoryPath) ;
|
|
_tcscat(Path, TEXT("\\*")) ;
|
|
TCHAR dossier[MAX_PATH] ;
|
|
_tcscpy(dossier, directoryPath) ;
|
|
_tcscat(dossier, TEXT("\\")) ;
|
|
WIN32_FIND_DATA wfd;
|
|
HANDLE hfl = FindFirstFile(Path, &wfd); // Recherche du premier fichier du répertoire
|
|
if(hfl != INVALID_HANDLE_VALUE)
|
|
{
|
|
if(strcmp(".", wfd.cFileName)!=0 && strcmp("..", wfd.cFileName)!=0)
|
|
{
|
|
_tcscat(dossier, wfd.cFileName) ;
|
|
if (wfd.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY && !deleteFilesButNotDirectories) // Si il s'agit d'un dossier
|
|
{
|
|
CleanDirectory(dossier, deleteFilesButNotDirectories) ; // Suppression récursive des dossiers
|
|
RemoveDirectory(dossier) ; // Suppression du dossier
|
|
}
|
|
else
|
|
{
|
|
DeleteFile(dossier); // Suppression du fichier
|
|
}
|
|
}
|
|
while(FindNextFile(hfl, &wfd)) // Tant qu'il y a de nouveaux fichiers
|
|
{
|
|
if(strcmp(".", wfd.cFileName)!=0 && strcmp("..", wfd.cFileName)!=0)
|
|
{
|
|
_tcscpy(dossier, directoryPath) ;
|
|
_tcscat(dossier, TEXT("\\")) ;
|
|
_tcscat(dossier, wfd.cFileName) ;
|
|
if (wfd.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY && !deleteFilesButNotDirectories) // Si il s'agit d'un dossier
|
|
{
|
|
CleanDirectory(dossier, deleteFilesButNotDirectories) ; // Suppression récursive des dossiers
|
|
RemoveDirectory(dossier) ; // Suppression du dossier
|
|
}
|
|
else
|
|
{
|
|
DeleteFile(dossier); // Suppression du fichier
|
|
}
|
|
}
|
|
}
|
|
FindClose(hfl); // Fermeture du dossier de recherche
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/********************************** Gestion de la mémoire **************************************/
|
|
|
|
void checkMemIntegrity(void* ptr, int Size)
|
|
{
|
|
if(ptr!=0)
|
|
{
|
|
if(strncmp((const char*)ptr, "abcd", 4))
|
|
assert(0);
|
|
if(strncmp((const char*)ptr+4+Size, "abcd", 4))
|
|
assert(0);
|
|
}
|
|
}
|
|
|
|
void* malloc2(u32 Size)
|
|
{
|
|
//vérification de l'intégrité des allocations
|
|
for(int i=0; i<nbAlloc; i++)
|
|
checkMemIntegrity(allocStack[i], allocSizes[i]);
|
|
|
|
//allocation de la nouvelle zone mémoire
|
|
char* ptr = (char*)CC_malloc(Size+8);
|
|
memset(ptr, 0, Size+8);
|
|
//ajout des marqueurs à la zone
|
|
ptr[0] = 'a'; ptr[1] = 'b'; ptr[2] = 'c'; ptr[3] = 'd';
|
|
ptr[Size+4+0] = 'a'; ptr[Size+4+1] = 'b'; ptr[Size+4+2] = 'c'; ptr[Size+4+3] = 'd';
|
|
//mise à jour de la liste des allocations
|
|
nbAlloc++;
|
|
allocSizes = (unsigned int*)CC_realloc(allocSizes, nbAlloc*sizeof(unsigned int));
|
|
allocSizes[nbAlloc-1] = Size;
|
|
allocStack = (void**)CC_realloc(allocStack, nbAlloc*sizeof(void*));
|
|
allocStack[nbAlloc-1] = ptr;
|
|
|
|
//vérification de l'intégrité des allocations
|
|
for(int i=0; i<nbAlloc; i++)
|
|
checkMemIntegrity(allocStack[i], allocSizes[i]);
|
|
|
|
//renvoie du pointeur vers la nouvelle zone mémoire
|
|
return ptr+4;
|
|
}
|
|
|
|
void* realloc2(void* ptr, u32 Size)
|
|
{
|
|
//vérification de l'intégrité des allocations
|
|
for(int i=0; i<nbAlloc; i++)
|
|
checkMemIntegrity(allocStack[i], allocSizes[i]);
|
|
|
|
//si le pointeur vers la zone mémoire à réallouer est nul, on quitte de la fonction
|
|
if(ptr==0)
|
|
return 0;
|
|
|
|
//sinon, création du pointeur vers la nouvelle zone mémoire
|
|
char* newPtr = 0;
|
|
|
|
//allocation de la nouvelle zone mémoire
|
|
newPtr = (char*)CC_malloc(Size+8);
|
|
memset(newPtr, 0, Size+8);
|
|
|
|
//récupération dans la pile d'allocation de la position du pointeur vers la zone mémoire à réallouer
|
|
int indexInStack = -1;
|
|
for(int i=0; i<nbAlloc; i++)
|
|
{
|
|
if((char*)allocStack[i]+4==(char*)ptr)
|
|
{
|
|
indexInStack = i;
|
|
i = nbAlloc;
|
|
}
|
|
}
|
|
//si la zone mémoire à réallouer n'avait pas été allouée par la fonction malloc2(), on quitte la fonction
|
|
if(indexInStack==-1)
|
|
return 0;
|
|
|
|
//sinon, copie des données utiles de l'ancienne zone mémoire vers la nouvelle
|
|
u32 oldSize = allocSizes[indexInStack];
|
|
memcpy(newPtr+4, ptr, oldSize);
|
|
|
|
//ajout des marqueurs à la zone
|
|
newPtr[0] = 'a'; newPtr[1] = 'b'; newPtr[2] = 'c'; newPtr[3] = 'd';
|
|
newPtr[Size+4+0] = 'a'; newPtr[Size+4+1] = 'b'; newPtr[Size+4+2] = 'c'; newPtr[Size+4+3] = 'd';
|
|
|
|
//mise à jour de la liste des allocations
|
|
allocSizes[indexInStack] = Size;
|
|
allocStack[indexInStack] = newPtr;
|
|
|
|
//vérification de l'intégrité des allocations
|
|
for(int i=0; i<nbAlloc; i++)
|
|
checkMemIntegrity(allocStack[i], allocSizes[i]);
|
|
|
|
//renvoie du nouveau pointeur
|
|
return newPtr+4;
|
|
}
|
|
|
|
void free2(void* ptr)
|
|
{
|
|
//vérification de l'intégrité des allocations
|
|
for(int i=0; i<nbAlloc; i++)
|
|
checkMemIntegrity(allocStack[i], allocSizes[i]);
|
|
|
|
if(ptr==0)
|
|
return;
|
|
|
|
//récupération dans la pile d'allocation de la position du pointeur vers la zone mémoire à libérer
|
|
int indexInStack = -1;
|
|
for(int i=0; i<nbAlloc; i++)
|
|
{
|
|
if((char*)allocStack[i]+4==(char*)ptr)
|
|
{
|
|
indexInStack = i;
|
|
i = nbAlloc;
|
|
}
|
|
}
|
|
//si la zone mémoire à libérer n'avait pas été allouée par la fonction malloc2() ou realloc2(), on quitte la fonction
|
|
if(indexInStack==-1)
|
|
return;
|
|
|
|
//suppression de la zone mémoire
|
|
free2(allocStack[indexInStack]);
|
|
for(int i=indexInStack; i<nbAlloc-1; i++)
|
|
{
|
|
allocStack[i] = allocStack[i+1];
|
|
allocSizes[i] = allocSizes[i+1];
|
|
}
|
|
nbAlloc--;
|
|
allocStack[nbAlloc] = 0;
|
|
allocSizes[nbAlloc] = 0;
|
|
|
|
//vérification de l'intégrité des allocations
|
|
for(int i=0; i<nbAlloc; i++)
|
|
checkMemIntegrity(allocStack[i], allocSizes[i]);
|
|
}
|
|
|
|
|
|
/* liste des balises SVG */
|
|
/*
|
|
s_utilFactory.insert(QLatin1String("a"), (ParseMethod) parseAnchorNode);
|
|
s_utilFactory.insert(QLatin1String("animate"), (ParseMethod) parseAnimateNode);
|
|
s_utilFactory.insert(QLatin1String("animateColor"), (ParseMethod) parseAnimateColorNode);
|
|
s_utilFactory.insert(QLatin1String("animateMotion"), (ParseMethod) parseAimateMotionNode);
|
|
s_utilFactory.insert(QLatin1String("animateTransform"), (ParseMethod) parseAnimateTransformNode);
|
|
s_utilFactory.insert(QLatin1String("audio"), (ParseMethod) parseAudioNode);
|
|
s_utilFactory.insert(QLatin1String("desc"), (ParseMethod) parseDescNode);
|
|
s_utilFactory.insert(QLatin1String("discard"), (ParseMethod) parseDiscardNode);
|
|
s_utilFactory.insert(QLatin1String("foreignObject"), (ParseMethod) parseForeignObjectNode);
|
|
s_utilFactory.insert(QLatin1String("handler"), (ParseMethod) parseHandlerNode);
|
|
s_utilFactory.insert(QLatin1String("hkern"), (ParseMethod) parseHkernNode);
|
|
s_utilFactory.insert(QLatin1String("metadata"), (ParseMethod) parseMetadataNode);
|
|
s_utilFactory.insert(QLatin1String("mpath"), (ParseMethod) parseMpathNode);
|
|
s_utilFactory.insert(QLatin1String("prefetch"), (ParseMethod) parsePrefetchNode);
|
|
s_utilFactory.insert(QLatin1String("script"), (ParseMethod) parseScriptNode);
|
|
s_utilFactory.insert(QLatin1String("set"), (ParseMethod) parseSetNode);
|
|
s_utilFactory.insert(QLatin1String("style"), (ParseMethod) parseStyleNode);
|
|
s_utilFactory.insert(QLatin1String("tBreak"), (ParseMethod) parseTbreakNode);
|
|
s_utilFactory.insert(QLatin1String("title"), (ParseMethod) parseTitleNode);
|
|
s_utilFactory.insert(QLatin1String("tspan"), (ParseMethod) parseTspanNode);
|
|
|
|
s_groupFactory.insert(QLatin1String("svg"), (FactoryMethod) createSvgNode);
|
|
s_groupFactory.insert(QLatin1String("g"), (FactoryMethod) createGNode);
|
|
s_groupFactory.insert(QLatin1String("defs"), (FactoryMethod) createDefsNode);
|
|
s_groupFactory.insert(QLatin1String("switch"), (FactoryMethod) createSwitchNode);
|
|
|
|
s_graphicsFactory.insert(QLatin1String("animation"), (FactoryMethod) createAnimationNode);
|
|
s_graphicsFactory.insert(QLatin1String("circle"), (FactoryMethod) createCircleNode);
|
|
s_graphicsFactory.insert(QLatin1String("ellipse"), (FactoryMethod) createEllipseNode);
|
|
s_graphicsFactory.insert(QLatin1String("image"), (FactoryMethod) createImageNode);
|
|
s_graphicsFactory.insert(QLatin1String("line"), (FactoryMethod) createLineNode);
|
|
s_graphicsFactory.insert(QLatin1String("path"), (FactoryMethod) createPathNode);
|
|
s_graphicsFactory.insert(QLatin1String("polygon"), (FactoryMethod) createPolygonNode);
|
|
s_graphicsFactory.insert(QLatin1String("polyline"), (FactoryMethod) createPolylineNode);
|
|
s_graphicsFactory.insert(QLatin1String("rect"), (FactoryMethod) createRectNode);
|
|
s_graphicsFactory.insert(QLatin1String("text"), (FactoryMethod) createTextNode);
|
|
s_graphicsFactory.insert(QLatin1String("textArea"), (FactoryMethod) createTextAreaNode);
|
|
s_graphicsFactory.insert(QLatin1String("use"), (FactoryMethod) createUseNode);
|
|
s_graphicsFactory.insert(QLatin1String("video"), (FactoryMethod) createVideoNode);
|
|
|
|
s_styleFactory.insert(QLatin1String("linearGradient"), (StyleFactoryMethod) createLinearGradientNode);
|
|
s_styleFactory.insert(QLatin1String("radialGradient"), (StyleFactoryMethod) createRadialGradientNode);
|
|
s_styleFactory.insert(QLatin1String("font"), (StyleFactoryMethod) createFontNode);
|
|
s_styleFactory.insert(QLatin1String("solidColor"), (StyleFactoryMethod) createSolidColorNode);
|
|
|
|
s_styleUtilFactory.insert(QLatin1String("font-face"), (StyleParseMethod) parseFontFaceNode);
|
|
s_styleUtilFactory.insert(QLatin1String("font-face-name"), (StyleParseMethod) parseFontFaceNameNode);
|
|
s_styleUtilFactory.insert(QLatin1String("font-face-src"), (StyleParseMethod) parseFontFaceSrcNode);
|
|
s_styleUtilFactory.insert(QLatin1String("font-face-uri"), (StyleParseMethod) parseFontFaceUriNode);
|
|
s_styleUtilFactory.insert(QLatin1String("glyph"), (StyleParseMethod) parseGlyphNode);
|
|
s_styleUtilFactory.insert(QLatin1String("missing-glyph"), (StyleParseMethod) parseMissingGlyphNode);
|
|
s_styleUtilFactory.insert(QLatin1String("stop"), (StyleParseMethod) parseStopNode);
|
|
*/
|
|
#endif //USE_SVG
|