]> Shamusworld >> Repos - architektonas/blobdiff - src/fileio.cpp
Added base units & display style to drawing.
[architektonas] / src / fileio.cpp
index 7f1a90a8d08b7e7c634545c0fb78b34dbc1b94c8..3ce447040014fe9ea7e53bb5d4be90bda16f0521 100644 (file)
@@ -19,6 +19,9 @@
 #include <stdlib.h>
 #include <string.h>
 #include <vector>
+#include "applicationwindow.h"
+#include "drawingview.h"
+#include "global.h"
 #include "structs.h"
 
 /*
@@ -58,7 +61,7 @@ Connect() function. Or, instead of a point, a parameter value?
 
 Doing that, with the Line and a parameter "t", if t == 0 we have endpoint 1.
 if t == 1, then we have endpoint 2. With a Circle, the parameter is a number
-between 0 and 1 (scaled to 0 to ). With an Arc, the parameter goes from 0 to
+between 0 and 1 (scaled to 0 to tau). With an Arc, the parameter goes from 0 to
 1, 0 being enpoint 1 and 1 being endpoint 2.
 
 How does this work for moving objects that are connected? Again, with the Line
@@ -105,18 +108,13 @@ OTHER CONSIDERATIONS:
   - Need to figure out how to store the Layer list (should layer list be optional?)
   - Need to figure out how to store the Block list and blocks
 
-
 */
 
-//enum ObjectTypeFile { OTFContainer, OTFContainerEnd, OTFLine, OTFCircle, OTFArc,
-//     OTFDimension, OTFPolygon, OTFText, OTFImage, OTFBlock, OTFEndOfFile };
 enum ObjectTypeFile { OTFContainer, OTFContainerEnd, OTFObject, OTFEndOfFile };
 
-
 // Instantiate class variables
 /*static*/ int FileIO::objectFileType = OTFObject;
 
-
 /*static*/ bool FileIO::SaveAtnsFile(FILE * file, Container * c)
 {
        /* Approach: loop through the container, doing a depth-first traversal. Any
@@ -125,28 +123,54 @@ enum ObjectTypeFile { OTFContainer, OTFContainerEnd, OTFObject, OTFEndOfFile };
           virtual Object function that reports the object by itself if it's a non-
           Container, otherwise it enumerates all objects within itself. */
 
-       fprintf(file, "ARCHITEKTONAS DRAWING V1.1\n");
+       fprintf(file, "ARCHITEKTONAS DRAWING V1.2\n");
+       fprintf(file, "PROPERTIES 4\n");
+       fprintf(file, "BASE_UNIT %i\n", c->baseUnit);
+       fprintf(file, "UNIT_STYLE %i\n", c->unitStyle);
+       fprintf(file, "DEC_PREC %i\n", c->decimalPrecision);
+       fprintf(file, "FRAC_PREC %i\n", c->fractionalPrecision);
+
+       fprintf(file, "LAYERS %i\n", Global::numLayers);
+
+       for(int i=0; i<Global::numLayers; i++)
+               fprintf(file, "%i %i \"%s\"\n", (Global::layerHidden[i] ? 1 : 0), (Global::layerLocked[i] ? 1 : 0), Global::layerName[i].c_str());
+
+       fprintf(file, "ACTIVE %i\n", Global::activeLayer);
        WriteObjectToFile(file, (Object *)c);
        fprintf(file, "END\n");
        return true;
 }
 
-
 /*static*/ bool FileIO::LoadAtnsFile(FILE * file, Container * drawing)
 {
        float version;
 
-       fscanf(file, "ARCHITEKTONAS DRAWING V%f", &version);
+       fscanf(file, "ARCHITEKTONAS DRAWING V%f\n", &version);
+
+       // Clear out layer vectors
+       Global::layerHidden.clear();
+       Global::layerLocked.clear();
+       Global::layerName.clear();
 
        if (version == 1.0f)
                return LoadVersion1_0(file, drawing);
        else if (version == 1.1f)
                return LoadVersion1_1(file, drawing);
+       else if (version == 1.2f)
+               return LoadVersion1_2(file, drawing);
 
-//printf("LoadAtnsFile: Could not locate version! (version=%f)\n", version);
        return false;
 }
 
+/*static*/ void FileIO::ResetLayerVectors(void)
+{
+       // Set up layer vectors
+       Global::layerHidden.insert(Global::layerHidden.begin(), false);
+       Global::layerLocked.insert(Global::layerLocked.begin(), false);
+       Global::layerName.insert(Global::layerName.begin(), "Background");
+       Global::numLayers = 1;
+       Global::activeLayer = 0;
+}
 
 /*static*/ bool FileIO::LoadVersion1_0(FILE * file, Container * drawing)
 {
@@ -155,6 +179,7 @@ enum ObjectTypeFile { OTFContainer, OTFContainerEnd, OTFObject, OTFEndOfFile };
        // This will require a stack to maintain the current Container.
        std::vector<Container *> containerStack;
        Container * currentTopContainer = drawing;
+       ResetLayerVectors();
 
        while (!feof(file))
        {
@@ -194,7 +219,6 @@ enum ObjectTypeFile { OTFContainer, OTFContainerEnd, OTFObject, OTFEndOfFile };
        return false;
 }
 
-
 /*static*/ bool FileIO::LoadVersion1_1(FILE * file, Container * drawing)
 {
        // Approach: read each object in the file, one by one. If the object is a
@@ -202,6 +226,7 @@ enum ObjectTypeFile { OTFContainer, OTFContainerEnd, OTFObject, OTFEndOfFile };
        // This will require a stack to maintain the current Container.
        std::vector<Container *> containerStack;
        Container * currentTopContainer = drawing;
+       ResetLayerVectors();
 
        while (!feof(file))
        {
@@ -227,6 +252,12 @@ enum ObjectTypeFile { OTFContainer, OTFContainerEnd, OTFObject, OTFEndOfFile };
                }
                else if (objectFileType == OTFContainerEnd)
                {
+                       // Add the extents of the current container
+                       Rect r = ApplicationWindow::drawing->GetObjectExtents((Object *)currentTopContainer);
+                       currentTopContainer->p[0] = r.TopLeft();
+                       currentTopContainer->p[1] = r.BottomRight();
+//printf("Container extents: <%lf, %lf>, <%lf, %lf>\n", r.l, r.t, r.r, r.b);
+
                        // Container is done, so pop the stack to get back the previous TLC
                        currentTopContainer = containerStack.back();
                        containerStack.pop_back();
@@ -241,10 +272,89 @@ enum ObjectTypeFile { OTFContainer, OTFContainerEnd, OTFObject, OTFEndOfFile };
        return false;
 }
 
+/*static*/ bool FileIO::LoadVersion1_2(FILE * file, Container * drawing)
+{
+       int hidden, locked, props = 0;
+       char textBuffer[65536];
+
+       // Load drawing properties, if any, first
+       fscanf(file, "PROPERTIES %i\n", &props);
+
+       if (props == 4)
+       {
+               fscanf(file, "BASE_UNIT %i\n", &(drawing->baseUnit));
+               fscanf(file, "UNIT_STYLE %i\n", &(drawing->unitStyle));
+               fscanf(file, "DEC_PREC %i\n", &(drawing->decimalPrecision));
+               fscanf(file, "FRAC_PREC %i\n", &(drawing->fractionalPrecision));
+       }
+
+       // Load layer information next
+       fscanf(file, "LAYERS %i\n", &Global::numLayers);
+
+       for(int i=0; i<Global::numLayers; i++)
+       {
+               fscanf(file, "%i %i \"%[^\"]\"\n", &hidden, &locked, textBuffer);
+               Global::layerHidden.push_back(hidden ? true : false);
+               Global::layerLocked.push_back(locked ? true : false);
+               Global::layerName.push_back(textBuffer);
+       }
+
+       fscanf(file, "ACTIVE %i\n", &Global::activeLayer);
+
+       // Approach: read each object in the file, one by one. If the object is a
+       // Container, add objects to it until an "endContainer" marker is found.
+       // This will require a stack to maintain the current Container.
+       std::vector<Container *> containerStack;
+       Container * currentTopContainer = drawing;
+
+       while (!feof(file))
+       {
+               // Reconstruct the object (extended format!)
+               Object * obj = GetObjectFromFile(file, true, true);
+
+               // objectFileType is set in GetObjectFromFile()...
+               if (objectFileType == OTFObject)
+               {
+                       if (obj == NULL)
+                               return false;
+
+                       currentTopContainer->objects.push_back(obj);
+//printf("Load: Adding object. Container size = %li (%li)\n", drawing->objects.size(), currentTopContainer->objects.size());
 
-/*static*/ Object * FileIO::GetObjectFromFile(FILE * file, bool extended/*= false*/)
+                       // If the object is a container, push current TLC on the stack and
+                       // set it as the new TLC
+                       if (obj->type == OTContainer)
+                       {
+                               containerStack.push_back(currentTopContainer);
+                               currentTopContainer = (Container *)obj;
+                       }
+               }
+               else if (objectFileType == OTFContainerEnd)
+               {
+                       // Add the extents of the current container
+                       Rect r = ApplicationWindow::drawing->GetObjectExtents((Object *)currentTopContainer);
+                       currentTopContainer->p[0] = r.TopLeft();
+                       currentTopContainer->p[1] = r.BottomRight();
+//printf("Container extents: <%lf, %lf>, <%lf, %lf>\n", r.l, r.t, r.r, r.b);
+
+                       // Container is done, so pop the stack to get back the previous TLC
+                       currentTopContainer = containerStack.back();
+                       containerStack.pop_back();
+               }
+               else if (objectFileType == OTFEndOfFile)
+               {
+//printf("Load: container size = %li\n", drawing->objects.size());
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+/*static*/ Object * FileIO::GetObjectFromFile(FILE * file, bool extended/*= false*/, bool ext2/*= false*/)
 {
        char buffer[256];
+       char textBuffer[65536];
        int foundLayer = 0;
        /*int num =*/ fscanf(file, "%s", buffer);
        Object * obj = NULL;
@@ -279,6 +389,7 @@ if (errno)
 }
 
        // Need to add pen attributes as well... do that for v1.1 :-P
+       // And fill attributes... do that for v1.3 (1.2 added layers)
        if (strcmp(buffer, "LINE") == 0)
        {
                Point p1, p2;
@@ -299,12 +410,23 @@ if (errno)
                fscanf(file, "(%lf,%lf) %lf, %lf, %lf", &p.x, &p.y, &r, &a1, &a2);
                obj = (Object *)new Arc(p, r, a1, a2);
        }
+       else if (strcmp(buffer, "TEXT") == 0)
+       {
+               Point p;
+               fscanf(file, "(%lf,%lf) \"%[^\"]\"", &p.x, &p.y, textBuffer);
+               obj = (Object *)new Text(p, textBuffer);
+       }
        else if (strcmp(buffer, "DIMENSION") == 0)
        {
                Point p1, p2;
                DimensionType type;
+               double offset = 0;
                fscanf(file, "(%lf,%lf) (%lf,%lf) %i", &p1.x, &p1.y, &p2.x, &p2.y, (int *)&type);
-               obj = (Object *)new Dimension(p1, p2, type);
+
+               if (ext2)
+                       fscanf(file, " %lf", &offset);
+
+               obj = (Object *)new Dimension(p1, p2, type, offset);
        }
        else if (strcmp(buffer, "CONTAINER") == 0)
        {
@@ -319,6 +441,8 @@ if (errno)
        {
                objectFileType = OTFEndOfFile;
        }
+       else
+               printf("Unknown object type '%s'...\n", buffer);
 
        if (obj != NULL)
        {
@@ -326,14 +450,13 @@ if (errno)
 
                if (extended && (obj->type != OTContainer))
                {
-                       fscanf(file, " (%i, %f, %i)", &obj->color, &obj->thickness, &obj->style);
+                       fscanf(file, " (%i, %f, %i)\n", &obj->color, &obj->thickness, &obj->style);
                }
        }
 
        return obj;
 }
 
-
 /*static*/ bool FileIO::WriteObjectToFile(FILE * file, Object * obj)
 {
        // Sanity check
@@ -356,8 +479,7 @@ if (errno)
        case OTPolygon:
                break;
        case OTDimension:
-//             fprintf(file, "DIMENSION %i (%lf,%lf) (%lf,%lf) %i\n", layer, position.x, position.y, endpoint.x, endpoint.y, dimensionType);
-               fprintf(file, "DIMENSION %i (%lf,%lf) (%lf,%lf) %i", obj->layer, obj->p[0].x, obj->p[0].y, obj->p[1].x, obj->p[1].y, ((Dimension *)obj)->subtype);
+               fprintf(file, "DIMENSION %i (%lf,%lf) (%lf,%lf) %i %lf", obj->layer, obj->p[0].x, obj->p[0].y, obj->p[1].x, obj->p[1].y, ((Dimension *)obj)->subtype, ((Dimension *)obj)->offset);
                break;
        case OTSpline:
                break;
@@ -390,4 +512,3 @@ if (errno)
 
        return true;
 }
-