<commit_before>
/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "gm.h"

#include "SkColorPriv.h"
#include "SkGeometry.h"
#include "SkShader.h"

static void tesselate(const SkPath& src, SkPath* dst) {
    SkPath::Iter iter(src, true);
    SkPoint pts[4];
    SkPath::Verb verb;
    while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
        switch (verb) {
            case SkPath::kMove_Verb:
                dst->moveTo(pts[0]);
                break;
            case SkPath::kLine_Verb:
                dst->lineTo(pts[1]);
                break;
            case SkPath::kQuad_Verb: {
                SkPoint p;
                for (int i = 1; i <= 8; ++i) {
                    SkEvalQuadAt(pts, i / 8.0f, &p, NULL);
                    dst->lineTo(p);
                }
            } break;
            case SkPath::kCubic_Verb: {
                SkPoint p;
                for (int i = 1; i <= 8; ++i) {
                    SkEvalCubicAt(pts, i / 8.0f, &p, NULL, NULL);
                    dst->lineTo(p);
                }
            } break;
        }
    }
}

static void setFade(SkPaint* paint, bool showGL) {
    paint->setAlpha(showGL ? 0x66 : 0xFF);
}

static void setGLFrame(SkPaint* paint) {
    paint->setColor(0xFFFF0000);
    paint->setStyle(SkPaint::kStroke_Style);
    paint->setAntiAlias(true);
    paint->setStrokeWidth(1.1f);
}

static void show_mesh(SkCanvas* canvas, const SkRect& r) {
    SkPaint paint;
    setGLFrame(&paint);

    canvas->drawRect(r, paint);
    canvas->drawLine(r.fLeft, r.fTop, r.fRight, r.fBottom, paint);
}

static void drawLine(SkCanvas* canvas, const SkPoint& p0, const SkPoint& p1,
                     const SkPaint& paint) {
    canvas->drawLine(p0.fX, p0.fY, p1.fX, p1.fY, paint);
}

static void show_mesh(SkCanvas* canvas, const SkPoint pts[],
                      const uint16_t indices[], int count) {
    SkPaint paint;
    setGLFrame(&paint);

    for (int i = 0; i < count - 2; ++i) {
        drawLine(canvas, pts[indices[i]], pts[indices[i+1]], paint);
        drawLine(canvas, pts[indices[i+1]], pts[indices[i+2]], paint);
        drawLine(canvas, pts[indices[i+2]], pts[indices[i]], paint);
    }
}

static void show_glframe(SkCanvas* canvas, const SkPath& path) {
    SkPaint paint;
    setGLFrame(&paint);
    canvas->drawPath(path, paint);
}

static void show_mesh_between(SkCanvas* canvas, const SkPath& p0, const SkPath& p1) {
    SkPath d0, d1;
    tesselate(p0, &d0);
    tesselate(p1, &d1);

    SkPoint pts0[256*2], pts1[256];
    int count = d0.getPoints(pts0, SK_ARRAY_COUNT(pts0));
    int count1 = d1.getPoints(pts1, SK_ARRAY_COUNT(pts1));
    SkASSERT(count == count1);
    memcpy(&pts0[count], pts1, count * sizeof(SkPoint));

    uint16_t indices[256*6];
    uint16_t* ndx = indices;
    for (int i = 0; i < count; ++i) {
        *ndx++ = i;
        *ndx++ = i + count;
    }
    *ndx++ = 0;

    show_mesh(canvas, pts0, indices, ndx - indices);
}

static void show_fan(SkCanvas* canvas, const SkPath& path, SkScalar cx, SkScalar cy) {
    SkPaint paint;
    setGLFrame(&paint);

    canvas->drawPath(path, paint);

    SkPoint pts[256];
    int count = path.getPoints(pts, SK_ARRAY_COUNT(pts));
    for (int i = 0; i < count; ++i) {
        canvas->drawLine(pts[i].fX, pts[i].fY, cx, cy, paint);
    }
}

///////////////////////////////////////////////////////////////////////////////

typedef void (*DrawProc)(SkCanvas* canvas, bool showGL, int flags);

static void draw_line(SkCanvas* canvas, bool showGL, int flags) {
    SkPaint paint;
    paint.setAntiAlias(true);

    canvas->drawLine(50, 50, 400, 100, paint);

    canvas->rotate(40);
    setFade(&paint, showGL);
    paint.setStrokeWidth(40);
    canvas->drawLine(100, 50, 450, 50, paint);
    if (showGL) {
        show_mesh(canvas, SkRect::MakeLTRB(100, 50-20, 450, 50+20));
    }
}

static void draw_rect(SkCanvas* canvas, bool showGL, int flags) {
    SkPaint paint;
    paint.setAntiAlias(true);

    SkRect r = SkRect::MakeLTRB(50, 70, 250, 370);

    setFade(&paint, showGL);
    canvas->drawRect(r, paint);
    if (showGL) {
        show_mesh(canvas, r);
    }

    canvas->translate(320, 0);

    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(25);
    canvas->drawRect(r, paint);
    if (showGL) {
        SkScalar rad = paint.getStrokeWidth() / 2;
        SkPoint pts[8];
        r.outset(rad, rad);
        r.toQuad(&pts[0]);
        r.inset(rad*2, rad*2);
        r.toQuad(&pts[4]);

        const uint16_t indices[] = {
            0, 4, 1, 5, 2, 6, 3, 7, 0, 4
        };
        show_mesh(canvas, pts, indices, SK_ARRAY_COUNT(indices));
    }
}

static void draw_oval(SkCanvas* canvas, bool showGL, int flags) {
    SkPaint paint;
    paint.setAntiAlias(true);

    SkRect r = SkRect::MakeLTRB(50, 70, 250, 370);

    setFade(&paint, showGL);
    canvas->drawOval(r, paint);
    if (showGL) {
        switch (flags) {
            case 0: {
                SkPath path;
                path.addOval(r);
                show_glframe(canvas, path);
            } break;
            case 1:
            case 2: {
                SkPath src, dst;
                src.addOval(r);
                tesselate(src, &dst);
                show_fan(canvas, dst, r.centerX(), r.centerY());
            } break;
        }
    }

    canvas->translate(320, 0);

    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(25);
    canvas->drawOval(r, paint);
    if (showGL) {
        switch (flags) {
            case 0: {
                SkPath path;
                SkScalar rad = paint.getStrokeWidth() / 2;
                r.outset(rad, rad);
                path.addOval(r);
                r.inset(rad*2, rad*2);
                path.addOval(r);
                show_glframe(canvas, path);
            } break;
            case 1: {
                SkPath path0, path1;
                SkScalar rad = paint.getStrokeWidth() / 2;
                r.outset(rad, rad);
                path0.addOval(r);
                r.inset(rad*2, rad*2);
                path1.addOval(r);
                show_mesh_between(canvas, path0, path1);
            } break;
            case 2: {
                SkScalar rad = paint.getStrokeWidth() / 2;
                r.outset(rad, rad);
                SkPaint paint;
                paint.setAlpha(0x33);
                canvas->drawRect(r, paint);
                show_mesh(canvas, r);
            } break;
        }
    }
}

#include "SkImageDecoder.h"
static void draw_image(SkCanvas* canvas, bool showGL, int flags) {
    SkPaint paint;
    paint.setAntiAlias(true);
    paint.setFilterBitmap(true);
    setFade(&paint, showGL);

    SkBitmap bm;
    SkImageDecoder::DecodeFile("/skimages/startrek.png", &bm);
    SkRect r = SkRect::MakeWH(bm.width(), bm.height());

    canvas->save();
    canvas->translate(30, 30);
    canvas->scale(0.8f, 0.8f);
    canvas->drawBitmap(bm, 0, 0, &paint);
    if (showGL) {
        show_mesh(canvas, r);
    }
    canvas->restore();

    canvas->translate(210, 290);
    canvas->rotate(-35);
    canvas->drawBitmap(bm, 0, 0, &paint);
    if (showGL) {
        show_mesh(canvas, r);
    }
}

static void draw_text(SkCanvas* canvas, bool showGL, int flags) {
    SkPaint paint;
    paint.setAntiAlias(true);
    const char text[] = "Graphics at Google";
    size_t len = strlen(text);
    setFade(&paint, showGL);

    canvas->translate(40, 50);
    for (int i = 0; i < 10; ++i) {
        paint.setTextSize(12 + i * 3);
        canvas->drawText(text, len, 0, 0, paint);
        if (showGL) {
            SkRect bounds[256];
            SkScalar widths[256];
            int count = paint.getTextWidths(text, len, widths, bounds);
            SkScalar adv = 0;
            for (int j = 0; j < count; ++j) {
                bounds[j].offset(adv, 0);
                show_mesh(canvas, bounds[j]);
                adv += widths[j];
            }
        }
        canvas->translate(0, paint.getTextSize() * 3 / 2);
    }
}

static const struct {
    DrawProc    fProc;
    const char* fName;
} gRec[] = {
    {   draw_line,  "Lines" },
    {   draw_rect,  "Rects" },
    {   draw_oval,  "Ovals" },
    {   draw_image, "Images" },
    {   draw_text,  "Text" },
};

class TalkGM : public skiagm::GM {
    DrawProc fProc;
    SkString fName;
    bool     fShowGL;
    int      fFlags;

public:
    TalkGM(int index, bool showGL, int flags = 0) {
        fProc = gRec[index].fProc;
        fName.set(gRec[index].fName);
        if (showGL) {
            fName.append("-gl");
        }
        fShowGL = showGL;
        fFlags = flags;
    }

protected:
    virtual SkString onShortName() {
        return fName;
    }

    virtual SkISize onISize() {
        return SkISize::Make(640, 480);
    }

    virtual void onDraw(SkCanvas* canvas) {
        SkRect dst = SkRect::MakeWH(canvas->getDevice()->width(), canvas->getDevice()->height());
        SkRect src = SkRect::MakeWH(640, 480);
        SkMatrix matrix;
        matrix.setRectToRect(src, dst, SkMatrix::kCenter_ScaleToFit);

        canvas->concat(matrix);
        fProc(canvas, fShowGL, fFlags);
    }

private:
    typedef skiagm::GM INHERITED;
};

//////////////////////////////////////////////////////////////////////////////

#define GM_CONCAT(X,Y) GM_CONCAT_IMPL(X,Y)
#define GM_CONCAT_IMPL(X,Y) X##Y

#define FACTORY_NAME  GM_CONCAT(Factory, __LINE__)
#define REGISTRY_NAME  GM_CONCAT(gReg, __LINE__)

#define ADD_GM(Class, args)    \
    static skiagm::GM* FACTORY_NAME(void*) { return new Class args; } \
    static skiagm::GMRegistry REGISTRY_NAME(FACTORY_NAME);

ADD_GM(TalkGM, (0, false))
ADD_GM(TalkGM, (0, true))
ADD_GM(TalkGM, (1, false))
ADD_GM(TalkGM, (1, true))
ADD_GM(TalkGM, (2, false))
ADD_GM(TalkGM, (2, true))
ADD_GM(TalkGM, (2, true, 1))
ADD_GM(TalkGM, (2, true, 2))
ADD_GM(TalkGM, (3, false))
ADD_GM(TalkGM, (3, true))
ADD_GM(TalkGM, (4, false))
ADD_GM(TalkGM, (4, true))

//static GM* MyFactory(void*) { return new TalkGM(0, false); }
//static GMRegistry reg(MyFactory);

<commit_msg>Sanitizing source files in Skia_Periodic_House_Keeping<commit_after>
/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "gm.h"

#include "SkColorPriv.h"
#include "SkGeometry.h"
#include "SkShader.h"

static void tesselate(const SkPath& src, SkPath* dst) {
    SkPath::Iter iter(src, true);
    SkPoint pts[4];
    SkPath::Verb verb;
    while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
        switch (verb) {
            case SkPath::kMove_Verb:
                dst->moveTo(pts[0]);
                break;
            case SkPath::kLine_Verb:
                dst->lineTo(pts[1]);
                break;
            case SkPath::kQuad_Verb: {
                SkPoint p;
                for (int i = 1; i <= 8; ++i) {
                    SkEvalQuadAt(pts, i / 8.0f, &p, NULL);
                    dst->lineTo(p);
                }
            } break;
            case SkPath::kCubic_Verb: {
                SkPoint p;
                for (int i = 1; i <= 8; ++i) {
                    SkEvalCubicAt(pts, i / 8.0f, &p, NULL, NULL);
                    dst->lineTo(p);
                }
            } break;
        }
    }
}

static void setFade(SkPaint* paint, bool showGL) {
    paint->setAlpha(showGL ? 0x66 : 0xFF);
}

static void setGLFrame(SkPaint* paint) {
    paint->setColor(0xFFFF0000);
    paint->setStyle(SkPaint::kStroke_Style);
    paint->setAntiAlias(true);
    paint->setStrokeWidth(1.1f);
}

static void show_mesh(SkCanvas* canvas, const SkRect& r) {
    SkPaint paint;
    setGLFrame(&paint);

    canvas->drawRect(r, paint);
    canvas->drawLine(r.fLeft, r.fTop, r.fRight, r.fBottom, paint);
}

static void drawLine(SkCanvas* canvas, const SkPoint& p0, const SkPoint& p1,
                     const SkPaint& paint) {
    canvas->drawLine(p0.fX, p0.fY, p1.fX, p1.fY, paint);
}

static void show_mesh(SkCanvas* canvas, const SkPoint pts[],
                      const uint16_t indices[], int count) {
    SkPaint paint;
    setGLFrame(&paint);

    for (int i = 0; i < count - 2; ++i) {
        drawLine(canvas, pts[indices[i]], pts[indices[i+1]], paint);
        drawLine(canvas, pts[indices[i+1]], pts[indices[i+2]], paint);
        drawLine(canvas, pts[indices[i+2]], pts[indices[i]], paint);
    }
}

static void show_glframe(SkCanvas* canvas, const SkPath& path) {
    SkPaint paint;
    setGLFrame(&paint);
    canvas->drawPath(path, paint);
}

static void show_mesh_between(SkCanvas* canvas, const SkPath& p0, const SkPath& p1) {
    SkPath d0, d1;
    tesselate(p0, &d0);
    tesselate(p1, &d1);

    SkPoint pts0[256*2], pts1[256];
    int count = d0.getPoints(pts0, SK_ARRAY_COUNT(pts0));
    int count1 = d1.getPoints(pts1, SK_ARRAY_COUNT(pts1));
    SkASSERT(count == count1);
    memcpy(&pts0[count], pts1, count * sizeof(SkPoint));

    uint16_t indices[256*6];
    uint16_t* ndx = indices;
    for (int i = 0; i < count; ++i) {
        *ndx++ = i;
        *ndx++ = i + count;
    }
    *ndx++ = 0;

    show_mesh(canvas, pts0, indices, ndx - indices);
}

static void show_fan(SkCanvas* canvas, const SkPath& path, SkScalar cx, SkScalar cy) {
    SkPaint paint;
    setGLFrame(&paint);

    canvas->drawPath(path, paint);

    SkPoint pts[256];
    int count = path.getPoints(pts, SK_ARRAY_COUNT(pts));
    for (int i = 0; i < count; ++i) {
        canvas->drawLine(pts[i].fX, pts[i].fY, cx, cy, paint);
    }
}

///////////////////////////////////////////////////////////////////////////////

typedef void (*DrawProc)(SkCanvas* canvas, bool showGL, int flags);

static void draw_line(SkCanvas* canvas, bool showGL, int flags) {
    SkPaint paint;
    paint.setAntiAlias(true);

    canvas->drawLine(50, 50, 400, 100, paint);

    canvas->rotate(40);
    setFade(&paint, showGL);
    paint.setStrokeWidth(40);
    canvas->drawLine(100, 50, 450, 50, paint);
    if (showGL) {
        show_mesh(canvas, SkRect::MakeLTRB(100, 50-20, 450, 50+20));
    }
}

static void draw_rect(SkCanvas* canvas, bool showGL, int flags) {
    SkPaint paint;
    paint.setAntiAlias(true);

    SkRect r = SkRect::MakeLTRB(50, 70, 250, 370);

    setFade(&paint, showGL);
    canvas->drawRect(r, paint);
    if (showGL) {
        show_mesh(canvas, r);
    }

    canvas->translate(320, 0);

    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(25);
    canvas->drawRect(r, paint);
    if (showGL) {
        SkScalar rad = paint.getStrokeWidth() / 2;
        SkPoint pts[8];
        r.outset(rad, rad);
        r.toQuad(&pts[0]);
        r.inset(rad*2, rad*2);
        r.toQuad(&pts[4]);

        const uint16_t indices[] = {
            0, 4, 1, 5, 2, 6, 3, 7, 0, 4
        };
        show_mesh(canvas, pts, indices, SK_ARRAY_COUNT(indices));
    }
}

static void draw_oval(SkCanvas* canvas, bool showGL, int flags) {
    SkPaint paint;
    paint.setAntiAlias(true);

    SkRect r = SkRect::MakeLTRB(50, 70, 250, 370);

    setFade(&paint, showGL);
    canvas->drawOval(r, paint);
    if (showGL) {
        switch (flags) {
            case 0: {
                SkPath path;
                path.addOval(r);
                show_glframe(canvas, path);
            } break;
            case 1:
            case 2: {
                SkPath src, dst;
                src.addOval(r);
                tesselate(src, &dst);
                show_fan(canvas, dst, r.centerX(), r.centerY());
            } break;
        }
    }

    canvas->translate(320, 0);

    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(25);
    canvas->drawOval(r, paint);
    if (showGL) {
        switch (flags) {
            case 0: {
                SkPath path;
                SkScalar rad = paint.getStrokeWidth() / 2;
                r.outset(rad, rad);
                path.addOval(r);
                r.inset(rad*2, rad*2);
                path.addOval(r);
                show_glframe(canvas, path);
            } break;
            case 1: {
                SkPath path0, path1;
                SkScalar rad = paint.getStrokeWidth() / 2;
                r.outset(rad, rad);
                path0.addOval(r);
                r.inset(rad*2, rad*2);
                path1.addOval(r);
                show_mesh_between(canvas, path0, path1);
            } break;
            case 2: {
                SkScalar rad = paint.getStrokeWidth() / 2;
                r.outset(rad, rad);
                SkPaint paint;
                paint.setAlpha(0x33);
                canvas->drawRect(r, paint);
                show_mesh(canvas, r);
            } break;
        }
    }
}

#include "SkImageDecoder.h"
static void draw_image(SkCanvas* canvas, bool showGL, int flags) {
    SkPaint paint;
    paint.setAntiAlias(true);
    paint.setFilterBitmap(true);
    setFade(&paint, showGL);

    SkBitmap bm;
    SkImageDecoder::DecodeFile("/skimages/startrek.png", &bm);
    SkRect r = SkRect::MakeWH(bm.width(), bm.height());

    canvas->save();
    canvas->translate(30, 30);
    canvas->scale(0.8f, 0.8f);
    canvas->drawBitmap(bm, 0, 0, &paint);
    if (showGL) {
        show_mesh(canvas, r);
    }
    canvas->restore();

    canvas->translate(210, 290);
    canvas->rotate(-35);
    canvas->drawBitmap(bm, 0, 0, &paint);
    if (showGL) {
        show_mesh(canvas, r);
    }
}

static void draw_text(SkCanvas* canvas, bool showGL, int flags) {
    SkPaint paint;
    paint.setAntiAlias(true);
    const char text[] = "Graphics at Google";
    size_t len = strlen(text);
    setFade(&paint, showGL);

    canvas->translate(40, 50);
    for (int i = 0; i < 10; ++i) {
        paint.setTextSize(12 + i * 3);
        canvas->drawText(text, len, 0, 0, paint);
        if (showGL) {
            SkRect bounds[256];
            SkScalar widths[256];
            int count = paint.getTextWidths(text, len, widths, bounds);
            SkScalar adv = 0;
            for (int j = 0; j < count; ++j) {
                bounds[j].offset(adv, 0);
                show_mesh(canvas, bounds[j]);
                adv += widths[j];
            }
        }
        canvas->translate(0, paint.getTextSize() * 3 / 2);
    }
}

static const struct {
    DrawProc    fProc;
    const char* fName;
} gRec[] = {
    {   draw_line,  "Lines" },
    {   draw_rect,  "Rects" },
    {   draw_oval,  "Ovals" },
    {   draw_image, "Images" },
    {   draw_text,  "Text" },
};

class TalkGM : public skiagm::GM {
    DrawProc fProc;
    SkString fName;
    bool     fShowGL;
    int      fFlags;

public:
    TalkGM(int index, bool showGL, int flags = 0) {
        fProc = gRec[index].fProc;
        fName.set(gRec[index].fName);
        if (showGL) {
            fName.append("-gl");
        }
        fShowGL = showGL;
        fFlags = flags;
    }

protected:
    virtual SkString onShortName() {
        return fName;
    }

    virtual SkISize onISize() {
        return SkISize::Make(640, 480);
    }

    virtual void onDraw(SkCanvas* canvas) {
        SkRect dst = SkRect::MakeWH(canvas->getDevice()->width(), canvas->getDevice()->height());
        SkRect src = SkRect::MakeWH(640, 480);
        SkMatrix matrix;
        matrix.setRectToRect(src, dst, SkMatrix::kCenter_ScaleToFit);

        canvas->concat(matrix);
        fProc(canvas, fShowGL, fFlags);
    }

private:
    typedef skiagm::GM INHERITED;
};

//////////////////////////////////////////////////////////////////////////////

#define GM_CONCAT(X,Y) GM_CONCAT_IMPL(X,Y)
#define GM_CONCAT_IMPL(X,Y) X##Y

#define FACTORY_NAME  GM_CONCAT(Factory, __LINE__)
#define REGISTRY_NAME  GM_CONCAT(gReg, __LINE__)

#define ADD_GM(Class, args)    \
    static skiagm::GM* FACTORY_NAME(void*) { return new Class args; } \
    static skiagm::GMRegistry REGISTRY_NAME(FACTORY_NAME);

ADD_GM(TalkGM, (0, false))
ADD_GM(TalkGM, (0, true))
ADD_GM(TalkGM, (1, false))
ADD_GM(TalkGM, (1, true))
ADD_GM(TalkGM, (2, false))
ADD_GM(TalkGM, (2, true))
ADD_GM(TalkGM, (2, true, 1))
ADD_GM(TalkGM, (2, true, 2))
ADD_GM(TalkGM, (3, false))
ADD_GM(TalkGM, (3, true))
ADD_GM(TalkGM, (4, false))
ADD_GM(TalkGM, (4, true))

//static GM* MyFactory(void*) { return new TalkGM(0, false); }
//static GMRegistry reg(MyFactory);

<|endoftext|>


<commit_before>
/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "gm.h"

#include "SkColorPriv.h"
#include "SkGeometry.h"
#include "SkShader.h"

static void tesselate(const SkPath& src, SkPath* dst) {
    SkPath::Iter iter(src, true);
    SkPoint pts[4];
    SkPath::Verb verb;
    while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
        switch (verb) {
            case SkPath::kMove_Verb:
                dst->moveTo(pts[0]);
                break;
            case SkPath::kLine_Verb:
                dst->lineTo(pts[1]);
                break;
            case SkPath::kQuad_Verb: {
                SkPoint p;
                for (int i = 1; i <= 8; ++i) {
                    SkEvalQuadAt(pts, i / 8.0f, &p, NULL);
                    dst->lineTo(p);
                }
            } break;
            case SkPath::kCubic_Verb: {
                SkPoint p;
                for (int i = 1; i <= 8; ++i) {
                    SkEvalCubicAt(pts, i / 8.0f, &p, NULL, NULL);
                    dst->lineTo(p);
                }
            } break;
        }
    }
}

static void setFade(SkPaint* paint, bool showGL) {
    paint->setAlpha(showGL ? 0x66 : 0xFF);
}

static void setGLFrame(SkPaint* paint) {
    paint->setColor(0xFFFF0000);
    paint->setStyle(SkPaint::kStroke_Style);
    paint->setAntiAlias(true);
    paint->setStrokeWidth(1.1f);
}

static void show_mesh(SkCanvas* canvas, const SkRect& r) {
    SkPaint paint;
    setGLFrame(&paint);

    canvas->drawRect(r, paint);
    canvas->drawLine(r.fLeft, r.fTop, r.fRight, r.fBottom, paint);
}

static void drawLine(SkCanvas* canvas, const SkPoint& p0, const SkPoint& p1,
                     const SkPaint& paint) {
    canvas->drawLine(p0.fX, p0.fY, p1.fX, p1.fY, paint);
}

static void show_mesh(SkCanvas* canvas, const SkPoint pts[],
                      const uint16_t indices[], int count) {
    SkPaint paint;
    setGLFrame(&paint);

    for (int i = 0; i < count - 2; ++i) {
        drawLine(canvas, pts[indices[i]], pts[indices[i+1]], paint);
        drawLine(canvas, pts[indices[i+1]], pts[indices[i+2]], paint);
        drawLine(canvas, pts[indices[i+2]], pts[indices[i]], paint);
    }
}

static void show_glframe(SkCanvas* canvas, const SkPath& path) {
    SkPaint paint;
    setGLFrame(&paint);
    canvas->drawPath(path, paint);
}

static void show_mesh_between(SkCanvas* canvas, const SkPath& p0, const SkPath& p1) {
    SkPath d0, d1;
    tesselate(p0, &d0);
    tesselate(p1, &d1);

    SkPoint pts0[256*2], pts1[256];
    int count = d0.getPoints(pts0, SK_ARRAY_COUNT(pts0));
    int count1 = d1.getPoints(pts1, SK_ARRAY_COUNT(pts1));
    SkASSERT(count == count1);
    memcpy(&pts0[count], pts1, count * sizeof(SkPoint));

    uint16_t indices[256*6];
    uint16_t* ndx = indices;
    for (int i = 0; i < count; ++i) {
        *ndx++ = i;
        *ndx++ = i + count;
    }
    *ndx++ = 0;

    show_mesh(canvas, pts0, indices, ndx - indices);
}

static void show_fan(SkCanvas* canvas, const SkPath& path, SkScalar cx, SkScalar cy) {
    SkPaint paint;
    setGLFrame(&paint);

    canvas->drawPath(path, paint);

    SkPoint pts[256];
    int count = path.getPoints(pts, SK_ARRAY_COUNT(pts));
    for (int i = 0; i < count; ++i) {
        canvas->drawLine(pts[i].fX, pts[i].fY, cx, cy, paint);
    }
}

///////////////////////////////////////////////////////////////////////////////

typedef void (*DrawProc)(SkCanvas* canvas, bool showGL, int flags);

static void draw_line(SkCanvas* canvas, bool showGL, int flags) {
    SkPaint paint;
    paint.setAntiAlias(true);

    canvas->drawLine(50, 50, 400, 100, paint);

    canvas->rotate(40);
    setFade(&paint, showGL);
    paint.setStrokeWidth(40);
    canvas->drawLine(100, 50, 450, 50, paint);
    if (showGL) {
        show_mesh(canvas, SkRect::MakeLTRB(100, 50-20, 450, 50+20));
    }
}

static void draw_rect(SkCanvas* canvas, bool showGL, int flags) {
    SkPaint paint;
    paint.setAntiAlias(true);

    SkRect r = SkRect::MakeLTRB(50, 70, 250, 370);

    setFade(&paint, showGL);
    canvas->drawRect(r, paint);
    if (showGL) {
        show_mesh(canvas, r);
    }

    canvas->translate(320, 0);

    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(25);
    canvas->drawRect(r, paint);
    if (showGL) {
        SkScalar rad = paint.getStrokeWidth() / 2;
        SkPoint pts[8];
        r.outset(rad, rad);
        r.toQuad(&pts[0]);
        r.inset(rad*2, rad*2);
        r.toQuad(&pts[4]);

        const uint16_t indices[] = {
            0, 4, 1, 5, 2, 6, 3, 7, 0, 4
        };
        show_mesh(canvas, pts, indices, SK_ARRAY_COUNT(indices));
    }
}

static void draw_oval(SkCanvas* canvas, bool showGL, int flags) {
    SkPaint paint;
    paint.setAntiAlias(true);

    SkRect r = SkRect::MakeLTRB(50, 70, 250, 370);

    setFade(&paint, showGL);
    canvas->drawOval(r, paint);
    if (showGL) {
        switch (flags) {
            case 0: {
                SkPath path;
                path.addOval(r);
                show_glframe(canvas, path);
            } break;
            case 1:
            case 2: {
                SkPath src, dst;
                src.addOval(r);
                tesselate(src, &dst);
                show_fan(canvas, dst, r.centerX(), r.centerY());
            } break;
        }
    }

    canvas->translate(320, 0);

    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(25);
    canvas->drawOval(r, paint);
    if (showGL) {
        switch (flags) {
            case 0: {
                SkPath path;
                SkScalar rad = paint.getStrokeWidth() / 2;
                r.outset(rad, rad);
                path.addOval(r);
                r.inset(rad*2, rad*2);
                path.addOval(r);
                show_glframe(canvas, path);
            } break;
            case 1: {
                SkPath path0, path1;
                SkScalar rad = paint.getStrokeWidth() / 2;
                r.outset(rad, rad);
                path0.addOval(r);
                r.inset(rad*2, rad*2);
                path1.addOval(r);
                show_mesh_between(canvas, path0, path1);
            } break;
            case 2: {
                SkScalar rad = paint.getStrokeWidth() / 2;
                r.outset(rad, rad);
                SkPaint paint;
                paint.setAlpha(0x33);
                canvas->drawRect(r, paint);
                show_mesh(canvas, r);
            } break;
        }
    }
}

#include "SkImageDecoder.h"
static void draw_image(SkCanvas* canvas, bool showGL, int flags) {
    SkPaint paint;
    paint.setAntiAlias(true);
    paint.setFilterBitmap(true);
    setFade(&paint, showGL);

    SkBitmap bm;
    SkImageDecoder::DecodeFile("/skimages/startrek.png", &bm);
    SkRect r = SkRect::MakeWH(bm.width(), bm.height());

    canvas->save();
    canvas->translate(30, 30);
    canvas->scale(0.8f, 0.8f);
    canvas->drawBitmap(bm, 0, 0, &paint);
    if (showGL) {
        show_mesh(canvas, r);
    }
    canvas->restore();

    canvas->translate(210, 290);
    canvas->rotate(-35);
    canvas->drawBitmap(bm, 0, 0, &paint);
    if (showGL) {
        show_mesh(canvas, r);
    }
}

static void draw_text(SkCanvas* canvas, bool showGL, int flags) {
    SkPaint paint;
    paint.setAntiAlias(true);
    const char text[] = "Graphics at Google";
    size_t len = strlen(text);
    setFade(&paint, showGL);

    canvas->translate(40, 50);
    for (int i = 0; i < 10; ++i) {
        paint.setTextSize(12 + i * 3);
        canvas->drawText(text, len, 0, 0, paint);
        if (showGL) {
            SkRect bounds[256];
            SkScalar widths[256];
            int count = paint.getTextWidths(text, len, widths, bounds);
            SkScalar adv = 0;
            for (int j = 0; j < count; ++j) {
                bounds[j].offset(adv, 0);
                show_mesh(canvas, bounds[j]);
                adv += widths[j];
            }
        }
        canvas->translate(0, paint.getTextSize() * 3 / 2);
    }
}

static const struct {
    DrawProc    fProc;
    const char* fName;
} gRec[] = {
    {   draw_line,  "Lines" },
    {   draw_rect,  "Rects" },
    {   draw_oval,  "Ovals" },
    {   draw_image, "Images" },
    {   draw_text,  "Text" },
};

class TalkGM : public skiagm::GM {
    DrawProc fProc;
    SkString fName;
    bool     fShowGL;
    int      fFlags;

public:
    TalkGM(int index, bool showGL, int flags = 0) {
        fProc = gRec[index].fProc;
        fName.set(gRec[index].fName);
        if (showGL) {
            fName.append("-gl");
        }
        fShowGL = showGL;
        fFlags = flags;
    }

protected:
    virtual SkString onShortName() {
        return fName;
    }

    virtual SkISize onISize() {
        return SkISize::Make(640, 480);
    }

    virtual void onDraw(SkCanvas* canvas) {
        SkRect dst = SkRect::MakeWH(canvas->getDevice()->width(), canvas->getDevice()->height());
        SkRect src = SkRect::MakeWH(640, 480);
        SkMatrix matrix;
        matrix.setRectToRect(src, dst, SkMatrix::kCenter_ScaleToFit);

        canvas->concat(matrix);
        fProc(canvas, fShowGL, fFlags);
    }

private:
    typedef skiagm::GM INHERITED;
};

//////////////////////////////////////////////////////////////////////////////

#define GM_CONCAT(X,Y) GM_CONCAT_IMPL(X,Y)
#define GM_CONCAT_IMPL(X,Y) X##Y

#define FACTORY_NAME  GM_CONCAT(Factory, __LINE__)
#define REGISTRY_NAME  GM_CONCAT(gReg, __LINE__)

#define ADD_GM(Class, args)    \
    static skiagm::GM* FACTORY_NAME(void*) { return new Class args; } \
    static skiagm::GMRegistry REGISTRY_NAME(FACTORY_NAME);

ADD_GM(TalkGM, (0, false))
ADD_GM(TalkGM, (0, true))
ADD_GM(TalkGM, (1, false))
ADD_GM(TalkGM, (1, true))
ADD_GM(TalkGM, (2, false))
ADD_GM(TalkGM, (2, true))
ADD_GM(TalkGM, (2, true, 1))
ADD_GM(TalkGM, (2, true, 2))
ADD_GM(TalkGM, (3, false))
ADD_GM(TalkGM, (3, true))
ADD_GM(TalkGM, (4, false))
ADD_GM(TalkGM, (4, true))

//static GM* MyFactory(void*) { return new TalkGM(0, false); }
//static GMRegistry reg(MyFactory);

<commit_msg>update<commit_after>
/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "gm.h"

#include "SkColorPriv.h"
#include "SkGeometry.h"
#include "SkShader.h"

#define WIRE_FRAME_WIDTH    1.1f

static void tesselate(const SkPath& src, SkPath* dst) {
    SkPath::Iter iter(src, true);
    SkPoint pts[4];
    SkPath::Verb verb;
    while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
        switch (verb) {
            case SkPath::kMove_Verb:
                dst->moveTo(pts[0]);
                break;
            case SkPath::kLine_Verb:
                dst->lineTo(pts[1]);
                break;
            case SkPath::kQuad_Verb: {
                SkPoint p;
                for (int i = 1; i <= 8; ++i) {
                    SkEvalQuadAt(pts, i / 8.0f, &p, NULL);
                    dst->lineTo(p);
                }
            } break;
            case SkPath::kCubic_Verb: {
                SkPoint p;
                for (int i = 1; i <= 8; ++i) {
                    SkEvalCubicAt(pts, i / 8.0f, &p, NULL, NULL);
                    dst->lineTo(p);
                }
            } break;
        }
    }
}

static void setFade(SkPaint* paint, bool showGL) {
    paint->setAlpha(showGL ? 0x66 : 0xFF);
}

static void setGLFrame(SkPaint* paint) {
    paint->setColor(0xFFFF0000);
    paint->setStyle(SkPaint::kStroke_Style);
    paint->setAntiAlias(true);
    paint->setStrokeWidth(WIRE_FRAME_WIDTH);
}

static void show_mesh(SkCanvas* canvas, const SkRect& r) {
    SkPaint paint;
    setGLFrame(&paint);

    canvas->drawRect(r, paint);
    canvas->drawLine(r.fLeft, r.fTop, r.fRight, r.fBottom, paint);
}

static void drawLine(SkCanvas* canvas, const SkPoint& p0, const SkPoint& p1,
                     const SkPaint& paint) {
    canvas->drawLine(p0.fX, p0.fY, p1.fX, p1.fY, paint);
}

static void show_mesh(SkCanvas* canvas, const SkPoint pts[],
                      const uint16_t indices[], int count) {
    SkPaint paint;
    setGLFrame(&paint);

    for (int i = 0; i < count - 2; ++i) {
        drawLine(canvas, pts[indices[i]], pts[indices[i+1]], paint);
        drawLine(canvas, pts[indices[i+1]], pts[indices[i+2]], paint);
        drawLine(canvas, pts[indices[i+2]], pts[indices[i]], paint);
    }
}

static void show_glframe(SkCanvas* canvas, const SkPath& path) {
    SkPaint paint;
    setGLFrame(&paint);
    canvas->drawPath(path, paint);
}

static void show_mesh_between(SkCanvas* canvas, const SkPath& p0, const SkPath& p1) {
    SkPath d0, d1;
    tesselate(p0, &d0);
    tesselate(p1, &d1);

    SkPoint pts0[256*2], pts1[256];
    int count = d0.getPoints(pts0, SK_ARRAY_COUNT(pts0));
    int count1 = d1.getPoints(pts1, SK_ARRAY_COUNT(pts1));
    SkASSERT(count == count1);
    memcpy(&pts0[count], pts1, count * sizeof(SkPoint));

    uint16_t indices[256*6];
    uint16_t* ndx = indices;
    for (int i = 0; i < count; ++i) {
        *ndx++ = i;
        *ndx++ = i + count;
    }
    *ndx++ = 0;

    show_mesh(canvas, pts0, indices, ndx - indices);
}

static void show_fan(SkCanvas* canvas, const SkPath& path, SkScalar cx, SkScalar cy) {
    SkPaint paint;
    setGLFrame(&paint);

    canvas->drawPath(path, paint);

    SkPoint pts[256];
    int count = path.getPoints(pts, SK_ARRAY_COUNT(pts));
    for (int i = 0; i < count; ++i) {
        canvas->drawLine(pts[i].fX, pts[i].fY, cx, cy, paint);
    }
}

///////////////////////////////////////////////////////////////////////////////

typedef void (*DrawProc)(SkCanvas* canvas, bool showGL, int flags);

static void draw_line(SkCanvas* canvas, bool showGL, int flags) {
    SkPaint paint;
    paint.setAntiAlias(true);

    if (showGL) {
        setGLFrame(&paint);
    }
    canvas->drawLine(50, 50, 400, 100, paint);
    paint.setColor(SK_ColorBLACK);

    canvas->rotate(40);
    setFade(&paint, showGL);
    paint.setStrokeWidth(40);
    canvas->drawLine(100, 50, 450, 50, paint);
    if (showGL) {
        show_mesh(canvas, SkRect::MakeLTRB(100, 50-20, 450, 50+20));
    }
}

static void draw_rect(SkCanvas* canvas, bool showGL, int flags) {
    SkPaint paint;
    paint.setAntiAlias(true);

    SkRect r = SkRect::MakeLTRB(50, 70, 250, 370);

    setFade(&paint, showGL);
    canvas->drawRect(r, paint);
    if (showGL) {
        show_mesh(canvas, r);
    }

    canvas->translate(320, 0);

    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(25);
    canvas->drawRect(r, paint);
    if (showGL) {
        SkScalar rad = paint.getStrokeWidth() / 2;
        SkPoint pts[8];
        r.outset(rad, rad);
        r.toQuad(&pts[0]);
        r.inset(rad*2, rad*2);
        r.toQuad(&pts[4]);

        const uint16_t indices[] = {
            0, 4, 1, 5, 2, 6, 3, 7, 0, 4
        };
        show_mesh(canvas, pts, indices, SK_ARRAY_COUNT(indices));
    }
}

static void draw_oval(SkCanvas* canvas, bool showGL, int flags) {
    SkPaint paint;
    paint.setAntiAlias(true);

    SkRect r = SkRect::MakeLTRB(50, 70, 250, 370);

    setFade(&paint, showGL);
    canvas->drawOval(r, paint);
    if (showGL) {
        switch (flags) {
            case 0: {
                SkPath path;
                path.addOval(r);
                show_glframe(canvas, path);
            } break;
            case 1:
            case 3: {
                SkPath src, dst;
                src.addOval(r);
                tesselate(src, &dst);
                show_fan(canvas, dst, r.centerX(), r.centerY());
            } break;
            case 2: {
                SkPaint p(paint);
                show_mesh(canvas, r);
                setGLFrame(&p);
                paint.setStyle(SkPaint::kFill_Style);
                canvas->drawCircle(r.centerX(), r.centerY(), 3, p);
            } break;
        }
    }

    canvas->translate(320, 0);

    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(25);
    canvas->drawOval(r, paint);
    if (showGL) {
        switch (flags) {
            case 0: {
                SkPath path;
                SkScalar rad = paint.getStrokeWidth() / 2;
                r.outset(rad, rad);
                path.addOval(r);
                r.inset(rad*2, rad*2);
                path.addOval(r);
                show_glframe(canvas, path);
            } break;
            case 1: {
                SkPath path0, path1;
                SkScalar rad = paint.getStrokeWidth() / 2;
                r.outset(rad, rad);
                path0.addOval(r);
                r.inset(rad*2, rad*2);
                path1.addOval(r);
                show_mesh_between(canvas, path0, path1);
            } break;
            case 2: {
                SkPath path;
                path.addOval(r);
                show_glframe(canvas, path);
                SkScalar rad = paint.getStrokeWidth() / 2;
                r.outset(rad, rad);
                show_mesh(canvas, r);
            } break;
            case 3: {
                SkScalar rad = paint.getStrokeWidth() / 2;
                r.outset(rad, rad);
                SkPaint paint;
                paint.setAlpha(0x33);
                canvas->drawRect(r, paint);
                show_mesh(canvas, r);
            } break;
        }
    }
}

#include "SkImageDecoder.h"
static void draw_image(SkCanvas* canvas, bool showGL, int flags) {
    SkPaint paint;
    paint.setAntiAlias(true);
    paint.setFilterBitmap(true);
    setFade(&paint, showGL);

    SkBitmap bm;
    SkImageDecoder::DecodeFile("/skimages/startrek.png", &bm);
    SkRect r = SkRect::MakeWH(bm.width(), bm.height());

    canvas->save();
    canvas->translate(30, 30);
    canvas->scale(0.8f, 0.8f);
    canvas->drawBitmap(bm, 0, 0, &paint);
    if (showGL) {
        show_mesh(canvas, r);
    }
    canvas->restore();

    canvas->translate(210, 290);
    canvas->rotate(-35);
    canvas->drawBitmap(bm, 0, 0, &paint);
    if (showGL) {
        show_mesh(canvas, r);
    }
}

static void draw_text(SkCanvas* canvas, bool showGL, int flags) {
    SkPaint paint;
    paint.setAntiAlias(true);
    const char text[] = "Graphics at Google";
    size_t len = strlen(text);
    setFade(&paint, showGL);

    canvas->translate(40, 50);
    for (int i = 0; i < 10; ++i) {
        paint.setTextSize(12 + i * 3);
        canvas->drawText(text, len, 0, 0, paint);
        if (showGL) {
            SkRect bounds[256];
            SkScalar widths[256];
            int count = paint.getTextWidths(text, len, widths, bounds);
            SkScalar adv = 0;
            for (int j = 0; j < count; ++j) {
                bounds[j].offset(adv, 0);
                show_mesh(canvas, bounds[j]);
                adv += widths[j];
            }
        }
        canvas->translate(0, paint.getTextSize() * 3 / 2);
    }
}

static const struct {
    DrawProc    fProc;
    const char* fName;
} gRec[] = {
    {   draw_line,  "Lines" },
    {   draw_rect,  "Rects" },
    {   draw_oval,  "Ovals" },
    {   draw_image, "Images" },
    {   draw_text,  "Text" },
};

class TalkGM : public skiagm::GM {
    DrawProc fProc;
    SkString fName;
    bool     fShowGL;
    int      fFlags;

public:
    TalkGM(int index, bool showGL, int flags = 0) {
        fProc = gRec[index].fProc;
        fName.set(gRec[index].fName);
        if (showGL) {
            fName.append("-gl");
        }
        fShowGL = showGL;
        fFlags = flags;
    }

protected:
    virtual SkString onShortName() {
        return fName;
    }

    virtual SkISize onISize() {
        return SkISize::Make(640, 480);
    }

    virtual void onDraw(SkCanvas* canvas) {
        SkRect dst = SkRect::MakeWH(canvas->getDevice()->width(), canvas->getDevice()->height());
        SkRect src = SkRect::MakeWH(640, 480);
        SkMatrix matrix;
        matrix.setRectToRect(src, dst, SkMatrix::kCenter_ScaleToFit);

        canvas->concat(matrix);
        fProc(canvas, fShowGL, fFlags);
    }

private:
    typedef skiagm::GM INHERITED;
};

//////////////////////////////////////////////////////////////////////////////

#define GM_CONCAT(X,Y) GM_CONCAT_IMPL(X,Y)
#define GM_CONCAT_IMPL(X,Y) X##Y

#define FACTORY_NAME  GM_CONCAT(Factory, __LINE__)
#define REGISTRY_NAME  GM_CONCAT(gReg, __LINE__)

#define ADD_GM(Class, args)    \
    static skiagm::GM* FACTORY_NAME(void*) { return new Class args; } \
    static skiagm::GMRegistry REGISTRY_NAME(FACTORY_NAME);

ADD_GM(TalkGM, (0, false))
ADD_GM(TalkGM, (0, true))
ADD_GM(TalkGM, (1, false))
ADD_GM(TalkGM, (1, true))
ADD_GM(TalkGM, (2, false))
ADD_GM(TalkGM, (2, true))
ADD_GM(TalkGM, (2, true, 1))
ADD_GM(TalkGM, (2, true, 2))
ADD_GM(TalkGM, (2, true, 3))
ADD_GM(TalkGM, (3, false))
ADD_GM(TalkGM, (3, true))
ADD_GM(TalkGM, (4, false))
ADD_GM(TalkGM, (4, true))

//static GM* MyFactory(void*) { return new TalkGM(0, false); }
//static GMRegistry reg(MyFactory);

<|endoftext|>


<commit_before>// Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/

#include "Nsfe_Emu.h"

#include "blargg_endian.h"
#include <string.h>
#include <ctype.h>

/* Copyright (C) 2005-2006 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. This
module is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details. You should have received a copy of the GNU Lesser General Public
License along with this module; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */

#include "blargg_source.h"

Nsfe_Info::Nsfe_Info() { playlist_disabled = false; }

Nsfe_Info::~Nsfe_Info() { }

inline void Nsfe_Info::unload()
{
	track_name_data.clear();
	track_names.clear();
	playlist.clear();
	track_times.clear();
}

// TODO: if no playlist, treat as if there is a playlist that is just 1,2,3,4,5... ?
void Nsfe_Info::disable_playlist( bool b )
{
	playlist_disabled = b;
	info.track_count = playlist.size();
	if ( !info.track_count || playlist_disabled )
		info.track_count = actual_track_count_;
}

int Nsfe_Info::remap_track( int track ) const
{
	if ( !playlist_disabled && (unsigned) track < playlist.size() )
		track = playlist [track];
	return track;
}

// Read multiple strings and separate into individual strings
static blargg_err_t read_strs( Data_Reader& in, long size, blargg_vector<char>& chars,
		blargg_vector<const char*>& strs )
{
	RETURN_ERR( chars.resize( size + 1 ) );
	chars [size] = 0; // in case last string doesn't have terminator
	RETURN_ERR( in.read( &chars [0], size ) );

	RETURN_ERR( strs.resize( 128 ) );
	int count = 0;
	for ( int i = 0; i < size; i++ )
	{
		if ( (int) strs.size() <= count )
			RETURN_ERR( strs.resize( count * 2 ) );
		strs [count++] = &chars [i];
		while ( i < size && chars [i] )
			i++;
	}

	return strs.resize( count );
}

// Copy in to out, where out has out_max characters allocated. Truncate to
// out_max - 1 characters.
static void copy_str( const char* in, char* out, int out_max )
{
	out [out_max - 1] = 0;
	strncpy( out, in, out_max - 1 );
}

struct nsfe_info_t
{
	byte load_addr [2];
	byte init_addr [2];
	byte play_addr [2];
	byte speed_flags;
	byte chip_flags;
	byte track_count;
	byte first_track;
	byte unused [6];
};

blargg_err_t Nsfe_Info::load( Data_Reader& in, Nsf_Emu* nsf_emu )
{
	int const nsfe_info_size = 16;
	assert( offsetof (nsfe_info_t,unused [6]) == nsfe_info_size );

	// check header
	byte signature [4];
	blargg_err_t err = in.read( signature, sizeof signature );
	if ( err )
		return (err == in.eof_error ? gme_wrong_file_type : err);
	if ( memcmp( signature, "NSFE", 4 ) )
		return gme_wrong_file_type;

	// free previous info
	track_name_data.clear();
	track_names.clear();
	playlist.clear();
	track_times.clear();

	// default nsf header
	static const Nsf_Emu::header_t base_header =
	{
		{'N','E','S','M','\x1A'},// tag
		1,                  // version
		1, 1,               // track count, first track
		{0,0},{0,0},{0,0},  // addresses
		"","","",           // strings
		{0x1A, 0x41},       // NTSC rate
		{0,0,0,0,0,0,0,0},  // banks
		{0x20, 0x4E},       // PAL rate
		0, 0,               // flags
		{0,0,0,0}           // unused
	};
	Nsf_Emu::header_t& header = info;
	header = base_header;

	// parse tags
	int phase = 0;
	while ( phase != 3 )
	{
		// read size and tag
		byte block_header [2] [4];
		RETURN_ERR( in.read( block_header, sizeof block_header ) );
		blargg_long size = get_le32( block_header [0] );
		blargg_long tag  = get_le32( block_header [1] );

		if ( size <= 0 )
			return "Corrupt file";

		//debug_printf( "tag: %c%c%c%c\n", char(tag), char(tag>>8), char(tag>>16), char(tag>>24) );

		switch ( tag )
		{
			case BLARGG_4CHAR('O','F','N','I'): {
				check( phase == 0 );
				if ( size < 8 )
					return "Corrupt file";

				nsfe_info_t finfo;
				finfo.track_count = 1;
				finfo.first_track = 0;

				RETURN_ERR( in.read( &finfo, min( size, (blargg_long) nsfe_info_size ) ) );
				if ( size > nsfe_info_size )
					RETURN_ERR( in.skip( size - nsfe_info_size ) );
				phase = 1;
				info.speed_flags = finfo.speed_flags;
				info.chip_flags  = finfo.chip_flags;
				info.track_count = finfo.track_count;
				this->actual_track_count_ = finfo.track_count;
				info.first_track = finfo.first_track;
				memcpy( info.load_addr, finfo.load_addr, 2 * 3 );
				break;
			}

			case BLARGG_4CHAR('K','N','A','B'):
				if ( size > (int) sizeof info.banks )
					return "Corrupt file";
				RETURN_ERR( in.read( info.banks, size ) );
				break;

			case BLARGG_4CHAR('h','t','u','a'): {
				blargg_vector<char> chars;
				blargg_vector<const char*> strs;
				RETURN_ERR( read_strs( in, size, chars, strs ) );
				int n = strs.size();

				if ( n > 3 )
					copy_str( strs [3], info.dumper, sizeof info.dumper );

				if ( n > 2 )
					copy_str( strs [2], info.copyright, sizeof info.copyright );

				if ( n > 1 )
					copy_str( strs [1], info.author, sizeof info.author );

				if ( n > 0 )
					copy_str( strs [0], info.game, sizeof info.game );

				break;
			}

			case BLARGG_4CHAR('e','m','i','t'):
				RETURN_ERR( track_times.resize( size / 4 ) );
				RETURN_ERR( in.read( track_times.begin(), track_times.size() * 4 ) );
				break;

			case BLARGG_4CHAR('l','b','l','t'):
				RETURN_ERR( read_strs( in, size, track_name_data, track_names ) );
				break;

			case BLARGG_4CHAR('t','s','l','p'):
				RETURN_ERR( playlist.resize( size ) );
				RETURN_ERR( in.read( &playlist [0], size ) );
				break;

			case BLARGG_4CHAR('A','T','A','D'): {
				check( phase == 1 );
				phase = 2;
				if ( !nsf_emu )
				{
					RETURN_ERR( in.skip( size ) );
				}
				else
				{
					Subset_Reader sub( &in, size ); // limit emu to nsf data
					Remaining_Reader rem( &header, Nsf_Emu::header_size, &sub );
					RETURN_ERR( nsf_emu->load( rem ) );
					check( rem.remain() == 0 );
				}
				break;
			}

			case BLARGG_4CHAR('D','N','E','N'):
				check( phase == 2 );
				phase = 3;
				break;

			default:
				// tags that can be skipped start with a lowercase character
				check( islower( (tag >> 24) & 0xFF ) );
				RETURN_ERR( in.skip( size ) );
				break;
		}
	}

	return 0;
}

blargg_err_t Nsfe_Info::track_info_( track_info_t* out, int track ) const
{
	int remapped = remap_track( track );
	if ( (unsigned) remapped < track_times.size() )
	{
		long length = (int32_t) get_le32( track_times [remapped] );
		if ( length > 0 )
			out->length = length;
	}
	if ( (unsigned) remapped < track_names.size() )
		Gme_File::copy_field_( out->song, track_names [remapped] );

	GME_COPY_FIELD( info, out, game );
	GME_COPY_FIELD( info, out, author );
	GME_COPY_FIELD( info, out, copyright );
	GME_COPY_FIELD( info, out, dumper );
	return 0;
}

Nsfe_Emu::Nsfe_Emu()
{
	loading = false;
	set_type( gme_nsfe_type );
}

Nsfe_Emu::~Nsfe_Emu() { }

void Nsfe_Emu::unload()
{
	if ( !loading )
		info.unload(); // TODO: extremely hacky!
	Nsf_Emu::unload();
}

blargg_err_t Nsfe_Emu::track_info_( track_info_t* out, int track ) const
{
	return info.track_info_( out, track );
}

struct Nsfe_File : Gme_Info_
{
	Nsfe_Info info;

	Nsfe_File() { set_type( gme_nsfe_type ); }

	blargg_err_t load_( Data_Reader& in )
	{
		RETURN_ERR( info.load( in, 0 ) );
		info.disable_playlist( false );
		set_track_count( info.info.track_count );
		return 0;
	}

	blargg_err_t track_info_( track_info_t* out, int track ) const
	{
		return info.track_info_( out, track );
	}
};

static Music_Emu* new_nsfe_emu () { return BLARGG_NEW Nsfe_Emu ; }
static Music_Emu* new_nsfe_file() { return BLARGG_NEW Nsfe_File; }

static gme_type_t_ const gme_nsfe_type_ = { "Nintendo NES", 0, &new_nsfe_emu, &new_nsfe_file, "NSFE", 1 };
BLARGG_EXPORT extern gme_type_t const gme_nsfe_type = &gme_nsfe_type_;

blargg_err_t Nsfe_Emu::load_( Data_Reader& in )
{
	if ( loading )
		return Nsf_Emu::load_( in );

	// TODO: this hacky recursion-avoidance could have subtle problems
	loading = true;
	blargg_err_t err = info.load( in, this );
	loading = false;
	disable_playlist( false );
	return err;
}

void Nsfe_Emu::disable_playlist( bool b )
{
	info.disable_playlist( b );
	set_track_count( info.info.track_count );
}

void Nsfe_Emu::clear_playlist_()
{
	disable_playlist();
	Nsf_Emu::clear_playlist_();
}

blargg_err_t Nsfe_Emu::start_track_( int track )
{
	return Nsf_Emu::start_track_( info.remap_track( track ) );
}
<commit_msg>nsfe: Some blocks can have a 0-sized header, don't fail for those.<commit_after>// Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/

#include "Nsfe_Emu.h"

#include "blargg_endian.h"
#include <string.h>
#include <ctype.h>

/* Copyright (C) 2005-2006 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. This
module is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details. You should have received a copy of the GNU Lesser General Public
License along with this module; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */

#include "blargg_source.h"

Nsfe_Info::Nsfe_Info() { playlist_disabled = false; }

Nsfe_Info::~Nsfe_Info() { }

inline void Nsfe_Info::unload()
{
	track_name_data.clear();
	track_names.clear();
	playlist.clear();
	track_times.clear();
}

// TODO: if no playlist, treat as if there is a playlist that is just 1,2,3,4,5... ?
void Nsfe_Info::disable_playlist( bool b )
{
	playlist_disabled = b;
	info.track_count = playlist.size();
	if ( !info.track_count || playlist_disabled )
		info.track_count = actual_track_count_;
}

int Nsfe_Info::remap_track( int track ) const
{
	if ( !playlist_disabled && (unsigned) track < playlist.size() )
		track = playlist [track];
	return track;
}

// Read multiple strings and separate into individual strings
static blargg_err_t read_strs( Data_Reader& in, long size, blargg_vector<char>& chars,
		blargg_vector<const char*>& strs )
{
	RETURN_ERR( chars.resize( size + 1 ) );
	chars [size] = 0; // in case last string doesn't have terminator
	RETURN_ERR( in.read( &chars [0], size ) );

	RETURN_ERR( strs.resize( 128 ) );
	int count = 0;
	for ( int i = 0; i < size; i++ )
	{
		if ( (int) strs.size() <= count )
			RETURN_ERR( strs.resize( count * 2 ) );
		strs [count++] = &chars [i];
		while ( i < size && chars [i] )
			i++;
	}

	return strs.resize( count );
}

// Copy in to out, where out has out_max characters allocated. Truncate to
// out_max - 1 characters.
static void copy_str( const char* in, char* out, int out_max )
{
	out [out_max - 1] = 0;
	strncpy( out, in, out_max - 1 );
}

struct nsfe_info_t
{
	byte load_addr [2];
	byte init_addr [2];
	byte play_addr [2];
	byte speed_flags;
	byte chip_flags;
	byte track_count;
	byte first_track;
	byte unused [6];
};

blargg_err_t Nsfe_Info::load( Data_Reader& in, Nsf_Emu* nsf_emu )
{
	int const nsfe_info_size = 16;
	assert( offsetof (nsfe_info_t,unused [6]) == nsfe_info_size );

	// check header
	byte signature [4];
	blargg_err_t err = in.read( signature, sizeof signature );
	if ( err )
		return (err == in.eof_error ? gme_wrong_file_type : err);
	if ( memcmp( signature, "NSFE", 4 ) )
		return gme_wrong_file_type;

	// free previous info
	track_name_data.clear();
	track_names.clear();
	playlist.clear();
	track_times.clear();

	// default nsf header
	static const Nsf_Emu::header_t base_header =
	{
		{'N','E','S','M','\x1A'},// tag
		1,                  // version
		1, 1,               // track count, first track
		{0,0},{0,0},{0,0},  // addresses
		"","","",           // strings
		{0x1A, 0x41},       // NTSC rate
		{0,0,0,0,0,0,0,0},  // banks
		{0x20, 0x4E},       // PAL rate
		0, 0,               // flags
		{0,0,0,0}           // unused
	};
	Nsf_Emu::header_t& header = info;
	header = base_header;

	// parse tags
	int phase = 0;
	while ( phase != 3 )
	{
		// read size and tag
		byte block_header [2] [4];
		RETURN_ERR( in.read( block_header, sizeof block_header ) );
		blargg_long size = get_le32( block_header [0] );
		blargg_long tag  = get_le32( block_header [1] );

		if ( size < 0 )
			return "Corrupt file";

		//debug_printf( "tag: %c%c%c%c\n", char(tag), char(tag>>8), char(tag>>16), char(tag>>24) );

		switch ( tag )
		{
			case BLARGG_4CHAR('O','F','N','I'): {
				check( phase == 0 );
				if ( size < 8 )
					return "Corrupt file";

				nsfe_info_t finfo;
				finfo.track_count = 1;
				finfo.first_track = 0;

				RETURN_ERR( in.read( &finfo, min( size, (blargg_long) nsfe_info_size ) ) );
				if ( size > nsfe_info_size )
					RETURN_ERR( in.skip( size - nsfe_info_size ) );
				phase = 1;
				info.speed_flags = finfo.speed_flags;
				info.chip_flags  = finfo.chip_flags;
				info.track_count = finfo.track_count;
				this->actual_track_count_ = finfo.track_count;
				info.first_track = finfo.first_track;
				memcpy( info.load_addr, finfo.load_addr, 2 * 3 );
				break;
			}

			case BLARGG_4CHAR('K','N','A','B'):
				if ( size > (int) sizeof info.banks )
					return "Corrupt file";
				RETURN_ERR( in.read( info.banks, size ) );
				break;

			case BLARGG_4CHAR('h','t','u','a'): {
				blargg_vector<char> chars;
				blargg_vector<const char*> strs;
				RETURN_ERR( read_strs( in, size, chars, strs ) );
				int n = strs.size();

				if ( n > 3 )
					copy_str( strs [3], info.dumper, sizeof info.dumper );

				if ( n > 2 )
					copy_str( strs [2], info.copyright, sizeof info.copyright );

				if ( n > 1 )
					copy_str( strs [1], info.author, sizeof info.author );

				if ( n > 0 )
					copy_str( strs [0], info.game, sizeof info.game );

				break;
			}

			case BLARGG_4CHAR('e','m','i','t'):
				RETURN_ERR( track_times.resize( size / 4 ) );
				RETURN_ERR( in.read( track_times.begin(), track_times.size() * 4 ) );
				break;

			case BLARGG_4CHAR('l','b','l','t'):
				RETURN_ERR( read_strs( in, size, track_name_data, track_names ) );
				break;

			case BLARGG_4CHAR('t','s','l','p'):
				RETURN_ERR( playlist.resize( size ) );
				RETURN_ERR( in.read( &playlist [0], size ) );
				break;

			case BLARGG_4CHAR('A','T','A','D'): {
				check( phase == 1 );
				phase = 2;
				if ( !nsf_emu )
				{
					RETURN_ERR( in.skip( size ) );
				}
				else
				{
					Subset_Reader sub( &in, size ); // limit emu to nsf data
					Remaining_Reader rem( &header, Nsf_Emu::header_size, &sub );
					RETURN_ERR( nsf_emu->load( rem ) );
					check( rem.remain() == 0 );
				}
				break;
			}

			case BLARGG_4CHAR('D','N','E','N'):
				check( phase == 2 );
				phase = 3;
				break;

			default:
				// tags that can be skipped start with a lowercase character
				check( islower( (tag >> 24) & 0xFF ) );
				RETURN_ERR( in.skip( size ) );
				break;
		}
	}

	return 0;
}

blargg_err_t Nsfe_Info::track_info_( track_info_t* out, int track ) const
{
	int remapped = remap_track( track );
	if ( (unsigned) remapped < track_times.size() )
	{
		long length = (int32_t) get_le32( track_times [remapped] );
		if ( length > 0 )
			out->length = length;
	}
	if ( (unsigned) remapped < track_names.size() )
		Gme_File::copy_field_( out->song, track_names [remapped] );

	GME_COPY_FIELD( info, out, game );
	GME_COPY_FIELD( info, out, author );
	GME_COPY_FIELD( info, out, copyright );
	GME_COPY_FIELD( info, out, dumper );
	return 0;
}

Nsfe_Emu::Nsfe_Emu()
{
	loading = false;
	set_type( gme_nsfe_type );
}

Nsfe_Emu::~Nsfe_Emu() { }

void Nsfe_Emu::unload()
{
	if ( !loading )
		info.unload(); // TODO: extremely hacky!
	Nsf_Emu::unload();
}

blargg_err_t Nsfe_Emu::track_info_( track_info_t* out, int track ) const
{
	return info.track_info_( out, track );
}

struct Nsfe_File : Gme_Info_
{
	Nsfe_Info info;

	Nsfe_File() { set_type( gme_nsfe_type ); }

	blargg_err_t load_( Data_Reader& in )
	{
		RETURN_ERR( info.load( in, 0 ) );
		info.disable_playlist( false );
		set_track_count( info.info.track_count );
		return 0;
	}

	blargg_err_t track_info_( track_info_t* out, int track ) const
	{
		return info.track_info_( out, track );
	}
};

static Music_Emu* new_nsfe_emu () { return BLARGG_NEW Nsfe_Emu ; }
static Music_Emu* new_nsfe_file() { return BLARGG_NEW Nsfe_File; }

static gme_type_t_ const gme_nsfe_type_ = { "Nintendo NES", 0, &new_nsfe_emu, &new_nsfe_file, "NSFE", 1 };
BLARGG_EXPORT extern gme_type_t const gme_nsfe_type = &gme_nsfe_type_;

blargg_err_t Nsfe_Emu::load_( Data_Reader& in )
{
	if ( loading )
		return Nsf_Emu::load_( in );

	// TODO: this hacky recursion-avoidance could have subtle problems
	loading = true;
	blargg_err_t err = info.load( in, this );
	loading = false;
	disable_playlist( false );
	return err;
}

void Nsfe_Emu::disable_playlist( bool b )
{
	info.disable_playlist( b );
	set_track_count( info.info.track_count );
}

void Nsfe_Emu::clear_playlist_()
{
	disable_playlist();
	Nsf_Emu::clear_playlist_();
}

blargg_err_t Nsfe_Emu::start_track_( int track )
{
	return Nsf_Emu::start_track_( info.remap_track( track ) );
}
<|endoftext|>


<commit_before>#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <ctype.h>

#include "../hunspell/csutil.hxx"
#include "latexparser.hxx"

#ifndef W32
using namespace std;
#endif

static struct {
	const char * pat[2];
	int arg;
} PATTERN[] = {
	{ { "\\(", "\\)" } , 0 },
	{ { "$$", "$$" } , 0 },
	{ { "$", "$" } , 0 },
	{ { "\\begin{math}", "\\end{math}" } , 0 },
	{ { "\\[", "\\]" } , 0 },
	{ { "\\begin{displaymath}", "\\end{displaymath}" } , 0 },
	{ { "\\begin{equation}", "\\end{equation}" } , 0 },
	{ { "\\begin{equation*}", "\\end{equation*}" } , 0 },
	{ { "\\cite", NULL } , 1 },
	{ { "\\nocite", NULL } , 1 },
	{ { "\\index", NULL } , 1 },
	{ { "\\label", NULL } , 1 },
	{ { "\\ref", NULL } , 1 },
	{ { "\\pageref", NULL } , 1 },
	{ { "\\parbox", NULL } , 1 },
	{ { "\\begin{verbatim}", "\\end{verbatim}" } , 0 },
	{ { "\\verb+", "+" } , 0 },
	{ { "\\verb|", "|" } , 0 },
	{ { "\\verb#", "#" } , 0 },
	{ { "\\verb*", "*" } , 0 },
	{ { "\\documentstyle", "\\begin{document}" } , 0 },
	{ { "\\documentclass", "\\begin{document}" } , 0 },
//	{ { "\\documentclass", NULL } , 1 },
	{ { "\\usepackage", NULL } , 1 },
	{ { "\\includeonly", NULL } , 1 },
	{ { "\\include", NULL } , 1 },
	{ { "\\input", NULL } , 1 },
	{ { "\\vspace", NULL } , 1 },
	{ { "\\setlength", NULL } , 2 },
	{ { "\\addtolength", NULL } , 2 },
	{ { "\\settowidth", NULL } , 2 },
	{ { "\\rule", NULL } , 2 },
	{ { "\\hspace", NULL } , 1 } ,
	{ { "\\vspace", NULL } , 1 } ,
	{ { "\\\\[", "]" } , 0 },
	{ { "\\pagebreak[", "]" } , 0 } ,
	{ { "\\nopagebreak[", "]" } , 0 } ,
	{ { "\\enlargethispage", NULL } , 1 } ,
	{ { "\\begin{tabular}", NULL } , 1 } ,
	{ { "\\addcontentsline", NULL } , 2 } ,
	{ { "\\begin{thebibliography}", NULL } , 1 } ,
	{ { "\\bibliography", NULL } , 1 } ,
	{ { "\\bibliographystyle", NULL } , 1 } ,
	{ { "\\bibitem", NULL } , 1 } ,
	{ { "\\begin", NULL } , 1 } ,
	{ { "\\end", NULL } , 1 } ,
	{ { "\\pagestyle", NULL } , 1 } ,
	{ { "\\pagenumbering", NULL } , 1 } ,
	{ { "\\thispagestyle", NULL } , 1 } ,
	{ { "\\newtheorem", NULL } , 2 },
	{ { "\\newcommand", NULL } , 2 },
	{ { "\\renewcommand", NULL } , 2 },
	{ { "\\setcounter", NULL } , 2 },
	{ { "\\addtocounter", NULL } , 1 },
	{ { "\\stepcounter", NULL } , 1 },
	{ { "\\selectlanguage", NULL } , 1 },
	{ { "\\inputencoding", NULL } , 1 },
	{ { "\\hyphenation", NULL } , 1 },
	{ { "\\definecolor", NULL } , 3 },
	{ { "\\color", NULL } , 1 },
	{ { "\\textcolor", NULL } , 1 },
	{ { "\\pagecolor", NULL } , 1 },
	{ { "\\colorbox", NULL } , 2 },
	{ { "\\fcolorbox", NULL } , 2 },
	{ { "\\declaregraphicsextensions", NULL } , 1 },
	{ { "\\psfig", NULL } , 1 },
	{ { "\\url", NULL } , 1 },
	{ { "\\eqref", NULL } , 1 },
	{ { "\\vskip", NULL } , 1 },
	{ { "\\vglue", NULL } , 1 },
	{ { "\'\'", NULL } , 1 }
};

#define PATTERN_LEN (sizeof(PATTERN) / sizeof(PATTERN[0]))

LaTeXParser::LaTeXParser(const char * wordchars)
{
	init(wordchars);
}

LaTeXParser::LaTeXParser(unsigned short * wordchars, int len)
{
	init(wordchars, len);
}

LaTeXParser::~LaTeXParser()
{
}

int LaTeXParser::look_pattern(int col)
{
	for (unsigned int i = 0; i < PATTERN_LEN; i++) {
		char * j = line[actual] + head;
		const char * k = PATTERN[i].pat[col];
		if (! k) continue;
		while ((*k != '\0') && (tolower(*j) == *k)) {
			j++;
			k++;
		}
		if (*k == '\0') return i;
	}
	return -1;
}

/*
 * LaTeXParser
 *
 * state 0: not wordchar
 * state 1: wordchar
 * state 2: comments
 * state 3: commands
 * state 4: commands with arguments
 * state 5: % comment
 *
 */

char * LaTeXParser::next_token()
{
	int i;
	int slash = 0;
	int apostrophe;
	for (;;) {
		// fprintf(stderr,"depth: %d, state: %d, , arg: %d, token: %s\n",depth,state,arg,line[actual]+head);

		switch (state)
		{
		case 0: // non word chars
			if ((pattern_num = look_pattern(0)) != -1) {
				if (PATTERN[pattern_num].pat[1]) {
					state = 2;
				} else {
					state = 4;
					depth = 0;
					arg = 0;
					opt = 1;
				}
				head += strlen(PATTERN[pattern_num].pat[0]) - 1;
			} else if (line[actual][head] == '%') {
					state = 5;
			} else if (is_wordchar(line[actual] + head)) {
				state = 1;
				token = head;
			} else if (line[actual][head] == '\\') {
				if (line[actual][head + 1] == '\\' ||  // \\ (linebreak)
					(line[actual][head + 1] == '$') || // \$ (dollar sign)
					(line[actual][head + 1] == '%')) { // \% (percent)
					head++;
					break;
				}
				state = 3;
			} else if (line[actual][head] == '%') {
				if ((head==0) || (line[actual][head - 1] != '\\')) state = 5;
			}
			break;
		case 1: // wordchar
			apostrophe = 0;
			if (! is_wordchar(line[actual] + head) ||
			  (line[actual][head] == '\'' && line[actual][head+1] == '\'' && ++apostrophe)) {
				state = 0;
				char * t = alloc_token(token, &head);
				if (apostrophe) head += 2;
				if (t) return t;
			}
			break;
		case 2: // comment, labels, etc
			if (((i = look_pattern(1)) != -1) &&
				(strcmp(PATTERN[i].pat[1],PATTERN[pattern_num].pat[1]) == 0)) {
					state = 0;
					head += strlen(PATTERN[pattern_num].pat[1]) - 1;
			}
			break;
		case 3: // command
			if ((tolower(line[actual][head]) < 'a') || (tolower(line[actual][head]) > 'z')) {
				state = 0;
				head--;
			}
			break;
		case 4: // command with arguments
			if (slash && (line[actual][head] != '\0')) {
				slash = 0;
				head++;
				break;
			} else if (line[actual][head]=='\\') {
				slash = 1;
			} else if ((line[actual][head] == '{') ||
				((opt) && (line[actual][head] == '['))) {
					depth++;
					opt = 0;
			} else if (line[actual][head] == '}') {
				depth--;
				if (depth == 0) {
					opt = 1;
					arg++;
				}
				if (((depth == 0) && (arg == PATTERN[pattern_num].arg)) ||
					(depth < 0) ) {
						state = 0; // XXX not handles the last optional arg.
				}
			} else if (line[actual][head] == ']') depth--;
		} // case
                if (next_char(line[actual], &head)) {
			if (state == 5) state = 0;
			return NULL;
		}
	}
}
<commit_msg>coverity#17929 Uninitialized scalar field<commit_after>#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <ctype.h>

#include "../hunspell/csutil.hxx"
#include "latexparser.hxx"

#ifndef W32
using namespace std;
#endif

static struct {
	const char * pat[2];
	int arg;
} PATTERN[] = {
	{ { "\\(", "\\)" } , 0 },
	{ { "$$", "$$" } , 0 },
	{ { "$", "$" } , 0 },
	{ { "\\begin{math}", "\\end{math}" } , 0 },
	{ { "\\[", "\\]" } , 0 },
	{ { "\\begin{displaymath}", "\\end{displaymath}" } , 0 },
	{ { "\\begin{equation}", "\\end{equation}" } , 0 },
	{ { "\\begin{equation*}", "\\end{equation*}" } , 0 },
	{ { "\\cite", NULL } , 1 },
	{ { "\\nocite", NULL } , 1 },
	{ { "\\index", NULL } , 1 },
	{ { "\\label", NULL } , 1 },
	{ { "\\ref", NULL } , 1 },
	{ { "\\pageref", NULL } , 1 },
	{ { "\\parbox", NULL } , 1 },
	{ { "\\begin{verbatim}", "\\end{verbatim}" } , 0 },
	{ { "\\verb+", "+" } , 0 },
	{ { "\\verb|", "|" } , 0 },
	{ { "\\verb#", "#" } , 0 },
	{ { "\\verb*", "*" } , 0 },
	{ { "\\documentstyle", "\\begin{document}" } , 0 },
	{ { "\\documentclass", "\\begin{document}" } , 0 },
//	{ { "\\documentclass", NULL } , 1 },
	{ { "\\usepackage", NULL } , 1 },
	{ { "\\includeonly", NULL } , 1 },
	{ { "\\include", NULL } , 1 },
	{ { "\\input", NULL } , 1 },
	{ { "\\vspace", NULL } , 1 },
	{ { "\\setlength", NULL } , 2 },
	{ { "\\addtolength", NULL } , 2 },
	{ { "\\settowidth", NULL } , 2 },
	{ { "\\rule", NULL } , 2 },
	{ { "\\hspace", NULL } , 1 } ,
	{ { "\\vspace", NULL } , 1 } ,
	{ { "\\\\[", "]" } , 0 },
	{ { "\\pagebreak[", "]" } , 0 } ,
	{ { "\\nopagebreak[", "]" } , 0 } ,
	{ { "\\enlargethispage", NULL } , 1 } ,
	{ { "\\begin{tabular}", NULL } , 1 } ,
	{ { "\\addcontentsline", NULL } , 2 } ,
	{ { "\\begin{thebibliography}", NULL } , 1 } ,
	{ { "\\bibliography", NULL } , 1 } ,
	{ { "\\bibliographystyle", NULL } , 1 } ,
	{ { "\\bibitem", NULL } , 1 } ,
	{ { "\\begin", NULL } , 1 } ,
	{ { "\\end", NULL } , 1 } ,
	{ { "\\pagestyle", NULL } , 1 } ,
	{ { "\\pagenumbering", NULL } , 1 } ,
	{ { "\\thispagestyle", NULL } , 1 } ,
	{ { "\\newtheorem", NULL } , 2 },
	{ { "\\newcommand", NULL } , 2 },
	{ { "\\renewcommand", NULL } , 2 },
	{ { "\\setcounter", NULL } , 2 },
	{ { "\\addtocounter", NULL } , 1 },
	{ { "\\stepcounter", NULL } , 1 },
	{ { "\\selectlanguage", NULL } , 1 },
	{ { "\\inputencoding", NULL } , 1 },
	{ { "\\hyphenation", NULL } , 1 },
	{ { "\\definecolor", NULL } , 3 },
	{ { "\\color", NULL } , 1 },
	{ { "\\textcolor", NULL } , 1 },
	{ { "\\pagecolor", NULL } , 1 },
	{ { "\\colorbox", NULL } , 2 },
	{ { "\\fcolorbox", NULL } , 2 },
	{ { "\\declaregraphicsextensions", NULL } , 1 },
	{ { "\\psfig", NULL } , 1 },
	{ { "\\url", NULL } , 1 },
	{ { "\\eqref", NULL } , 1 },
	{ { "\\vskip", NULL } , 1 },
	{ { "\\vglue", NULL } , 1 },
	{ { "\'\'", NULL } , 1 }
};

#define PATTERN_LEN (sizeof(PATTERN) / sizeof(PATTERN[0]))

LaTeXParser::LaTeXParser(const char * wordchars)
    : pattern_num(0)
    , depth(0)
    , arg(0)
    , opt(0)
{
	init(wordchars);
}

LaTeXParser::LaTeXParser(unsigned short * wordchars, int len)
    : pattern_num(0)
    , depth(0)
    , arg(0)
    , opt(0)
{
	init(wordchars, len);
}

LaTeXParser::~LaTeXParser()
{
}

int LaTeXParser::look_pattern(int col)
{
	for (unsigned int i = 0; i < PATTERN_LEN; i++) {
		char * j = line[actual] + head;
		const char * k = PATTERN[i].pat[col];
		if (! k) continue;
		while ((*k != '\0') && (tolower(*j) == *k)) {
			j++;
			k++;
		}
		if (*k == '\0') return i;
	}
	return -1;
}

/*
 * LaTeXParser
 *
 * state 0: not wordchar
 * state 1: wordchar
 * state 2: comments
 * state 3: commands
 * state 4: commands with arguments
 * state 5: % comment
 *
 */

char * LaTeXParser::next_token()
{
	int i;
	int slash = 0;
	int apostrophe;
	for (;;) {
		// fprintf(stderr,"depth: %d, state: %d, , arg: %d, token: %s\n",depth,state,arg,line[actual]+head);

		switch (state)
		{
		case 0: // non word chars
			if ((pattern_num = look_pattern(0)) != -1) {
				if (PATTERN[pattern_num].pat[1]) {
					state = 2;
				} else {
					state = 4;
					depth = 0;
					arg = 0;
					opt = 1;
				}
				head += strlen(PATTERN[pattern_num].pat[0]) - 1;
			} else if (line[actual][head] == '%') {
					state = 5;
			} else if (is_wordchar(line[actual] + head)) {
				state = 1;
				token = head;
			} else if (line[actual][head] == '\\') {
				if (line[actual][head + 1] == '\\' ||  // \\ (linebreak)
					(line[actual][head + 1] == '$') || // \$ (dollar sign)
					(line[actual][head + 1] == '%')) { // \% (percent)
					head++;
					break;
				}
				state = 3;
			} else if (line[actual][head] == '%') {
				if ((head==0) || (line[actual][head - 1] != '\\')) state = 5;
			}
			break;
		case 1: // wordchar
			apostrophe = 0;
			if (! is_wordchar(line[actual] + head) ||
			  (line[actual][head] == '\'' && line[actual][head+1] == '\'' && ++apostrophe)) {
				state = 0;
				char * t = alloc_token(token, &head);
				if (apostrophe) head += 2;
				if (t) return t;
			}
			break;
		case 2: // comment, labels, etc
			if (((i = look_pattern(1)) != -1) &&
				(strcmp(PATTERN[i].pat[1],PATTERN[pattern_num].pat[1]) == 0)) {
					state = 0;
					head += strlen(PATTERN[pattern_num].pat[1]) - 1;
			}
			break;
		case 3: // command
			if ((tolower(line[actual][head]) < 'a') || (tolower(line[actual][head]) > 'z')) {
				state = 0;
				head--;
			}
			break;
		case 4: // command with arguments
			if (slash && (line[actual][head] != '\0')) {
				slash = 0;
				head++;
				break;
			} else if (line[actual][head]=='\\') {
				slash = 1;
			} else if ((line[actual][head] == '{') ||
				((opt) && (line[actual][head] == '['))) {
					depth++;
					opt = 0;
			} else if (line[actual][head] == '}') {
				depth--;
				if (depth == 0) {
					opt = 1;
					arg++;
				}
				if (((depth == 0) && (arg == PATTERN[pattern_num].arg)) ||
					(depth < 0) ) {
						state = 0; // XXX not handles the last optional arg.
				}
			} else if (line[actual][head] == ']') depth--;
		} // case
                if (next_char(line[actual], &head)) {
			if (state == 5) state = 0;
			return NULL;
		}
	}
}
<|endoftext|>


<commit_before>#include "surfacefeaturesextractor.h"
#include <vtkDoubleArray.h>
#include <sstream>
#include <vtkObjectFactory.h>

#if !defined(M_PI)
#define M_PI 3.14159265358979323846264338327950288   /* pi */
#endif

vtkStandardNewMacro(SurfaceFeaturesExtractor);

/**
* Constructor SurfaceFeaturesExtractor()
*/
SurfaceFeaturesExtractor::SurfaceFeaturesExtractor(){
	this->inputSurface = vtkSmartPointer<vtkPolyData>::New();
	this->outputSurface = vtkSmartPointer<vtkPolyData>::New();

	this->intermediateSurface = vtkSmartPointer<vtkPolyData>::New();
}

/**
* Destructor SurfaceFeaturesExtractor()
*/
SurfaceFeaturesExtractor::~SurfaceFeaturesExtractor(){}

/**
* Function SetInput() for SurfaceFeaturesExtractor
*/
void SurfaceFeaturesExtractor::SetInput(vtkSmartPointer<vtkPolyData> input, std::vector< vtkSmartPointer<vtkPolyData> > list, std::vector<std::string> landmarkFile)
{
	this->meanShapesList = list;
	this->inputSurface = input;
	this->landmarkFile = landmarkFile;
}

/**
 * Function init_output() for SurfaceFeaturesExtractor
 */
void SurfaceFeaturesExtractor::init_output()
{
	this->intermediateSurface = this->inputSurface;
	this->outputSurface = this->inputSurface;
}

/**
 * Function compute_normals()
 */
void SurfaceFeaturesExtractor::compute_normals()
{
	vtkSmartPointer<vtkPolyDataNormals> NormalFilter = vtkSmartPointer<vtkPolyDataNormals>::New();
	NormalFilter->SetInputData(this->intermediateSurface);

	NormalFilter->ComputePointNormalsOn();
    NormalFilter->ComputeCellNormalsOff();
    NormalFilter->SetFlipNormals(0);
    NormalFilter->SplittingOff();
	NormalFilter->FlipNormalsOff();
	NormalFilter->ConsistencyOff();

	NormalFilter->Update();
	this->intermediateSurface = NormalFilter->GetOutput();
}

/**
 * Function compute_positions()
 */
void SurfaceFeaturesExtractor::compute_positions()
{
    std::string name = "Position";
    int nbPoints = this->intermediateSurface->GetNumberOfPoints();

	vtkSmartPointer<vtkFloatArray> position = vtkSmartPointer<vtkFloatArray>::New();
	position->SetNumberOfComponents(3);
	position->SetName(name.c_str());

	for(int i=0; i<nbPoints; i++)
	{
		double* p = new double[3];
		p = this->intermediateSurface->GetPoint(i);

		position->InsertNextTuple3(p[0],p[1],p[2]);

	}

	this->intermediateSurface->GetPointData()->SetActiveVectors(name.c_str());
	this->intermediateSurface->GetPointData()->SetVectors(position);

}

/**
 * Function compute_distances()
 */
void SurfaceFeaturesExtractor::compute_distances()
{
	int nbPoints = this->intermediateSurface->GetNumberOfPoints();

	// Load each mean groupe shape & create labels
	std::vector<std::string> meanDistLabels;
	for (size_t k=0; k<this->meanShapesList.size(); k++)
	{
		std::ostringstream k_temp;
    	k_temp << k;
    	std::string k_char = k_temp.str();
		// std::string k_char = static_cast<std::ostringstream*>( &( std::ostringstream() << k) )->str();
		meanDistLabels.push_back("distanceGroup"+k_char);
	}
	//for (int k=0; k<this->meanShapesList.size(); k++)
	//	std::cout<<meanDistLabels[k]<<std::endl;

	for(size_t k=0; k<meanShapesList.size(); k++)
	{
		vtkSmartPointer<vtkFloatArray> meanDistance = vtkSmartPointer<vtkFloatArray>::New() ;
		meanDistance->SetName(meanDistLabels[k].c_str());

		for (int i=0; i<nbPoints; i++)
		{
			double* p1 = new double[3];
			p1 = this->intermediateSurface->GetPoint(i);

			double* p2 = new double[3];
			p2 = meanShapesList[k]->GetPoint(i);

			double dist = sqrt( (p1[0]-p2[0])*(p1[0]-p2[0]) + (p1[1]-p2[1])*(p1[1]-p2[1]) + (p1[2]-p2[2])*(p1[2]-p2[2]) );

			meanDistance->InsertNextTuple1(dist);

			this->intermediateSurface->GetPointData()->SetActiveScalars(meanDistLabels[k].c_str());
			this->intermediateSurface->GetPointData()->SetScalars(meanDistance);

		}
	}
}

void SurfaceFeaturesExtractor::compute_maxcurvatures()		// Kappa2
{
	vtkSmartPointer<vtkCurvatures> curvaturesFilter = vtkSmartPointer<vtkCurvatures>::New();

	curvaturesFilter->SetInputDataObject(this->intermediateSurface);
	curvaturesFilter->SetCurvatureTypeToMaximum();
	curvaturesFilter->Update();

	this->intermediateSurface = curvaturesFilter->GetOutput();
}
void SurfaceFeaturesExtractor::compute_mincurvatures()		// Kappa1
{
	vtkSmartPointer<vtkCurvatures> curvaturesFilter = vtkSmartPointer<vtkCurvatures>::New();

	curvaturesFilter->SetInputDataObject(this->intermediateSurface);
	curvaturesFilter->SetCurvatureTypeToMinimum();
	curvaturesFilter->Update();

	this->intermediateSurface = curvaturesFilter->GetOutput();
}
void SurfaceFeaturesExtractor::compute_gaussiancurvatures()	// G
{
	vtkSmartPointer<vtkCurvatures> curvaturesFilter = vtkSmartPointer<vtkCurvatures>::New();

	curvaturesFilter->SetInputDataObject(this->intermediateSurface);
	curvaturesFilter->SetCurvatureTypeToGaussian();
	curvaturesFilter->Update();

	this->intermediateSurface = curvaturesFilter->GetOutput();
}
void SurfaceFeaturesExtractor::compute_meancurvatures()		// H
{
	vtkSmartPointer<vtkCurvatures> curvaturesFilter = vtkSmartPointer<vtkCurvatures>::New();

	curvaturesFilter->SetInputDataObject(this->intermediateSurface);
	curvaturesFilter->SetCurvatureTypeToMean();
	curvaturesFilter->Update();

	this->intermediateSurface = curvaturesFilter->GetOutput();
}

void SurfaceFeaturesExtractor::compute_shapeindex()			// S
{
	// std::cout<<" :: Function compute_shapeindex"<<std::endl;

	int nbPoints = this->intermediateSurface->GetNumberOfPoints();

	vtkSmartPointer<vtkFloatArray> shapeIndexArray = vtkSmartPointer<vtkFloatArray>::New() ;

	// vtkDataArray* minCurvArray = this->intermediateSurface->GetPointData()->GetScalars("Minimum_Curvature");
	// vtkDataArray* maxCurvArray = this->intermediateSurface->GetPointData()->GetScalars("Maximum_Curvature");

	vtkSmartPointer<vtkDataArray> minCurvArray = this->intermediateSurface->GetPointData()->GetScalars("Minimum_Curvature");
	vtkSmartPointer<vtkDataArray> maxCurvArray = this->intermediateSurface->GetPointData()->GetScalars("Maximum_Curvature");

	shapeIndexArray->SetName("Shape_Index");

	for (int i=0; i<nbPoints; i++)
	{
		double k1 = minCurvArray->GetTuple1(i);
		double k2 = maxCurvArray->GetTuple1(i);

		double value = (2 / M_PI) * (atan( (k2 + k1) / (k2 - k1) ) );
		if( value != value )
        	value = 0;

		shapeIndexArray->InsertNextTuple1(value);
	}

	this->intermediateSurface->GetPointData()->SetActiveScalars("Shape_Index");
	this->intermediateSurface->GetPointData()->SetScalars(shapeIndexArray);
}

void SurfaceFeaturesExtractor::compute_curvedness()			// C
{
	// std::cout<<" :: Function compute_curvedness"<<std::endl;

	int nbPoints = this->intermediateSurface->GetNumberOfPoints();

	vtkSmartPointer<vtkFloatArray> curvednessArray = vtkSmartPointer<vtkFloatArray>::New() ;

	// vtkDataArray* minCurvArray = this->intermediateSurface->GetPointData()->GetScalars("Minimum_Curvature");
	// vtkDataArray* maxCurvArray = this->intermediateSurface->GetPointData()->GetScalars("Maximum_Curvature");

	vtkSmartPointer<vtkDataArray> minCurvArray = this->intermediateSurface->GetPointData()->GetScalars("Minimum_Curvature");
	vtkSmartPointer<vtkDataArray> maxCurvArray = this->intermediateSurface->GetPointData()->GetScalars("Maximum_Curvature");

	curvednessArray->SetName("Curvedness");

	for (int i=0; i<nbPoints; i++)
	{
		double k1 = minCurvArray->GetTuple1(i);
		double k2 = maxCurvArray->GetTuple1(i);

		double value = sqrt( (pow(k1, 2) + pow(k2, 2) ) / 2);

		curvednessArray->InsertNextTuple1(value);

		this->intermediateSurface->GetPointData()->SetActiveScalars("Curvedness");
		this->intermediateSurface->GetPointData()->SetScalars(curvednessArray);
	}

}

void SurfaceFeaturesExtractor::scalar_indexPoint()
{
	int nbPoints = this->intermediateSurface->GetNumberOfPoints();

	vtkSmartPointer<vtkFloatArray> indexPointArray = vtkSmartPointer<vtkFloatArray>::New() ;

	indexPointArray->SetName("Index_Points");

	for (int i=0; i<nbPoints; i++)
	{
		indexPointArray->InsertNextTuple1(i);

		this->intermediateSurface->GetPointData()->SetActiveScalars("Index_Points");
		this->intermediateSurface->GetPointData()->SetScalars(indexPointArray);
	}
}

void SurfaceFeaturesExtractor::store_landmarks_vtk()
{
	//std::cout << " Functions store landmarks_vtk " << std::endl;

	// Build a locator
	vtkSmartPointer<vtkPointLocator> pointLocator = vtkPointLocator::New();
	pointLocator->SetDataSet(this->intermediateSurface);
	pointLocator->BuildLocator();

	// ---------- Reading FCSV file ----------

	#define NB_LINES 250
	#define NB_WORDS 250

	// Get the Surface filename from the command line
	std::fstream fcsvfile(this->landmarkFile[0].c_str());
	std::string line, mot;
	std::string words[NB_LINES][NB_WORDS]; // !!!! WARNING DEFINE AND TO PROTECT IF SUPERIOR TO 20
	int i,j;
	int* landmarkPids;
	int NbLandmarks;

	if(fcsvfile)
	{
		getline(fcsvfile, line);
		fcsvfile>>mot;
		while(mot=="#")
		{
			if(getline(fcsvfile, line))
				fcsvfile>>mot;
			else
				mot="#";
		}

		i=0;
		do
		{
			std::size_t pos_end, pos1;
			j=0;
			do
			{
				std::size_t pos0 = 0;
				pos1 = mot.find(',');
				pos_end = mot.find(",,");
				words[i][j] = mot.substr(pos0, pos1-pos0);
				mot = mot.substr(pos1+1);
				j++;
			}
			while(pos1+1<pos_end);
			i++;
		}
		while(fcsvfile>>mot);

		NbLandmarks = i;
		landmarkPids = new int[NbLandmarks];

		for (int i = 0; i < NbLandmarks; ++i)
		{
			double x = atof(words[i][1].c_str());
			double y = atof(words[i][2].c_str());
			double z = atof(words[i][3].c_str());

            // Find closest point
            vtkIdType ptId;
            double p[] = {0.0, 0.0, 0.0};
            p[0] = x; p[1] = y; p[2] = z;
            ptId = pointLocator->FindClosestPoint(p);
            landmarkPids[i] = ptId;

		// std::cout << "landmark " << i << " position " << x << "," << y << "," << z << " and the corresponding Pid is " << landmarkPids[i] << std::endl;
		}
	}
	else
		std::cout<<"Error !";

	// ---------- Encode landmarks in  FCSV file ----------
	vtkSmartPointer<vtkDoubleArray> landmarksArray = vtkSmartPointer<vtkDoubleArray>::New();
	landmarksArray->SetName("Landmarks");
	landmarksArray->SetNumberOfComponents(1);

	for(int ID = 0; ID < this->intermediateSurface->GetNumberOfPoints(); ID++)
	{
		double exists = 0.0;
		for (int i = 0; i < NbLandmarks; ++i)
		{
			double diff = landmarkPids[i] - ID;
			if (diff == 0)
			{
				exists = i+1;
				//std::cout << "Landmark ID " << exists << std::endl;
				break;
			}
		}
		landmarksArray->InsertNextValue(exists);
	}
	landmarksArray->Resize(this->intermediateSurface->GetNumberOfPoints());
	this->intermediateSurface->GetPointData()->AddArray(landmarksArray);

	//delete[] landmarkPids;

}

/**
 * Function Update()
 */
void SurfaceFeaturesExtractor::Update()
{
	this->init_output();

	// Compute normal for each vertex
	this->compute_normals();

	// Compute position of each point
	this->compute_positions();

	// Compute distance to each mean groups
	if (this->meanShapesList.size() > 0)
		this->compute_distances();

	// Compute curvatures at each point
	this->compute_maxcurvatures();
	this->compute_mincurvatures();
	this->compute_gaussiancurvatures();
	this->compute_meancurvatures();

	// Shape Index and Curvedness
	this->compute_shapeindex();
	this->compute_curvedness();

	// this->scalar_indexPoint();

	if (this->landmarkFile.size() == 1)
		this->store_landmarks_vtk();

	this->outputSurface = this->intermediateSurface;
}

/**
 * Function GetOutput()
 */
vtkSmartPointer<vtkPolyData> SurfaceFeaturesExtractor::GetOutput()
{
	return this->outputSurface;
}

<commit_msg>COMP: Fix -Wmaybe-uninitialized warnings in SurfaceFeaturesExtractor CLI<commit_after>#include "surfacefeaturesextractor.h"
#include <vtkDoubleArray.h>
#include <sstream>
#include <vtkObjectFactory.h>

#if !defined(M_PI)
#define M_PI 3.14159265358979323846264338327950288   /* pi */
#endif

vtkStandardNewMacro(SurfaceFeaturesExtractor);

/**
* Constructor SurfaceFeaturesExtractor()
*/
SurfaceFeaturesExtractor::SurfaceFeaturesExtractor(){
	this->inputSurface = vtkSmartPointer<vtkPolyData>::New();
	this->outputSurface = vtkSmartPointer<vtkPolyData>::New();

	this->intermediateSurface = vtkSmartPointer<vtkPolyData>::New();
}

/**
* Destructor SurfaceFeaturesExtractor()
*/
SurfaceFeaturesExtractor::~SurfaceFeaturesExtractor(){}

/**
* Function SetInput() for SurfaceFeaturesExtractor
*/
void SurfaceFeaturesExtractor::SetInput(vtkSmartPointer<vtkPolyData> input, std::vector< vtkSmartPointer<vtkPolyData> > list, std::vector<std::string> landmarkFile)
{
	this->meanShapesList = list;
	this->inputSurface = input;
	this->landmarkFile = landmarkFile;
}

/**
 * Function init_output() for SurfaceFeaturesExtractor
 */
void SurfaceFeaturesExtractor::init_output()
{
	this->intermediateSurface = this->inputSurface;
	this->outputSurface = this->inputSurface;
}

/**
 * Function compute_normals()
 */
void SurfaceFeaturesExtractor::compute_normals()
{
	vtkSmartPointer<vtkPolyDataNormals> NormalFilter = vtkSmartPointer<vtkPolyDataNormals>::New();
	NormalFilter->SetInputData(this->intermediateSurface);

	NormalFilter->ComputePointNormalsOn();
    NormalFilter->ComputeCellNormalsOff();
    NormalFilter->SetFlipNormals(0);
    NormalFilter->SplittingOff();
	NormalFilter->FlipNormalsOff();
	NormalFilter->ConsistencyOff();

	NormalFilter->Update();
	this->intermediateSurface = NormalFilter->GetOutput();
}

/**
 * Function compute_positions()
 */
void SurfaceFeaturesExtractor::compute_positions()
{
    std::string name = "Position";
    int nbPoints = this->intermediateSurface->GetNumberOfPoints();

	vtkSmartPointer<vtkFloatArray> position = vtkSmartPointer<vtkFloatArray>::New();
	position->SetNumberOfComponents(3);
	position->SetName(name.c_str());

	for(int i=0; i<nbPoints; i++)
	{
		double* p = new double[3];
		p = this->intermediateSurface->GetPoint(i);

		position->InsertNextTuple3(p[0],p[1],p[2]);

	}

	this->intermediateSurface->GetPointData()->SetActiveVectors(name.c_str());
	this->intermediateSurface->GetPointData()->SetVectors(position);

}

/**
 * Function compute_distances()
 */
void SurfaceFeaturesExtractor::compute_distances()
{
	int nbPoints = this->intermediateSurface->GetNumberOfPoints();

	// Load each mean groupe shape & create labels
	std::vector<std::string> meanDistLabels;
	for (size_t k=0; k<this->meanShapesList.size(); k++)
	{
		std::ostringstream k_temp;
    	k_temp << k;
    	std::string k_char = k_temp.str();
		// std::string k_char = static_cast<std::ostringstream*>( &( std::ostringstream() << k) )->str();
		meanDistLabels.push_back("distanceGroup"+k_char);
	}
	//for (int k=0; k<this->meanShapesList.size(); k++)
	//	std::cout<<meanDistLabels[k]<<std::endl;

	for(size_t k=0; k<meanShapesList.size(); k++)
	{
		vtkSmartPointer<vtkFloatArray> meanDistance = vtkSmartPointer<vtkFloatArray>::New() ;
		meanDistance->SetName(meanDistLabels[k].c_str());

		for (int i=0; i<nbPoints; i++)
		{
			double* p1 = new double[3];
			p1 = this->intermediateSurface->GetPoint(i);

			double* p2 = new double[3];
			p2 = meanShapesList[k]->GetPoint(i);

			double dist = sqrt( (p1[0]-p2[0])*(p1[0]-p2[0]) + (p1[1]-p2[1])*(p1[1]-p2[1]) + (p1[2]-p2[2])*(p1[2]-p2[2]) );

			meanDistance->InsertNextTuple1(dist);

			this->intermediateSurface->GetPointData()->SetActiveScalars(meanDistLabels[k].c_str());
			this->intermediateSurface->GetPointData()->SetScalars(meanDistance);

		}
	}
}

void SurfaceFeaturesExtractor::compute_maxcurvatures()		// Kappa2
{
	vtkSmartPointer<vtkCurvatures> curvaturesFilter = vtkSmartPointer<vtkCurvatures>::New();

	curvaturesFilter->SetInputDataObject(this->intermediateSurface);
	curvaturesFilter->SetCurvatureTypeToMaximum();
	curvaturesFilter->Update();

	this->intermediateSurface = curvaturesFilter->GetOutput();
}
void SurfaceFeaturesExtractor::compute_mincurvatures()		// Kappa1
{
	vtkSmartPointer<vtkCurvatures> curvaturesFilter = vtkSmartPointer<vtkCurvatures>::New();

	curvaturesFilter->SetInputDataObject(this->intermediateSurface);
	curvaturesFilter->SetCurvatureTypeToMinimum();
	curvaturesFilter->Update();

	this->intermediateSurface = curvaturesFilter->GetOutput();
}
void SurfaceFeaturesExtractor::compute_gaussiancurvatures()	// G
{
	vtkSmartPointer<vtkCurvatures> curvaturesFilter = vtkSmartPointer<vtkCurvatures>::New();

	curvaturesFilter->SetInputDataObject(this->intermediateSurface);
	curvaturesFilter->SetCurvatureTypeToGaussian();
	curvaturesFilter->Update();

	this->intermediateSurface = curvaturesFilter->GetOutput();
}
void SurfaceFeaturesExtractor::compute_meancurvatures()		// H
{
	vtkSmartPointer<vtkCurvatures> curvaturesFilter = vtkSmartPointer<vtkCurvatures>::New();

	curvaturesFilter->SetInputDataObject(this->intermediateSurface);
	curvaturesFilter->SetCurvatureTypeToMean();
	curvaturesFilter->Update();

	this->intermediateSurface = curvaturesFilter->GetOutput();
}

void SurfaceFeaturesExtractor::compute_shapeindex()			// S
{
	// std::cout<<" :: Function compute_shapeindex"<<std::endl;

	int nbPoints = this->intermediateSurface->GetNumberOfPoints();

	vtkSmartPointer<vtkFloatArray> shapeIndexArray = vtkSmartPointer<vtkFloatArray>::New() ;

	// vtkDataArray* minCurvArray = this->intermediateSurface->GetPointData()->GetScalars("Minimum_Curvature");
	// vtkDataArray* maxCurvArray = this->intermediateSurface->GetPointData()->GetScalars("Maximum_Curvature");

	vtkSmartPointer<vtkDataArray> minCurvArray = this->intermediateSurface->GetPointData()->GetScalars("Minimum_Curvature");
	vtkSmartPointer<vtkDataArray> maxCurvArray = this->intermediateSurface->GetPointData()->GetScalars("Maximum_Curvature");

	shapeIndexArray->SetName("Shape_Index");

	for (int i=0; i<nbPoints; i++)
	{
		double k1 = minCurvArray->GetTuple1(i);
		double k2 = maxCurvArray->GetTuple1(i);

		double value = (2 / M_PI) * (atan( (k2 + k1) / (k2 - k1) ) );
		if( value != value )
        	value = 0;

		shapeIndexArray->InsertNextTuple1(value);
	}

	this->intermediateSurface->GetPointData()->SetActiveScalars("Shape_Index");
	this->intermediateSurface->GetPointData()->SetScalars(shapeIndexArray);
}

void SurfaceFeaturesExtractor::compute_curvedness()			// C
{
	// std::cout<<" :: Function compute_curvedness"<<std::endl;

	int nbPoints = this->intermediateSurface->GetNumberOfPoints();

	vtkSmartPointer<vtkFloatArray> curvednessArray = vtkSmartPointer<vtkFloatArray>::New() ;

	// vtkDataArray* minCurvArray = this->intermediateSurface->GetPointData()->GetScalars("Minimum_Curvature");
	// vtkDataArray* maxCurvArray = this->intermediateSurface->GetPointData()->GetScalars("Maximum_Curvature");

	vtkSmartPointer<vtkDataArray> minCurvArray = this->intermediateSurface->GetPointData()->GetScalars("Minimum_Curvature");
	vtkSmartPointer<vtkDataArray> maxCurvArray = this->intermediateSurface->GetPointData()->GetScalars("Maximum_Curvature");

	curvednessArray->SetName("Curvedness");

	for (int i=0; i<nbPoints; i++)
	{
		double k1 = minCurvArray->GetTuple1(i);
		double k2 = maxCurvArray->GetTuple1(i);

		double value = sqrt( (pow(k1, 2) + pow(k2, 2) ) / 2);

		curvednessArray->InsertNextTuple1(value);

		this->intermediateSurface->GetPointData()->SetActiveScalars("Curvedness");
		this->intermediateSurface->GetPointData()->SetScalars(curvednessArray);
	}

}

void SurfaceFeaturesExtractor::scalar_indexPoint()
{
	int nbPoints = this->intermediateSurface->GetNumberOfPoints();

	vtkSmartPointer<vtkFloatArray> indexPointArray = vtkSmartPointer<vtkFloatArray>::New() ;

	indexPointArray->SetName("Index_Points");

	for (int i=0; i<nbPoints; i++)
	{
		indexPointArray->InsertNextTuple1(i);

		this->intermediateSurface->GetPointData()->SetActiveScalars("Index_Points");
		this->intermediateSurface->GetPointData()->SetScalars(indexPointArray);
	}
}

void SurfaceFeaturesExtractor::store_landmarks_vtk()
{
	//std::cout << " Functions store landmarks_vtk " << std::endl;

	// Build a locator
	vtkSmartPointer<vtkPointLocator> pointLocator = vtkPointLocator::New();
	pointLocator->SetDataSet(this->intermediateSurface);
	pointLocator->BuildLocator();

	// ---------- Reading FCSV file ----------

	#define NB_LINES 250
	#define NB_WORDS 250

	// Get the Surface filename from the command line
	std::fstream fcsvfile(this->landmarkFile[0].c_str());
	std::string line, mot;
	std::string words[NB_LINES][NB_WORDS]; // !!!! WARNING DEFINE AND TO PROTECT IF SUPERIOR TO 20
	int i,j;
	int* landmarkPids = NULL;
	int NbLandmarks = 0;

	if(fcsvfile)
	{
		getline(fcsvfile, line);
		fcsvfile>>mot;
		while(mot=="#")
		{
			if(getline(fcsvfile, line))
				fcsvfile>>mot;
			else
				mot="#";
		}

		i=0;
		do
		{
			std::size_t pos_end, pos1;
			j=0;
			do
			{
				std::size_t pos0 = 0;
				pos1 = mot.find(',');
				pos_end = mot.find(",,");
				words[i][j] = mot.substr(pos0, pos1-pos0);
				mot = mot.substr(pos1+1);
				j++;
			}
			while(pos1+1<pos_end);
			i++;
		}
		while(fcsvfile>>mot);

		NbLandmarks = i;
		landmarkPids = new int[NbLandmarks];

		for (int i = 0; i < NbLandmarks; ++i)
		{
			double x = atof(words[i][1].c_str());
			double y = atof(words[i][2].c_str());
			double z = atof(words[i][3].c_str());

            // Find closest point
            vtkIdType ptId;
            double p[] = {0.0, 0.0, 0.0};
            p[0] = x; p[1] = y; p[2] = z;
            ptId = pointLocator->FindClosestPoint(p);
            landmarkPids[i] = ptId;

		// std::cout << "landmark " << i << " position " << x << "," << y << "," << z << " and the corresponding Pid is " << landmarkPids[i] << std::endl;
		}
	}
	else
		std::cout<<"Error !";

	// ---------- Encode landmarks in  FCSV file ----------
	vtkSmartPointer<vtkDoubleArray> landmarksArray = vtkSmartPointer<vtkDoubleArray>::New();
	landmarksArray->SetName("Landmarks");
	landmarksArray->SetNumberOfComponents(1);

	for(int ID = 0; ID < this->intermediateSurface->GetNumberOfPoints(); ID++)
	{
		double exists = 0.0;
		for (int i = 0; i < NbLandmarks; ++i)
		{
			double diff = landmarkPids[i] - ID;
			if (diff == 0)
			{
				exists = i+1;
				//std::cout << "Landmark ID " << exists << std::endl;
				break;
			}
		}
		landmarksArray->InsertNextValue(exists);
	}
	landmarksArray->Resize(this->intermediateSurface->GetNumberOfPoints());
	this->intermediateSurface->GetPointData()->AddArray(landmarksArray);

	//delete[] landmarkPids;

}

/**
 * Function Update()
 */
void SurfaceFeaturesExtractor::Update()
{
	this->init_output();

	// Compute normal for each vertex
	this->compute_normals();

	// Compute position of each point
	this->compute_positions();

	// Compute distance to each mean groups
	if (this->meanShapesList.size() > 0)
		this->compute_distances();

	// Compute curvatures at each point
	this->compute_maxcurvatures();
	this->compute_mincurvatures();
	this->compute_gaussiancurvatures();
	this->compute_meancurvatures();

	// Shape Index and Curvedness
	this->compute_shapeindex();
	this->compute_curvedness();

	// this->scalar_indexPoint();

	if (this->landmarkFile.size() == 1)
		this->store_landmarks_vtk();

	this->outputSurface = this->intermediateSurface;
}

/**
 * Function GetOutput()
 */
vtkSmartPointer<vtkPolyData> SurfaceFeaturesExtractor::GetOutput()
{
	return this->outputSurface;
}

<|endoftext|>