#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& 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 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 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; hNumberOfHierarchieNodes; 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; hNumberOfHierarchieNodes; h++) { int o = svgMad->Hierarchie[h].Object; if(o != MAD_NULL_INDEX) { o--; for(int n=0; nNumberOfPoints; 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; hNumberOfHierarchieNodes; 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; hNumberOfHierarchieNodes; 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; hNumberOfHierarchieNodes; 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 innerPointsList; std::vector 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 strokePointsList; //strokePointsList.push_back(i0); for(int i=0; iSetAttribute("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; nNumberOfPoints; 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; nNumberOfPoints; 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=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 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, "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 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& 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::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::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= '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