int readMax(EmbPattern* pattern, const char* fileName)
{
    int i;
    unsigned char b[8];
    double dx = 0, dy = 0;
    int flags = 0;
    int stitchCount;
    FILE* file;

    file = fopen(fileName, "rb");
    if(file == 0)
    {
        return 0;
    }
    fseek(file, 0xD5, SEEK_SET);
    stitchCount = binaryReadUInt32(file);

    /* READ STITCH RECORDS */
    for(i = 0; i < stitchCount; i++)
    {
        flags = NORMAL;
        if(fread(b, 1, 8, file) != 8)
            break;

        dx = maxDecode(b[0], b[1], b[2]);
        dy = maxDecode(b[4], b[5], b[6]);
        embPattern_addStitchAbs(pattern, dx / 10.0, dy / 10.0, flags, 1);
    }
    embPattern_addStitchRel(pattern, 0, 0, END, 1);
	embPattern_flipVertical(pattern);
    fclose(file);
    return 1;
}
Beispiel #2
0
/* TODO: It doesn't appear that this function actually clears the polylineObjList so it is more of a copy than a move. */
void movePolylinesToStitchList(EmbPattern* p)
{
    if(p)
    {
        EmbPolylineObjectList* polyList = p->polylineObjList;
        EmbStitchList* currentList = 0;
        int firstObject = 1;
        /*int currentColor = polyList->polylineObj->color TODO: polyline color */
        while(polyList)
        {
            EmbPolylineObject* currentPoly = polyList->polylineObj;
            EmbPointList* currentPointList = currentPoly->pointList;
            EmbThread thread;
            thread.catalogNumber = 0;
            thread.color = currentPoly->color;
            thread.description = 0;
            embPattern_addThread(p, thread);
            if(!firstObject)
            {
                embPattern_addStitchRel(p, currentPointList->point.xx, currentPointList->point.yy, TRIM, 1);
                embPattern_addStitchRel(p, 0.0, 0.0, STOP, 1);
                firstObject = 0;
            }
            while(currentPointList)
            {
                embPattern_addStitchAbs(p, currentPointList->point.xx, currentPointList->point.yy, NORMAL, 1);
                currentPointList = currentPointList->next;
            }

            polyList = polyList->next;
        }
        embPattern_addStitchRel(p, 0.0, 0.0, END, 1);
    }
}
Beispiel #3
0
void embPattern_copyPolylinesToStitchList(EmbPattern* p)
{
    EmbPolylineObjectList* polyList = 0;
    EmbStitchList* currentList = 0;
    int firstObject = 1;
    /*int currentColor = polyList->polylineObj->color TODO: polyline color */

    if(!p) { embLog_error("emb-pattern.c embPattern_copyPolylinesToStitchList(), p argument is null\n"); return; }
    polyList = p->polylineObjList;
    while(polyList)
    {
        EmbPolylineObject* currentPoly = polyList->polylineObj;
        EmbPointList* currentPointList = currentPoly->pointList;
        EmbThread thread;
        thread.catalogNumber = 0;
        thread.color = currentPoly->color;
        thread.description = 0;
        embPattern_addThread(p, thread);
        if(!firstObject)
        {
            embPattern_addStitchRel(p, currentPointList->point.xx, currentPointList->point.yy, TRIM, 1);
            embPattern_addStitchRel(p, 0.0, 0.0, STOP, 1);
            firstObject = 0;
        }
        while(currentPointList)
        {
            embPattern_addStitchAbs(p, currentPointList->point.xx, currentPointList->point.yy, NORMAL, 1);
            currentPointList = currentPointList->next;
        }

        polyList = polyList->next;
    }
    embPattern_addStitchRel(p, 0.0, 0.0, END, 1);
}
int readPcm(EmbPattern* pattern, const char* fileName)
{
    int i;
    unsigned char b[9];
    double dx = 0, dy = 0;
    int flags = 0, st = 0;
    FILE* file = fopen(fileName, "rb");

    if(file == 0)
    {
        return 0;
    }

    fseek(file, 4, SEEK_SET);

    for(i = 0; i < 16; i++)
    {
        char zero = fgetc(file);
        int colorNumber = fgetc(file);
        embPattern_addThread(pattern, pcmThreads[colorNumber]);
    }
    st = binaryReadUInt16BE(file);
    /* READ STITCH RECORDS */
    for(i = 0; i < st; i++)
    {
        flags = NORMAL;
        if(fread(b, 1, 9, file) != 9)
            break;

        if(b[8] & 0x01)
        {
            flags = STOP;
        }
        else if(b[8] & 0x04)
        {
            flags = TRIM;
        }
        else if(b[8] != 0)
        {
            /* TODO: ONLY INTERESTED IN THIS CASE TO LEARN MORE ABOUT THE FORMAT */
        }
        dx = pcmDecode(b[2], b[1], b[0]);
        dy = pcmDecode(b[6], b[5], b[4]);
        embPattern_addStitchAbs(pattern, dx / 10.0, dy / 10.0, flags, 1);
    }
    embPattern_addStitchRel(pattern, 0, 0, END, 1);
    fclose(file);
    return 1;
}
Beispiel #5
0
static void ofmReadExpanded(EmbFile* file, EmbPattern* p)
{
    int i, numberOfStitches = 0;

    if(!file) { embLog_error("format-ofm.c ofmReadExpanded(), file argument is null\n"); return; }
    if(!p) { embLog_error("format-ofm.c ofmReadExpanded(), p argument is null\n"); return; }

    ofmReadBlockHeader(file);
    numberOfStitches = binaryReadInt32(file);

    for(i = 0; i < numberOfStitches; i++)
    {
        unsigned char stitch[5];
        binaryReadBytes(file, stitch, 5); /* TODO: check return value */
        if(stitch[0] == 0)
        {
            embPattern_addStitchAbs(p, ofmDecode(stitch[1], stitch[2]) / 10.0, ofmDecode(stitch[3], stitch[4]) / 10.0, i == 0 ? JUMP : EM_NORMAL, 1);
        }
        else if(stitch[0] == 32)
        {
            embPattern_addStitchAbs(p, ofmDecode(stitch[1], stitch[2]) / 10.0, ofmDecode(stitch[3], stitch[4]) / 10.0, i == 0 ? TRIM : EM_NORMAL, 1);
        }
    }
}
Beispiel #6
0
static void ofmReadExpanded(FILE* file, EmbPattern* p)
{
    int i, numberOfStitches = 0;

    ofmReadBlockHeader(file);
    numberOfStitches = binaryReadInt32(file);

    for(i = 0; i < numberOfStitches; i++)
    {
        unsigned char stitch[5];
        binaryReadBytes(file, stitch, 5);
        if(stitch[0] == 0)
        {
            embPattern_addStitchAbs(p, ofmDecode(stitch[1], stitch[2]) / 10.0, ofmDecode(stitch[3], stitch[4]) / 10.0, i == 0 ? JUMP : NORMAL, 1);
        }
    }
}
Beispiel #7
0
/* Adds a stitch at the relative position (dx,dy) to the previous stitch. Positive y is up. Units are in millimeters. */
void embPattern_addStitchRel(EmbPattern* p, double dx, double dy, int flags, int isAutoColorIndex)
{
    /* TODO: pointer safety */
    double x,y;
    if(!embStitchList_empty(p->stitchList))
    {
        x = p->lastX + dx;
        y = p->lastY + dy;
    }
    else
    {
        /* the list is empty so assume starting location is 0,0 */
        x = dx;
        y = dy;
    }
    embPattern_addStitchAbs(p, x, y, flags, isAutoColorIndex);
}
Beispiel #8
0
/* Adds a stitch at the relative position (dx,dy) to the previous stitch. Positive y is up. Units are in millimeters. */
void embPattern_addStitchRel(EmbPattern* p, double dx, double dy, int flags, int isAutoColorIndex)
{
    double x,y;

    if(!p) { embLog_error("emb-pattern.c embPattern_addStitchRel(), p argument is null\n"); return; }
    if(!embStitchList_empty(p->stitchList))
    {
        x = p->lastX + dx;
        y = p->lastY + dy;
    }
    else
    {
        /* the list is empty so assume starting location is 0,0 */
        x = dx;
        y = dy;
    }
    embPattern_addStitchAbs(p, x, y, flags, isAutoColorIndex);
}
Beispiel #9
0
/*! Adds a stitch to the pattern (\a p) at the relative position (\a dx,\a dy) to the previous stitch. Positive y is up. Units are in millimeters. */
void embPattern_addStitchRel(EmbPattern* p, double dx, double dy, int flags, int isAutoColorIndex)
{
    double x,y;

    if(!p) { embLog_error("emb-pattern.c embPattern_addStitchRel(), p argument is null\n"); return; }
    if(!embStitchList_empty(p->stitchList))
    {
        x = p->lastX + dx;
        y = p->lastY + dy;
    }
    else
    {
        /* NOTE: The stitchList is empty, so add it to the HOME position. The embStitchList_create function will ensure the first coordinate is at the HOME position. */
        EmbPoint home = embSettings_home(&(p->settings));
        x = home.xx + dx;
        y = home.yy + dy;
    }
    embPattern_addStitchAbs(p, x, y, flags, isAutoColorIndex);
}
Beispiel #10
0
/*TODO: The params determine the max XY movement rather than the length. They need renamed or clarified further. */
void embPattern_correctForMaxStitchLength(EmbPattern* p, double maxStitchLength, double maxJumpLength)
{
    int j = 0, splits;
    double maxXY, maxLen, addX, addY;

    if(!p) { embLog_error("emb-pattern.c embPattern_correctForMaxStitchLength(), p argument is null\n"); return; }
    if(embStitchList_count(p->stitchList) > 1)
    {
        EmbStitchList* pointer = 0;
        EmbStitchList* prev = 0;
        prev = p->stitchList;
        pointer = prev->next;

        while(pointer)
        {
            double xx = prev->stitch.xx;
            double yy = prev->stitch.yy;
            double dx = pointer->stitch.xx - xx;
            double dy = pointer->stitch.yy - yy;
            if((fabs(dx) > maxStitchLength) || (fabs(dy) > maxStitchLength))
            {
                maxXY = max(fabs(dx), fabs(dy));
                if(pointer->stitch.flags & (JUMP | TRIM)) maxLen = maxJumpLength;
                else maxLen = maxStitchLength;

                splits = (int)ceil((double)maxXY / maxLen);

                if(splits > 1)
                {
                    int flagsToUse = pointer->stitch.flags;
                    int colorToUse = pointer->stitch.color;
                    addX = (double)dx / splits;
                    addY = (double)dy / splits;

                    for(j = 1; j < splits; j++)
                    {
                        EmbStitchList *item;
                        EmbStitch s;
                        s.xx = xx + addX * j;
                        s.yy = yy + addY * j;
                        s.flags = flagsToUse;
                        s.color = colorToUse;
                        item = (EmbStitchList *)malloc(sizeof(EmbStitchList));
                        if(!item) { embLog_error("emb-pattern.c embPattern_correctForMaxStitchLength(), cannot allocate memory for item\n"); return; }
                        item->stitch = s;
                        item->next = pointer;
                        prev->next = item;
                        prev = item;
                    }
                }
            }
            prev = pointer;
            if(pointer)
            {
                pointer = pointer->next;
            }
        }
    }
    if(p->lastStitch && p->lastStitch->stitch.flags != END)
    {
        embPattern_addStitchAbs(p, p->lastStitch->stitch.xx, p->lastStitch->stitch.yy, END, 1);
    }
}
Beispiel #11
0
/*! Reads a file with the given \a fileName and loads the data into \a pattern.
 *  Returns \c true if successful, otherwise returns \c false. */
int readCsv(EmbPattern* pattern, const char* fileName)
{
    FILE* file = 0;
    int numColorChanges = 0;
    int size = 1024;
    int pos = 0;
    int c = 0;
    int cellNum = 0;
    int process = 0;
    int csvMode = CSV_MODE_NULL;
    int expect = CSV_EXPECT_QUOTE1;
    int flags = 0;
    double xx = 0.0;
    double yy = 0.0;
    unsigned char r = 0, g = 0, b = 0;
    char* buff = 0;

    if(!pattern) { embLog_error("format-csv.c readCsv(), pattern argument is null\n"); return 0; }
    if(!fileName) { embLog_error("format-csv.c readCsv(), fileName argument is null\n"); return 0; }

    buff = (char*)malloc(size);
    if(!buff) { embLog_error("format-csv.c readCsv(), unable to allocate memory for buff\n"); return 0; }

    file = fopen(fileName,"r");
    if(!file)
    {
        embLog_error("format-csv.c readCsv(), cannot open %s for reading\n", fileName);
        return 0;
    }
    else
    {
        pos = 0;
        do
        {
            c = fgetc(file);
            switch(c)
            {
                case '"':
                    if(expect == CSV_EXPECT_QUOTE1)
                    {
                        expect = CSV_EXPECT_QUOTE2;
                    }
                    else if(expect == CSV_EXPECT_QUOTE2)
                        expect = CSV_EXPECT_COMMA;
                    break;
                case ',':
                    if(expect == CSV_EXPECT_COMMA)
                    {
                        process = 1;
                    }
                    break;
                case '\n':
                    if(expect == CSV_EXPECT_COMMA)
                    {
                        process = 1;
                    }
                    else if(expect == CSV_EXPECT_QUOTE1)
                    {
                        /* Do Nothing. We encountered a blank line. */
                    }
                    else
                    {
                        embLog_error("format-csv.c readCsv(), premature newline\n");
                        return 0;
                    }
                    break;
            }
            if(pos >= size - 1)
            {
                size *= 2;
                buff = (char*)realloc(buff,size);
                if(!buff) { embLog_error("format-csv.c readCsv(), cannot re-allocate memory for buff\n"); return 0; }
            }

            if(process)
            {
                buff[pos] = 0;
                pos = 0;
                process = 0;
                cellNum++;
                expect = CSV_EXPECT_QUOTE1;
                if(csvMode == CSV_MODE_NULL)
                {
                    if     (!strcmp(buff, "#")) { csvMode = CSV_MODE_COMMENT; }
                    else if(!strcmp(buff, ">")) { csvMode = CSV_MODE_VARIABLE; }
                    else if(!strcmp(buff, "$")) { csvMode = CSV_MODE_THREAD; }
                    else if(!strcmp(buff, "*")) { csvMode = CSV_MODE_STITCH; }
                    else { /* TODO: error */ return 0; }
                }
                else if(csvMode == CSV_MODE_COMMENT)
                {
                    /* Do Nothing */
                }
                else if(csvMode == CSV_MODE_VARIABLE)
                {
                    /* Do Nothing */
                }
                else if(csvMode == CSV_MODE_THREAD)
                {
                    if(cellNum == 2)
                    {
                        /* Do Nothing. Ignore Thread Number */
                    }
                    else if(cellNum == 3)
                        r = (unsigned char)atoi(buff);
                    else if(cellNum == 4)
                        g = (unsigned char)atoi(buff);
                    else if(cellNum == 5)
                        b = (unsigned char)atoi(buff);
                    else if(cellNum == 6)
                    {
                        /* TODO: Thread Description */
                    }
                    else if(cellNum == 7)
                    {
                        /* TODO: Thread Catalog Number */
                        EmbThread t;
                        t.color.r = r;
                        t.color.g = g;
                        t.color.b = b;
                        t.description = "TODO:DESCRIPTION";
                        t.catalogNumber = "TODO:CATALOG_NUMBER";
                        embPattern_addThread(pattern, t);
                        csvMode = CSV_MODE_NULL;
                        cellNum = 0;
                    }
                    else
                    {
                        /* TODO: error */
                        return 0;
                    }
                }
                else if(csvMode == CSV_MODE_STITCH)
                {
                    if(cellNum == 2)
                    {
                        flags = csvStrToStitchFlag(buff);
                        if(flags == STOP)
                            numColorChanges++;
                    }
                    else if(cellNum == 3)
                        xx = atof(buff);
                    else if(cellNum == 4)
                    {
                        yy = atof(buff);
                        embPattern_addStitchAbs(pattern, xx, yy, flags, 1);
                        csvMode = CSV_MODE_NULL;
                        cellNum = 0;
                    }
                    else
                    {
                        /* TODO: error */
                        return 0;
                    }
                }

                if(c == '\n')
                {
                    csvMode = CSV_MODE_NULL;
                    cellNum = 0;
                }
            }
            else
            {
                if(expect == CSV_EXPECT_QUOTE2 && c != '"')
                    buff[pos++] = (char)c;
            }
        }
        while(c != EOF);
        fclose(file);
    }

    /* if not enough colors defined, fill in random colors */
    while(embThreadList_count(pattern->threadList) < numColorChanges)
    {
        embPattern_addThread(pattern, embThread_getRandom());
    }

    free(buff);
    buff = 0;

    return 1;
}
Beispiel #12
0
/*! Reads a file with the given \a fileName and loads the data into \a pattern.
 *  Returns \c true if successful, otherwise returns \c false. */
int readVp3(EmbPattern* pattern, const char* fileName)
{
    unsigned char magicString[5];
    unsigned char some;
    unsigned char* softwareVendorString = 0;
    unsigned char v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18;
    unsigned char* anotherSoftwareVendorString = 0;
    int numberOfColors;
    long colorSectionOffset;
    unsigned char magicCode[6];
    short someShort;
    unsigned char someByte;
    int bytesRemainingInFile;
    unsigned char* fileCommentString = 0; /* some software writes used settings here */
    int hoopConfigurationOffset;
    unsigned char* anotherCommentString = 0;
    int i;
    EmbFile* file = 0;

    if(!pattern) { embLog_error("format-vp3.c readVp3(), pattern argument is null\n"); return 0; }
    if(!fileName) { embLog_error("format-vp3.c readVp3(), fileName argument is null\n"); return 0; }

    file = embFile_open(fileName, "rb");
    if(!file)
    {
        embLog_error("format-vp3.c readVp3(), cannot open %s for reading\n", fileName);
        return 0;
    }

    binaryReadBytes(file, magicString, 5); /* %vsm% */ /* TODO: check return value */

    some = binaryReadByte(file); /* 0 */
    softwareVendorString = vp3ReadString(file);
    someShort = binaryReadInt16(file);
    someByte = binaryReadByte(file);
    bytesRemainingInFile = binaryReadInt32(file);
    fileCommentString = vp3ReadString(file);
    hoopConfigurationOffset = (int)embFile_tell(file);

    vp3ReadHoopSection(file);

    anotherCommentString = vp3ReadString(file);

    /* TODO: review v1 thru v18 variables and use emb_unused() if needed */
    v1 = binaryReadByte(file);
    v2 = binaryReadByte(file);
    v3 = binaryReadByte(file);
    v4 = binaryReadByte(file);
    v5 = binaryReadByte(file);
    v6 = binaryReadByte(file);
    v7 = binaryReadByte(file);
    v8 = binaryReadByte(file);
    v9 = binaryReadByte(file);
    v10 = binaryReadByte(file);
    v11 = binaryReadByte(file);
    v12 = binaryReadByte(file);
    v13 = binaryReadByte(file);
    v14 = binaryReadByte(file);
    v15 = binaryReadByte(file);
    v16 = binaryReadByte(file);
    v17 = binaryReadByte(file);
    v18 = binaryReadByte(file);

    binaryReadBytes(file, magicCode, 6); /* 0x78 0x78 0x55 0x55 0x01 0x00 */ /* TODO: check return value */

    anotherSoftwareVendorString = vp3ReadString(file);

    numberOfColors = binaryReadInt16BE(file);
    embLog_error("format-vp3.c Number of Colors: %d\n", numberOfColors);
    colorSectionOffset = (int)embFile_tell(file);

    for(i = 0; i < numberOfColors; i++)
    {
        EmbThread t;
        char tableSize;
        int startX, startY, offsetToNextColorX, offsetToNextColorY;
        unsigned char* threadColorNumber, *colorName, *threadVendor;
        int unknownThreadString, numberOfBytesInColor;

        embFile_seek(file, colorSectionOffset, SEEK_SET);
        embLog_error("format-vp3.c Color Check Byte #1: 0 == %d\n", binaryReadByte(file));
        embLog_error("format-vp3.c Color Check Byte #2: 5 == %d\n", binaryReadByte(file));
        embLog_error("format-vp3.c Color Check Byte #3: 0 == %d\n", binaryReadByte(file));
        colorSectionOffset = binaryReadInt32BE(file);
        colorSectionOffset += embFile_tell(file);
        startX = binaryReadInt32BE(file);
        startY = binaryReadInt32BE(file);
        embPattern_addStitchAbs(pattern, startX / 1000, -startY / 1000, JUMP, 0);

        tableSize = binaryReadByte(file);
        binaryReadByte(file);
        t.color.r = binaryReadByte(file);
        t.color.g = binaryReadByte(file);
        t.color.b = binaryReadByte(file);
        embPattern_addThread(pattern, t);
        embFile_seek(file, 6*tableSize - 1, SEEK_CUR);

        threadColorNumber = vp3ReadString(file);
        colorName = vp3ReadString(file);
        threadVendor = vp3ReadString(file);

        offsetToNextColorX = binaryReadInt32BE(file);
        offsetToNextColorY = binaryReadInt32BE(file);

        unknownThreadString = binaryReadInt16BE(file);
        embFile_seek(file, unknownThreadString, SEEK_CUR);
        numberOfBytesInColor = binaryReadInt32BE(file);
        embFile_seek(file, 0x3, SEEK_CUR);
        while(embFile_tell(file) < colorSectionOffset - 1)
        {
            int lastFilePosition = embFile_tell(file);

            int x = vp3Decode(binaryReadByte(file));
            int y = vp3Decode(binaryReadByte(file));
            if(x == 0x80)
            {
                switch (y)
                {
                    case 0x00:
                    case 0x03:
                        break;
                    case 0x01:
                        x = vp3DecodeInt16(binaryReadInt16BE(file));
                        y = vp3DecodeInt16(binaryReadInt16BE(file));
                        binaryReadInt16BE(file);
                        embPattern_addStitchRel(pattern, x/ 10.0, y / 10.0, TRIM, 1);
                        break;
                    default:
                        break;
                }
            }
            else
            {
                embPattern_addStitchRel(pattern, x / 10.0, y / 10.0, NORMAL, 1);
            }

            if(embFile_tell(file) == lastFilePosition)
            {
                embLog_error("format-vp3.c could not read stitch block in entirety\n");
                return 0;
            }
        }
        if(i + 1 < numberOfColors)
            embPattern_addStitchRel(pattern, 0, 0, STOP, 1);
    }
    embFile_close(file);

    /* Check for an END stitch and add one if it is not present */
    if(pattern->lastStitch->stitch.flags != END)
        embPattern_addStitchRel(pattern, 0, 0, END, 1);

    embPattern_flipVertical(pattern);

    return 1;
}
Beispiel #13
0
/*! Reads a file with the given \a fileName and loads the data into \a pattern.
 *  Returns \c true if successful, otherwise returns \c false. */
int readPcs(EmbPattern* pattern, const char* fileName)
{
    char allZeroColor = 1;
    int i = 0;
    unsigned char b[9];
    double dx = 0, dy = 0;
    int flags = 0, st = 0;
    unsigned char version, hoopSize;
    unsigned short colorCount;
    EmbFile* file = 0;

    if(!pattern) { embLog_error("format-pcs.c readPcs(), pattern argument is null\n"); return 0; }
    if(!fileName) { embLog_error("format-pcs.c readPcs(), fileName argument is null\n"); return 0; }

    file = embFile_open(fileName, "rb");
    if(!file)
    {
        embLog_error("format-pcs.c readPcs(), cannot open %s for reading\n", fileName);
        return 0;
    }
    version = binaryReadByte(file);
    hoopSize = binaryReadByte(file);  /* 0 for PCD, 1 for PCQ (MAXI), 2 for PCS with small hoop(80x80), */
                                      /* and 3 for PCS with large hoop (115x120) */

    switch(hoopSize)
    {
        case 2:
            pattern->hoop.width = 80.0;
            pattern->hoop.height = 80.0;
            break;
        case 3:
            pattern->hoop.width = 115;
            pattern->hoop.height = 120.0;
            break;
    }

    colorCount = binaryReadUInt16(file);

    for(i = 0; i < colorCount; i++)
    {
        EmbThread t;
		t.color.r = binaryReadByte(file);
        t.color.g = binaryReadByte(file);
        t.color.b = binaryReadByte(file);
        t.catalogNumber = "";
        t.description = "";
        if(t.color.r || t.color.g || t.color.b)
        {
            allZeroColor = 0;
        }
        embPattern_addThread(pattern, t);
        binaryReadByte(file);
    }
    if(allZeroColor)
        embPattern_loadExternalColorFile(pattern, fileName);
    st = binaryReadUInt16(file);
    /* READ STITCH RECORDS */
    for(i = 0; i < st; i++)
    {
        flags = NORMAL;
        if(embFile_read(b, 1, 9, file) != 9)
            break;

        if(b[8] & 0x01)
        {
            flags = STOP;
        }
        else if(b[8] & 0x04)
        {
            flags = TRIM;
        }
        else if(b[8] != 0)
        {
            /* TODO: ONLY INTERESTED IN THIS CASE TO LEARN MORE ABOUT THE FORMAT */
        }
        dx = pcsDecode(b[1], b[2], b[3]);
        dy = pcsDecode(b[5], b[6], b[7]);
        embPattern_addStitchAbs(pattern, dx / 10.0, dy / 10.0, flags, 1);
    }
    embFile_close(file);

    /* Check for an END stitch and add one if it is not present */
    if(pattern->lastStitch->stitch.flags != END)
        embPattern_addStitchRel(pattern, 0, 0, END, 1);

    return 1;
}