<commit_before>
/*
 * Copyright 2011 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 "SkCanvas.h"
#include "SkPaint.h"
#include "SkPath.h"
#include "SkRandom.h"

namespace skiagm {

class EmptyPathGM : public GM {
public:
    EmptyPathGM() {}

protected:
    SkString onShortName() {
        return SkString("emptypath");
    }

    SkISize onISize() { return SkISize::Make(600, 280); }

    void drawEmpty(SkCanvas* canvas,
                    SkColor color,
                    const SkRect& clip,
                    SkPaint::Style style,
                    SkPath::FillType fill) {
        SkPath path;
        path.setFillType(fill);
        SkPaint paint;
        paint.setColor(color);
        paint.setStyle(style);
        canvas->save();
        canvas->clipRect(clip);
        canvas->drawPath(path, paint);
        canvas->restore();
    }

    virtual void onDraw(SkCanvas* canvas) {
        struct FillAndName {
            SkPath::FillType fFill;
            const char*      fName;
        };
        static const FillAndName gFills[] = {
            {SkPath::kWinding_FillType, "Winding"},
            {SkPath::kEvenOdd_FillType, "Even / Odd"},
            {SkPath::kInverseWinding_FillType, "Inverse Winding"},
            {SkPath::kInverseEvenOdd_FillType, "Inverse Even / Odd"},
        };
        struct StyleAndName {
            SkPaint::Style fStyle;
            const char*    fName;
        };
        static const StyleAndName gStyles[] = {
            {SkPaint::kFill_Style, "Fill"},
            {SkPaint::kStroke_Style, "Stroke"},
            {SkPaint::kStrokeAndFill_Style, "Stroke And Fill"},
        };

        SkPaint titlePaint;
        titlePaint.setColor(SK_ColorBLACK);
        titlePaint.setAntiAlias(true);
        sk_tool_utils::set_portable_typeface(&titlePaint);
        titlePaint.setTextSize(15 * SK_Scalar1);
        const char title[] = "Empty Paths Drawn Into Rectangle Clips With "
                             "Indicated Style and Fill";
        canvas->drawText(title, strlen(title),
                            20 * SK_Scalar1,
                            20 * SK_Scalar1,
                            titlePaint);

        SkRandom rand;
        SkRect rect = SkRect::MakeWH(100*SK_Scalar1, 30*SK_Scalar1);
        int i = 0;
        canvas->save();
        canvas->translate(10 * SK_Scalar1, 0);
        canvas->save();
        for (size_t style = 0; style < SK_ARRAY_COUNT(gStyles); ++style) {
            for (size_t fill = 0; fill < SK_ARRAY_COUNT(gFills); ++fill) {
                if (0 == i % 4) {
                    canvas->restore();
                    canvas->translate(0, rect.height() + 40 * SK_Scalar1);
                    canvas->save();
                } else {
                    canvas->translate(rect.width() + 40 * SK_Scalar1, 0);
                }
                ++i;

                SkColor color = rand.nextU();
                color = 0xff000000 | color; // force solid
                color = sk_tool_utils::color_to_565(color);
                this->drawEmpty(canvas, color, rect,
                                gStyles[style].fStyle, gFills[fill].fFill);

                SkPaint rectPaint;
                rectPaint.setColor(SK_ColorBLACK);
                rectPaint.setStyle(SkPaint::kStroke_Style);
                rectPaint.setStrokeWidth(-1);
                rectPaint.setAntiAlias(true);
                canvas->drawRect(rect, rectPaint);

                SkPaint labelPaint;
                labelPaint.setColor(color);
                labelPaint.setAntiAlias(true);
                sk_tool_utils::set_portable_typeface(&labelPaint);
                labelPaint.setTextSize(12 * SK_Scalar1);
                canvas->drawText(gStyles[style].fName,
                                 strlen(gStyles[style].fName),
                                 0, rect.height() + 15 * SK_Scalar1,
                                 labelPaint);
                canvas->drawText(gFills[fill].fName,
                                 strlen(gFills[fill].fName),
                                 0, rect.height() + 28 * SK_Scalar1,
                                 labelPaint);
            }
        }
        canvas->restore();
        canvas->restore();
    }

private:
    typedef GM INHERITED;
};

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

static GM* MyFactory(void*) { return new EmptyPathGM; }
static GMRegistry reg(MyFactory);

}
<commit_msg>draw 3 moveTos followed by various others [moves, lines, closes]<commit_after>
/*
 * Copyright 2011 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 "SkCanvas.h"
#include "SkPaint.h"
#include "SkPath.h"
#include "SkRandom.h"

namespace skiagm {

class EmptyPathGM : public GM {
public:
    EmptyPathGM() {}

protected:
    SkString onShortName() {
        return SkString("emptypath");
    }

    SkISize onISize() { return SkISize::Make(600, 280); }

    void drawEmpty(SkCanvas* canvas,
                    SkColor color,
                    const SkRect& clip,
                    SkPaint::Style style,
                    SkPath::FillType fill) {
        SkPath path;
        path.setFillType(fill);
        SkPaint paint;
        paint.setColor(color);
        paint.setStyle(style);
        canvas->save();
        canvas->clipRect(clip);
        canvas->drawPath(path, paint);
        canvas->restore();
    }

    virtual void onDraw(SkCanvas* canvas) {
        struct FillAndName {
            SkPath::FillType fFill;
            const char*      fName;
        };
        static const FillAndName gFills[] = {
            {SkPath::kWinding_FillType, "Winding"},
            {SkPath::kEvenOdd_FillType, "Even / Odd"},
            {SkPath::kInverseWinding_FillType, "Inverse Winding"},
            {SkPath::kInverseEvenOdd_FillType, "Inverse Even / Odd"},
        };
        struct StyleAndName {
            SkPaint::Style fStyle;
            const char*    fName;
        };
        static const StyleAndName gStyles[] = {
            {SkPaint::kFill_Style, "Fill"},
            {SkPaint::kStroke_Style, "Stroke"},
            {SkPaint::kStrokeAndFill_Style, "Stroke And Fill"},
        };

        SkPaint titlePaint;
        titlePaint.setColor(SK_ColorBLACK);
        titlePaint.setAntiAlias(true);
        sk_tool_utils::set_portable_typeface(&titlePaint);
        titlePaint.setTextSize(15 * SK_Scalar1);
        const char title[] = "Empty Paths Drawn Into Rectangle Clips With "
                             "Indicated Style and Fill";
        canvas->drawText(title, strlen(title),
                            20 * SK_Scalar1,
                            20 * SK_Scalar1,
                            titlePaint);

        SkRandom rand;
        SkRect rect = SkRect::MakeWH(100*SK_Scalar1, 30*SK_Scalar1);
        int i = 0;
        canvas->save();
        canvas->translate(10 * SK_Scalar1, 0);
        canvas->save();
        for (size_t style = 0; style < SK_ARRAY_COUNT(gStyles); ++style) {
            for (size_t fill = 0; fill < SK_ARRAY_COUNT(gFills); ++fill) {
                if (0 == i % 4) {
                    canvas->restore();
                    canvas->translate(0, rect.height() + 40 * SK_Scalar1);
                    canvas->save();
                } else {
                    canvas->translate(rect.width() + 40 * SK_Scalar1, 0);
                }
                ++i;

                SkColor color = rand.nextU();
                color = 0xff000000 | color; // force solid
                color = sk_tool_utils::color_to_565(color);
                this->drawEmpty(canvas, color, rect,
                                gStyles[style].fStyle, gFills[fill].fFill);

                SkPaint rectPaint;
                rectPaint.setColor(SK_ColorBLACK);
                rectPaint.setStyle(SkPaint::kStroke_Style);
                rectPaint.setStrokeWidth(-1);
                rectPaint.setAntiAlias(true);
                canvas->drawRect(rect, rectPaint);

                SkPaint labelPaint;
                labelPaint.setColor(color);
                labelPaint.setAntiAlias(true);
                sk_tool_utils::set_portable_typeface(&labelPaint);
                labelPaint.setTextSize(12 * SK_Scalar1);
                canvas->drawText(gStyles[style].fName,
                                 strlen(gStyles[style].fName),
                                 0, rect.height() + 15 * SK_Scalar1,
                                 labelPaint);
                canvas->drawText(gFills[fill].fName,
                                 strlen(gFills[fill].fName),
                                 0, rect.height() + 28 * SK_Scalar1,
                                 labelPaint);
            }
        }
        canvas->restore();
        canvas->restore();
    }

private:
    typedef GM INHERITED;
};
DEF_GM( return new EmptyPathGM; )

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

static void make_path_move(SkPath* path, const SkPoint pts[3]) {
    for (int i = 0; i < 3; ++i) {
        path->moveTo(pts[i]);
    }
}

static void make_path_move_close(SkPath* path, const SkPoint pts[3]) {
    for (int i = 0; i < 3; ++i) {
        path->moveTo(pts[i]);
        path->close();
    }
}

static void make_path_move_line(SkPath* path, const SkPoint pts[3]) {
    for (int i = 0; i < 3; ++i) {
        path->moveTo(pts[i]);
        path->lineTo(pts[i]);
    }
}

typedef void (*MakePathProc)(SkPath*, const SkPoint pts[3]);

static void make_path_move_mix(SkPath* path, const SkPoint pts[3]) {
    path->moveTo(pts[0]);
    path->moveTo(pts[1]); path->close();
    path->moveTo(pts[2]); path->lineTo(pts[2]);
}

class EmptyStrokeGM : public GM {
    SkPoint fPts[3];

public:
    EmptyStrokeGM() {
        fPts[0].set(40, 40);
        fPts[1].set(80, 40);
        fPts[2].set(120, 40);
    }

protected:
    SkString onShortName() {
        return SkString("emptystroke");
    }

    SkISize onISize() override { return SkISize::Make(200, 240); }

    void onDraw(SkCanvas* canvas) override {
        const MakePathProc procs[] = {
            make_path_move,             // expect red red red
            make_path_move_close,       // expect black black black
            make_path_move_line,        // expect black black black
            make_path_move_mix,         // expect red black black,
        };

        SkPaint strokePaint;
        strokePaint.setStyle(SkPaint::kStroke_Style);
        strokePaint.setStrokeWidth(21);
        strokePaint.setStrokeCap(SkPaint::kSquare_Cap);

        SkPaint dotPaint;
        dotPaint.setColor(SK_ColorRED);
        strokePaint.setStyle(SkPaint::kStroke_Style);
        dotPaint.setStrokeWidth(7);

        for (size_t i = 0; i < SK_ARRAY_COUNT(procs); ++i) {
            SkPath path;
            procs[i](&path, fPts);
            canvas->drawPoints(SkCanvas::kPoints_PointMode, 3, fPts, dotPaint);
            canvas->drawPath(path, strokePaint);
            canvas->translate(0, 40);
        }
    }

private:
    typedef GM INHERITED;
};
DEF_GM( return new EmptyStrokeGM; )

}
<|endoftext|>


<commit_before>
/*
 * Copyright 2011 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 "SkGradientShader.h"

namespace skiagm {

struct GradData {
    int             fCount;
    const SkColor*  fColors;
    const SkScalar* fPos;
};

static const SkColor gColors[] = {
    SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK
};
static const SkScalar gPos0[] = { 0, SK_Scalar1 };
static const SkScalar gPos1[] = { SK_Scalar1/4, SK_Scalar1*3/4 };
static const SkScalar gPos2[] = {
    0, SK_Scalar1/8, SK_Scalar1/2, SK_Scalar1*7/8, SK_Scalar1
};

static const GradData gGradData[] = {
    { 2, gColors, NULL },
    { 2, gColors, gPos0 },
    { 2, gColors, gPos1 },
    { 5, gColors, NULL },
    { 5, gColors, gPos2 }
};

static SkShader* MakeLinear(const SkPoint pts[2], const GradData& data,
                            SkShader::TileMode tm, SkUnitMapper* mapper) {
    return SkGradientShader::CreateLinear(pts, data.fColors, data.fPos,
                                          data.fCount, tm, mapper);
}

static SkShader* MakeRadial(const SkPoint pts[2], const GradData& data,
                            SkShader::TileMode tm, SkUnitMapper* mapper) {
    SkPoint center;
    center.set(SkScalarAve(pts[0].fX, pts[1].fX),
               SkScalarAve(pts[0].fY, pts[1].fY));
    return SkGradientShader::CreateRadial(center, center.fX, data.fColors,
                                          data.fPos, data.fCount, tm, mapper);
}

static SkShader* MakeSweep(const SkPoint pts[2], const GradData& data,
                           SkShader::TileMode tm, SkUnitMapper* mapper) {
    SkPoint center;
    center.set(SkScalarAve(pts[0].fX, pts[1].fX),
               SkScalarAve(pts[0].fY, pts[1].fY));
    return SkGradientShader::CreateSweep(center.fX, center.fY, data.fColors,
                                         data.fPos, data.fCount, mapper);
}

static SkShader* Make2Radial(const SkPoint pts[2], const GradData& data,
                             SkShader::TileMode tm, SkUnitMapper* mapper) {
    SkPoint center0, center1;
    center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
                SkScalarAve(pts[0].fY, pts[1].fY));
    center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
                SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
    return SkGradientShader::CreateTwoPointRadial(
                                                  center1, (pts[1].fX - pts[0].fX) / 7,
                                                  center0, (pts[1].fX - pts[0].fX) / 2,
                                                  data.fColors, data.fPos, data.fCount, tm, mapper);
}

typedef SkShader* (*GradMaker)(const SkPoint pts[2], const GradData& data,
                               SkShader::TileMode tm, SkUnitMapper* mapper);
static const GradMaker gGradMakers[] = {
    MakeLinear, MakeRadial, MakeSweep, Make2Radial
};

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

class GradientsGM : public GM {
public:
	GradientsGM() {
        this->setBGColor(0xFFDDDDDD);
    }

protected:
    SkString onShortName() {
        return SkString("gradients");
    }

    virtual SkISize onISize() { return make_isize(640, 510); }

    virtual void onDraw(SkCanvas* canvas) {

        SkPoint pts[2] = {
            { 0, 0 },
            { SkIntToScalar(100), SkIntToScalar(100) }
        };
        SkShader::TileMode tm = SkShader::kClamp_TileMode;
        SkRect r = { 0, 0, SkIntToScalar(100), SkIntToScalar(100) };
        SkPaint paint;
        paint.setAntiAlias(true);

        canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
        for (size_t i = 0; i < SK_ARRAY_COUNT(gGradData); i++) {
            canvas->save();
            for (size_t j = 0; j < SK_ARRAY_COUNT(gGradMakers); j++) {
                SkShader* shader = gGradMakers[j](pts, gGradData[i], tm, NULL);
                paint.setShader(shader);
                canvas->drawRect(r, paint);
                shader->unref();
                canvas->translate(0, SkIntToScalar(120));
            }
            canvas->restore();
            canvas->translate(SkIntToScalar(120), 0);
        }
    }

private:
    typedef GM INHERITED;
};

/*
 Inspired by this <canvas> javascript, where we need to detect that we are not
 solving a quadratic equation, but must instead solve a linear (since our X^2
 coefficient is 0)

 ctx.fillStyle = '#f00';
 ctx.fillRect(0, 0, 100, 50);

 var g = ctx.createRadialGradient(-80, 25, 70, 0, 25, 150);
 g.addColorStop(0, '#f00');
 g.addColorStop(0.01, '#0f0');
 g.addColorStop(0.99, '#0f0');
 g.addColorStop(1, '#f00');
 ctx.fillStyle = g;
 ctx.fillRect(0, 0, 100, 50);
 */
class GradientsDegenrate2PointGM : public GM {
public:
    GradientsDegenrate2PointGM() {}

protected:
    SkString onShortName() {
        return SkString("gradients_degenerate_2pt");
    }

	virtual SkISize onISize() { return make_isize(320, 320); }

    void drawBG(SkCanvas* canvas) {
        canvas->drawColor(SK_ColorBLUE);
    }

    virtual void onDraw(SkCanvas* canvas) {
        this->drawBG(canvas);

        SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorGREEN, SK_ColorRED };
        SkScalar pos[] = { 0, SkFloatToScalar(0.01f), SkFloatToScalar(0.99f), SK_Scalar1 };
        SkPoint c0;
        c0.iset(-80, 25);
        SkScalar r0 = SkIntToScalar(70);
        SkPoint c1;
        c1.iset(0, 25);
        SkScalar r1 = SkIntToScalar(150);
        SkShader* s = SkGradientShader::CreateTwoPointRadial(c0, r0, c1, r1, colors,
                                                             pos, SK_ARRAY_COUNT(pos),
                                                             SkShader::kClamp_TileMode);
        SkPaint paint;
        paint.setShader(s)->unref();
        canvas->drawPaint(paint);
    }

private:
    typedef GM INHERITED;
};

/// Tests correctness of *optimized* codepaths in gradients.

class ClampedGradientsGM : public GM {
public:
    ClampedGradientsGM() {}

protected:
    SkString onShortName() { return SkString("clamped_gradients"); }

    virtual SkISize onISize() { return make_isize(640, 510); }

    void drawBG(SkCanvas* canvas) {
        canvas->drawColor(0xFFDDDDDD);
    }

    virtual void onDraw(SkCanvas* canvas) {
        this->drawBG(canvas);

        SkRect r = { 0, 0, SkIntToScalar(100), SkIntToScalar(300) };
        SkPaint paint;
        paint.setAntiAlias(true);

        SkPoint center;
        center.iset(0, 300);
        canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
        SkShader* shader = SkGradientShader::CreateRadial(
            SkPoint(center),
            SkIntToScalar(200), gColors, NULL, 5,
            SkShader::kClamp_TileMode, NULL);
        paint.setShader(shader);
        canvas->drawRect(r, paint);
        shader->unref();
    }

private:
    typedef GM INHERITED;
};

/// Checks quality of large radial gradients, which may display
/// some banding.

class RadialGradientGM : public GM {
public:
    RadialGradientGM() {}

protected:
    SkString onShortName() { return SkString("radial_gradient"); }
    virtual SkISize onISize() { return make_isize(1280, 1024); }
    void drawBG(SkCanvas* canvas) {
        canvas->drawColor(0xFF000000);
    }
    virtual void onDraw(SkCanvas* canvas) {
        this->drawBG(canvas);

        SkPaint paint;
        paint.setDither(true);
        SkPoint center;
        center.set(SkIntToScalar(640), SkIntToScalar(512));
        SkScalar radius = SkIntToScalar(640);
        SkColor colors [3] = { 0x7f7f7f7f, 0x7f7f7f7f, 0xb2000000 };
        SkScalar pos [3] = { 0.0, 0.35, 1.0 };
        SkShader* shader =
            SkGradientShader::CreateRadial(center, radius, colors,
                                           pos, 3, SkShader::kClamp_TileMode);
        paint.setShader(shader)->unref();
        SkRect r = { 0, 0, SkIntToScalar(1280), SkIntToScalar(1024) };
        canvas->drawRect(r, paint);
    }
private:
    typedef GM INHERITED;
};

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

static GM* MyFactory(void*) { return new GradientsGM; }
static GMRegistry reg(MyFactory);

static GM* MyFactory2(void*) { return new GradientsDegenrate2PointGM; }
static GMRegistry reg2(MyFactory2);

static GM* MyFactory3(void*) { return new ClampedGradientsGM; }
static GMRegistry reg3(MyFactory3);

static GM* MyFactory4(void*) { return new RadialGradientGM; }
static GMRegistry reg4(MyFactory4);
}

<commit_msg>Add missing SkFloatToScalar() calls to fix the build.<commit_after>
/*
 * Copyright 2011 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 "SkGradientShader.h"

namespace skiagm {

struct GradData {
    int             fCount;
    const SkColor*  fColors;
    const SkScalar* fPos;
};

static const SkColor gColors[] = {
    SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK
};
static const SkScalar gPos0[] = { 0, SK_Scalar1 };
static const SkScalar gPos1[] = { SK_Scalar1/4, SK_Scalar1*3/4 };
static const SkScalar gPos2[] = {
    0, SK_Scalar1/8, SK_Scalar1/2, SK_Scalar1*7/8, SK_Scalar1
};

static const GradData gGradData[] = {
    { 2, gColors, NULL },
    { 2, gColors, gPos0 },
    { 2, gColors, gPos1 },
    { 5, gColors, NULL },
    { 5, gColors, gPos2 }
};

static SkShader* MakeLinear(const SkPoint pts[2], const GradData& data,
                            SkShader::TileMode tm, SkUnitMapper* mapper) {
    return SkGradientShader::CreateLinear(pts, data.fColors, data.fPos,
                                          data.fCount, tm, mapper);
}

static SkShader* MakeRadial(const SkPoint pts[2], const GradData& data,
                            SkShader::TileMode tm, SkUnitMapper* mapper) {
    SkPoint center;
    center.set(SkScalarAve(pts[0].fX, pts[1].fX),
               SkScalarAve(pts[0].fY, pts[1].fY));
    return SkGradientShader::CreateRadial(center, center.fX, data.fColors,
                                          data.fPos, data.fCount, tm, mapper);
}

static SkShader* MakeSweep(const SkPoint pts[2], const GradData& data,
                           SkShader::TileMode tm, SkUnitMapper* mapper) {
    SkPoint center;
    center.set(SkScalarAve(pts[0].fX, pts[1].fX),
               SkScalarAve(pts[0].fY, pts[1].fY));
    return SkGradientShader::CreateSweep(center.fX, center.fY, data.fColors,
                                         data.fPos, data.fCount, mapper);
}

static SkShader* Make2Radial(const SkPoint pts[2], const GradData& data,
                             SkShader::TileMode tm, SkUnitMapper* mapper) {
    SkPoint center0, center1;
    center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
                SkScalarAve(pts[0].fY, pts[1].fY));
    center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
                SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
    return SkGradientShader::CreateTwoPointRadial(
                                                  center1, (pts[1].fX - pts[0].fX) / 7,
                                                  center0, (pts[1].fX - pts[0].fX) / 2,
                                                  data.fColors, data.fPos, data.fCount, tm, mapper);
}

typedef SkShader* (*GradMaker)(const SkPoint pts[2], const GradData& data,
                               SkShader::TileMode tm, SkUnitMapper* mapper);
static const GradMaker gGradMakers[] = {
    MakeLinear, MakeRadial, MakeSweep, Make2Radial
};

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

class GradientsGM : public GM {
public:
	GradientsGM() {
        this->setBGColor(0xFFDDDDDD);
    }

protected:
    SkString onShortName() {
        return SkString("gradients");
    }

    virtual SkISize onISize() { return make_isize(640, 510); }

    virtual void onDraw(SkCanvas* canvas) {

        SkPoint pts[2] = {
            { 0, 0 },
            { SkIntToScalar(100), SkIntToScalar(100) }
        };
        SkShader::TileMode tm = SkShader::kClamp_TileMode;
        SkRect r = { 0, 0, SkIntToScalar(100), SkIntToScalar(100) };
        SkPaint paint;
        paint.setAntiAlias(true);

        canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
        for (size_t i = 0; i < SK_ARRAY_COUNT(gGradData); i++) {
            canvas->save();
            for (size_t j = 0; j < SK_ARRAY_COUNT(gGradMakers); j++) {
                SkShader* shader = gGradMakers[j](pts, gGradData[i], tm, NULL);
                paint.setShader(shader);
                canvas->drawRect(r, paint);
                shader->unref();
                canvas->translate(0, SkIntToScalar(120));
            }
            canvas->restore();
            canvas->translate(SkIntToScalar(120), 0);
        }
    }

private:
    typedef GM INHERITED;
};

/*
 Inspired by this <canvas> javascript, where we need to detect that we are not
 solving a quadratic equation, but must instead solve a linear (since our X^2
 coefficient is 0)

 ctx.fillStyle = '#f00';
 ctx.fillRect(0, 0, 100, 50);

 var g = ctx.createRadialGradient(-80, 25, 70, 0, 25, 150);
 g.addColorStop(0, '#f00');
 g.addColorStop(0.01, '#0f0');
 g.addColorStop(0.99, '#0f0');
 g.addColorStop(1, '#f00');
 ctx.fillStyle = g;
 ctx.fillRect(0, 0, 100, 50);
 */
class GradientsDegenrate2PointGM : public GM {
public:
    GradientsDegenrate2PointGM() {}

protected:
    SkString onShortName() {
        return SkString("gradients_degenerate_2pt");
    }

	virtual SkISize onISize() { return make_isize(320, 320); }

    void drawBG(SkCanvas* canvas) {
        canvas->drawColor(SK_ColorBLUE);
    }

    virtual void onDraw(SkCanvas* canvas) {
        this->drawBG(canvas);

        SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorGREEN, SK_ColorRED };
        SkScalar pos[] = { 0, SkFloatToScalar(0.01f), SkFloatToScalar(0.99f), SK_Scalar1 };
        SkPoint c0;
        c0.iset(-80, 25);
        SkScalar r0 = SkIntToScalar(70);
        SkPoint c1;
        c1.iset(0, 25);
        SkScalar r1 = SkIntToScalar(150);
        SkShader* s = SkGradientShader::CreateTwoPointRadial(c0, r0, c1, r1, colors,
                                                             pos, SK_ARRAY_COUNT(pos),
                                                             SkShader::kClamp_TileMode);
        SkPaint paint;
        paint.setShader(s)->unref();
        canvas->drawPaint(paint);
    }

private:
    typedef GM INHERITED;
};

/// Tests correctness of *optimized* codepaths in gradients.

class ClampedGradientsGM : public GM {
public:
    ClampedGradientsGM() {}

protected:
    SkString onShortName() { return SkString("clamped_gradients"); }

    virtual SkISize onISize() { return make_isize(640, 510); }

    void drawBG(SkCanvas* canvas) {
        canvas->drawColor(0xFFDDDDDD);
    }

    virtual void onDraw(SkCanvas* canvas) {
        this->drawBG(canvas);

        SkRect r = { 0, 0, SkIntToScalar(100), SkIntToScalar(300) };
        SkPaint paint;
        paint.setAntiAlias(true);

        SkPoint center;
        center.iset(0, 300);
        canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
        SkShader* shader = SkGradientShader::CreateRadial(
            SkPoint(center),
            SkIntToScalar(200), gColors, NULL, 5,
            SkShader::kClamp_TileMode, NULL);
        paint.setShader(shader);
        canvas->drawRect(r, paint);
        shader->unref();
    }

private:
    typedef GM INHERITED;
};

/// Checks quality of large radial gradients, which may display
/// some banding.

class RadialGradientGM : public GM {
public:
    RadialGradientGM() {}

protected:
    SkString onShortName() { return SkString("radial_gradient"); }
    virtual SkISize onISize() { return make_isize(1280, 1024); }
    void drawBG(SkCanvas* canvas) {
        canvas->drawColor(0xFF000000);
    }
    virtual void onDraw(SkCanvas* canvas) {
        this->drawBG(canvas);

        SkPaint paint;
        paint.setDither(true);
        SkPoint center;
        center.set(SkIntToScalar(640), SkIntToScalar(512));
        SkScalar radius = SkIntToScalar(640);
        SkColor colors [3] = { 0x7f7f7f7f, 0x7f7f7f7f, 0xb2000000 };
        SkScalar pos [3] = { SkFloatToScalar(0.0),
                             SkFloatToScalar(0.35),
                             SkFloatToScalar(1.0) };
        SkShader* shader =
            SkGradientShader::CreateRadial(center, radius, colors,
                                           pos, 3, SkShader::kClamp_TileMode);
        paint.setShader(shader)->unref();
        SkRect r = { 0, 0, SkIntToScalar(1280), SkIntToScalar(1024) };
        canvas->drawRect(r, paint);
    }
private:
    typedef GM INHERITED;
};

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

static GM* MyFactory(void*) { return new GradientsGM; }
static GMRegistry reg(MyFactory);

static GM* MyFactory2(void*) { return new GradientsDegenrate2PointGM; }
static GMRegistry reg2(MyFactory2);

static GM* MyFactory3(void*) { return new ClampedGradientsGM; }
static GMRegistry reg3(MyFactory3);

static GM* MyFactory4(void*) { return new RadialGradientGM; }
static GMRegistry reg4(MyFactory4);
}

<|endoftext|>


<commit_before>#include "ToolBase.h"
#include "NGSD.h"
#include "Exceptions.h"
#include "Helper.h"

class ConcreteTool
		: public ToolBase
{
	Q_OBJECT

public:
	ConcreteTool(int& argc, char *argv[])
		: ToolBase(argc, argv)
	{
	}

	virtual void setup()
	{
		setDescription("Imports Ensembl/CCDS transcript information into NGSD.");
		addInfile("in", "Ensemble transcript file (download and unzip ftp://ftp.ensembl.org/pub/grch37/update/gff3/homo_sapiens/Homo_sapiens.GRCh37.87.gff3.gz).", false);
		//optional
		addFlag("all", "If set, all transcripts are imported (the default is to skip transcripts not labeled as with the 'GENCODE basic' tag).");
		addFlag("test", "Uses the test database instead of on the production database.");
		addFlag("force", "If set, overwrites old data.");

		changeLog(2017,  7,  6, "Added first version");
	}

	QMap<QByteArray, QByteArray> parseAttributes(QByteArray attributes)
	{
		QMap<QByteArray, QByteArray> output;

		QByteArrayList parts = attributes.split(';');
		foreach(QByteArray part, parts)
		{
			int split_index = part.indexOf('=');
			output[part.left(split_index)] = part.mid(split_index+1);
		}

		return output;
	}

	struct TranscriptData
	{
		QByteArray name;
		QByteArray name_ccds;
		QByteArray chr;
		int start_coding = -1;
		int end_coding = -1;
		QByteArray strand;

		BedFile exons;

		int ngsd_gene_id;
	};

	int addTranscript(SqlQuery& query, int gene_id, QByteArray name, QByteArray source, const TranscriptData& t_data)
	{
		//TODO
		QTextStream(stdout) << "Adding transcript name=" << name << " source=" << source << " gene=" << t_data.ngsd_gene_id << " start_coding=" << t_data.start_coding << " end_coding=" << t_data.end_coding << endl;
		query.bindValue(0, gene_id);
		query.bindValue(1, name);
		query.bindValue(2, source);
		query.bindValue(3, t_data.chr);
		if (t_data.start_coding!=-1 && t_data.end_coding!=-1)
		{
			query.bindValue(4, t_data.start_coding);
			query.bindValue(5, t_data.end_coding);
		}
		else
		{
			query.bindValue(4, QVariant());
			query.bindValue(5, QVariant());
		}
		query.bindValue(6, t_data.strand);
		query.exec();

		return query.lastInsertId().toInt();
	}

	void addExons(SqlQuery& query, int transcript_id, const BedFile& exons)
	{

		//TODO
		QTextStream(stdout) << " " << exons.count() << endl;
		for (int i=0; i<exons.count(); ++i)
		{
			//out << "  Adding exon start=" << exons[i].start() << " end=" <<exons[i].end() << endl;
			query.bindValue(0, transcript_id);
			query.bindValue(1, exons[i].start());
			query.bindValue(2, exons[i].end());
			query.exec();
		}
	}

	virtual void main()
	{
		//init
		NGSD db(getFlag("test"));
		QTextStream out(stdout);
		bool all = getFlag("all");

		//check tables exist
		db.tableExists("gene");
		db.tableExists("gene_alias");
		db.tableExists("gene_transcript");
		db.tableExists("gene_exon");

		//clear tables if not empty
		if (!db.tableEmpty("gene_transcript") || !db.tableEmpty("gene_exon"))
		{
			if (getFlag("force"))
			{
				db.clearTable("gene_exon");
				db.clearTable("gene_transcript");
			}
			else
			{
				THROW(DatabaseException, "Tables already contain data! Use '-force' to overwrite old data!");
			}
		}

		//prepare queries
		SqlQuery q_trans = db.getQuery();
		q_trans.prepare("INSERT INTO gene_transcript (gene_id, name, source, chromosome, start_coding, end_coding, strand) VALUES (:0, :1, :2, :3, :4, :5, :6);");

		SqlQuery q_exon = db.getQuery();
		q_exon.prepare("INSERT INTO gene_exon (transcript_id, start, end) VALUES (:0, :1, :2);");

		//parse input - format description at https://www.gencodegenes.org/data_format.html and http://www.ensembl.org/info/website/upload/gff3.html
		QMap<QByteArray, int> gene_ensemble2ngsd;
		QMap<QByteArray, TranscriptData> transcripts;
		QSet<QByteArray> ccds_transcripts_added;
		auto fp = Helper::openFileForReading(getInfile("in"));
		while(!fp->atEnd())
		{
			QByteArray line = fp->readLine().trimmed();
			if (line.isEmpty()) continue;

			//section end => commit data
			if (line=="###")
			{
				//import data
				auto it = transcripts.begin();
				while(it!=transcripts.end())
				{
					//add Ensembl transcript
					TranscriptData& t_data = it.value();
					int trans_id = addTranscript(q_trans, t_data.ngsd_gene_id, t_data.name , "ensembl", t_data);
					//add exons
					t_data.exons.merge();
					addExons(q_exon, trans_id, t_data.exons);

					//add CCDS transcript as well (only once)
					if (t_data.name_ccds!="" && !ccds_transcripts_added.contains(t_data.name_ccds))
					{
						int trans_id_ccds = addTranscript(q_trans, t_data.ngsd_gene_id, t_data.name_ccds , "ccds", t_data);
						//add exons (only coding part)
						BedFile coding_part;
						coding_part.append(BedLine(t_data.exons[0].chr() ,t_data.start_coding, t_data.end_coding));
						t_data.exons.intersect(coding_part);
						addExons(q_exon, trans_id_ccds, t_data.exons);

						ccds_transcripts_added.insert(t_data.name_ccds);
					}
					++it;
				}

				//clear cache
				gene_ensemble2ngsd.clear();
				transcripts.clear();
				continue;
			}

			//skip header lines
			if (line.startsWith("#")) continue;

			QByteArrayList parts = line.split('\t');
			QByteArray type = parts[2];
			QMap<QByteArray, QByteArray> data = parseAttributes(parts[8]);

			//gene line
			if (data.contains("gene_id"))
			{
				QByteArray gene = data["Name"];

				//transform gene names to approved gene IDs
				int ngsd_gene_id = db.geneToApprovedID(gene);
				if (ngsd_gene_id==-1)
				{
					out << "ERROR " << data["gene_id"] << "/" << gene << ": no approved gene names found." << endl;
					continue;
				}
				gene_ensemble2ngsd[data["ID"]] = ngsd_gene_id;
			}

			//transcript line
			else if (data.contains("transcript_id"))
			{
				if (all || data.value("tag")=="basic")
				{
					TranscriptData tmp;
					tmp.name = data["transcript_id"];
					tmp.name_ccds = data.value("ccdsid", "");
					tmp.chr = parts[0];
					tmp.strand = parts[6];
					tmp.ngsd_gene_id = gene_ensemble2ngsd[data["Parent"]];
					transcripts[data["ID"]] = tmp;
				}
			}

			//exon lines
			else if (type=="CDS" || type=="exon" || type=="three_prime_UTR" || type=="five_prime_UTR" )
			{
				QByteArray parent_id = data["Parent"];

				//skip exons of unhandled transcripts (not GENCODE basic)
				if (!transcripts.contains(parent_id)) continue;
				TranscriptData& t_data = transcripts[parent_id];

				//check chromosome matches
				QByteArray chr = parts[0];
				if (chr!=t_data.chr)
				{
					THROW(FileParseException, "Chromosome mismach between transcript and exon!");
				}

				//update coding start/end
				int start = Helper::toInt(parts[3], "start position");
				int end = Helper::toInt(parts[4], "end position");

				if (type=="CDS")
				{
					t_data.start_coding = (t_data.start_coding==-1) ? start : std::min(start, t_data.start_coding);
					t_data.end_coding = (t_data.end_coding==-1) ? end : std::max(end, t_data.end_coding);
				}

				//add coding exon
				t_data.exons.append(BedLine(chr, start, end));
			}
		}
	}
};

#include "main.moc"

int main(int argc, char *argv[])
{
	ConcreteTool tool(argc, argv);
	return tool.execute();
}
<commit_msg>removed accidentally committed debug output.<commit_after>#include "ToolBase.h"
#include "NGSD.h"
#include "Exceptions.h"
#include "Helper.h"

class ConcreteTool
		: public ToolBase
{
	Q_OBJECT

public:
	ConcreteTool(int& argc, char *argv[])
		: ToolBase(argc, argv)
	{
	}

	virtual void setup()
	{
		setDescription("Imports Ensembl/CCDS transcript information into NGSD.");
		addInfile("in", "Ensemble transcript file (download and unzip ftp://ftp.ensembl.org/pub/grch37/update/gff3/homo_sapiens/Homo_sapiens.GRCh37.87.gff3.gz).", false);
		//optional
		addFlag("all", "If set, all transcripts are imported (the default is to skip transcripts not labeled as with the 'GENCODE basic' tag).");
		addFlag("test", "Uses the test database instead of on the production database.");
		addFlag("force", "If set, overwrites old data.");

		changeLog(2017,  7,  6, "Added first version");
	}

	QMap<QByteArray, QByteArray> parseAttributes(QByteArray attributes)
	{
		QMap<QByteArray, QByteArray> output;

		QByteArrayList parts = attributes.split(';');
		foreach(QByteArray part, parts)
		{
			int split_index = part.indexOf('=');
			output[part.left(split_index)] = part.mid(split_index+1);
		}

		return output;
	}

	struct TranscriptData
	{
		QByteArray name;
		QByteArray name_ccds;
		QByteArray chr;
		int start_coding = -1;
		int end_coding = -1;
		QByteArray strand;

		BedFile exons;

		int ngsd_gene_id;
	};

	int addTranscript(SqlQuery& query, int gene_id, QByteArray name, QByteArray source, const TranscriptData& t_data)
	{
		//QTextStream(stdout) << "Adding transcript name=" << name << " source=" << source << " gene=" << t_data.ngsd_gene_id << " start_coding=" << t_data.start_coding << " end_coding=" << t_data.end_coding << endl;
		query.bindValue(0, gene_id);
		query.bindValue(1, name);
		query.bindValue(2, source);
		query.bindValue(3, t_data.chr);
		if (t_data.start_coding!=-1 && t_data.end_coding!=-1)
		{
			query.bindValue(4, t_data.start_coding);
			query.bindValue(5, t_data.end_coding);
		}
		else
		{
			query.bindValue(4, QVariant());
			query.bindValue(5, QVariant());
		}
		query.bindValue(6, t_data.strand);
		query.exec();

		return query.lastInsertId().toInt();
	}

	void addExons(SqlQuery& query, int transcript_id, const BedFile& exons)
	{
		//QTextStream(stdout) << " " << exons.count() << endl;
		for (int i=0; i<exons.count(); ++i)
		{
			//out << "  Adding exon start=" << exons[i].start() << " end=" <<exons[i].end() << endl;
			query.bindValue(0, transcript_id);
			query.bindValue(1, exons[i].start());
			query.bindValue(2, exons[i].end());
			query.exec();
		}
	}

	virtual void main()
	{
		//init
		NGSD db(getFlag("test"));
		QTextStream out(stdout);
		bool all = getFlag("all");

		//check tables exist
		db.tableExists("gene");
		db.tableExists("gene_alias");
		db.tableExists("gene_transcript");
		db.tableExists("gene_exon");

		//clear tables if not empty
		if (!db.tableEmpty("gene_transcript") || !db.tableEmpty("gene_exon"))
		{
			if (getFlag("force"))
			{
				db.clearTable("gene_exon");
				db.clearTable("gene_transcript");
			}
			else
			{
				THROW(DatabaseException, "Tables already contain data! Use '-force' to overwrite old data!");
			}
		}

		//prepare queries
		SqlQuery q_trans = db.getQuery();
		q_trans.prepare("INSERT INTO gene_transcript (gene_id, name, source, chromosome, start_coding, end_coding, strand) VALUES (:0, :1, :2, :3, :4, :5, :6);");

		SqlQuery q_exon = db.getQuery();
		q_exon.prepare("INSERT INTO gene_exon (transcript_id, start, end) VALUES (:0, :1, :2);");

		//parse input - format description at https://www.gencodegenes.org/data_format.html and http://www.ensembl.org/info/website/upload/gff3.html
		QMap<QByteArray, int> gene_ensemble2ngsd;
		QMap<QByteArray, TranscriptData> transcripts;
		QSet<QByteArray> ccds_transcripts_added;
		auto fp = Helper::openFileForReading(getInfile("in"));
		while(!fp->atEnd())
		{
			QByteArray line = fp->readLine().trimmed();
			if (line.isEmpty()) continue;

			//section end => commit data
			if (line=="###")
			{
				//import data
				auto it = transcripts.begin();
				while(it!=transcripts.end())
				{
					//add Ensembl transcript
					TranscriptData& t_data = it.value();
					int trans_id = addTranscript(q_trans, t_data.ngsd_gene_id, t_data.name , "ensembl", t_data);
					//add exons
					t_data.exons.merge();
					addExons(q_exon, trans_id, t_data.exons);

					//add CCDS transcript as well (only once)
					if (t_data.name_ccds!="" && !ccds_transcripts_added.contains(t_data.name_ccds))
					{
						int trans_id_ccds = addTranscript(q_trans, t_data.ngsd_gene_id, t_data.name_ccds , "ccds", t_data);
						//add exons (only coding part)
						BedFile coding_part;
						coding_part.append(BedLine(t_data.exons[0].chr() ,t_data.start_coding, t_data.end_coding));
						t_data.exons.intersect(coding_part);
						addExons(q_exon, trans_id_ccds, t_data.exons);

						ccds_transcripts_added.insert(t_data.name_ccds);
					}
					++it;
				}

				//clear cache
				gene_ensemble2ngsd.clear();
				transcripts.clear();
				continue;
			}

			//skip header lines
			if (line.startsWith("#")) continue;

			QByteArrayList parts = line.split('\t');
			QByteArray type = parts[2];
			QMap<QByteArray, QByteArray> data = parseAttributes(parts[8]);

			//gene line
			if (data.contains("gene_id"))
			{
				QByteArray gene = data["Name"];

				//transform gene names to approved gene IDs
				int ngsd_gene_id = db.geneToApprovedID(gene);
				if (ngsd_gene_id==-1)
				{
					out << "ERROR " << data["gene_id"] << "/" << gene << ": no approved gene names found." << endl;
					continue;
				}
				gene_ensemble2ngsd[data["ID"]] = ngsd_gene_id;
			}

			//transcript line
			else if (data.contains("transcript_id"))
			{
				if (all || data.value("tag")=="basic")
				{
					TranscriptData tmp;
					tmp.name = data["transcript_id"];
					tmp.name_ccds = data.value("ccdsid", "");
					tmp.chr = parts[0];
					tmp.strand = parts[6];
					tmp.ngsd_gene_id = gene_ensemble2ngsd[data["Parent"]];
					transcripts[data["ID"]] = tmp;
				}
			}

			//exon lines
			else if (type=="CDS" || type=="exon" || type=="three_prime_UTR" || type=="five_prime_UTR" )
			{
				QByteArray parent_id = data["Parent"];

				//skip exons of unhandled transcripts (not GENCODE basic)
				if (!transcripts.contains(parent_id)) continue;
				TranscriptData& t_data = transcripts[parent_id];

				//check chromosome matches
				QByteArray chr = parts[0];
				if (chr!=t_data.chr)
				{
					THROW(FileParseException, "Chromosome mismach between transcript and exon!");
				}

				//update coding start/end
				int start = Helper::toInt(parts[3], "start position");
				int end = Helper::toInt(parts[4], "end position");

				if (type=="CDS")
				{
					t_data.start_coding = (t_data.start_coding==-1) ? start : std::min(start, t_data.start_coding);
					t_data.end_coding = (t_data.end_coding==-1) ? end : std::max(end, t_data.end_coding);
				}

				//add coding exon
				t_data.exons.append(BedLine(chr, start, end));
			}
		}
	}
};

#include "main.moc"

int main(int argc, char *argv[])
{
	ConcreteTool tool(argc, argv);
	return tool.execute();
}
<|endoftext|>


<commit_before>// For conditions of distribution and use, see copyright notice in license.txt

#include "StableHeaders.h"
#include "DebugOperatorNew.h"

#include "NaaliApplication.h"
#include "Framework.h"
#include "ConfigurationManager.h"
#include "CoreStringUtils.h"

#include <QDir>
#include <QGraphicsView>
#include <QTranslator>
#include <QLocale>
#include <QIcon>
#include <QWebSettings>

#include "MemoryLeakCheck.h"

namespace Foundation
{
    NaaliApplication::NaaliApplication(Framework *framework_, int &argc, char **argv) :
        QApplication(argc, argv),
        framework(framework_),
        appActivated(true),
        nativeTranslator(new QTranslator),
        appTranslator(new QTranslator)
    {
        QApplication::setApplicationName("realXtend-Naali");

#ifdef Q_WS_WIN

        // On Windows the current directory have to be the application installation directory
//        QDir::setCurrent(applicationDirPath());

        // If under windows, add run_dir/plugins as library path
        // unix users will get plugins from their OS Qt installation folder automatically

        QString runDirectory = QString::fromStdString(ReplaceChar(framework->GetPlatform()->GetInstallDirectory(), '\\', '/'));
        runDirectory += "/qtplugins";
        addLibraryPath(runDirectory);
#endif

        QDir dir("data/translations/qt_native_translations");
        QStringList qmFiles = GetQmFiles(dir);

        // Search then that is there corresponding native translations for system locals.
        QString loc = QLocale::system().name();
        loc.chop(3);

        QString name = "data/translations/qt_native_translations/qt_" + loc + ".qm";
        QStringList lst = qmFiles.filter(name);
        if (!lst.empty() )
            nativeTranslator->load(lst[0]);

        this->installTranslator(nativeTranslator);

        std::string default_language = framework->GetConfigManager()->DeclareSetting(Framework::ConfigurationGroup(),
            "language", std::string("data/translations/naali_en"));
        ChangeLanguage(QString::fromStdString(default_language));

        QWebSettings::globalSettings()->setAttribute(QWebSettings::PluginsEnabled, true); //enablig flash
    }

    NaaliApplication::~NaaliApplication()
    {
        SAFE_DELETE(nativeTranslator);
        SAFE_DELETE(appTranslator);
    }

    QStringList NaaliApplication::GetQmFiles(const QDir& dir)
    {
         QStringList fileNames = dir.entryList(QStringList("*.qm"), QDir::Files, QDir::Name);
         QMutableStringListIterator i(fileNames);
         while (i.hasNext())
         {
             i.next();
             i.setValue(dir.filePath(i.value()));
         }
         return fileNames;
    }

    void NaaliApplication::Go()
    {
        installEventFilter(this);

        QObject::connect(&frameUpdateTimer, SIGNAL(timeout()), this, SLOT(UpdateFrame()));
        frameUpdateTimer.setSingleShot(true);
        frameUpdateTimer.start(0);

        try
        {
            exec ();
        }
        catch(const std::exception &e)
        {
            RootLogCritical(std::string("NaaliApplication::Go caught an exception: ") + (e.what() ? e.what() : "(null)"));
            throw;
        }
        catch(...)
        {
            RootLogCritical(std::string("NaaliApplication::Go caught an unknown exception!"));
            throw;
        }
    }

    bool NaaliApplication::eventFilter(QObject *obj, QEvent *event)
    {
        try
        {
            if (obj == this)
            {
                if (event->type() == QEvent::ApplicationActivate)
                    appActivated = true;
                if (event->type() == QEvent::ApplicationDeactivate)
                    appActivated = false;
            }
            return QObject::eventFilter(obj, event);
        }
        catch(const std::exception &e)
        {
            std::cout << std::string("QApp::eventFilter caught an exception: ") + (e.what() ? e.what() : "(null)") << std::endl;
            RootLogCritical(std::string("QApp::eventFilter caught an exception: ") + (e.what() ? e.what() : "(null)"));
            throw;
        } catch(...)
        {
            std::cout << std::string("QApp::eventFilter caught an unknown exception!") << std::endl;
            RootLogCritical(std::string("QApp::eventFilter caught an unknown exception!"));
            throw;
        }
        return true;
    }

    void NaaliApplication::ChangeLanguage(const QString& file)
    {
        QString filename = file;
        if (!filename.endsWith(".qm", Qt::CaseInsensitive))
            filename.append(".qm");
        QString tmp = filename;
        tmp.chop(3);
        QString str = tmp.right(2);

        QString name = "data/translations/qt_native_translations/qt_" + str + ".qm";

        // Remove old translators then change them to new.
        removeTranslator(nativeTranslator);

        if (QFile::exists(name))
        {
            if (nativeTranslator != 0)
            {
                nativeTranslator->load(name);
                installTranslator(nativeTranslator);
            }
        }
        else
        {
            if (nativeTranslator != 0 && nativeTranslator->isEmpty())
            {
                installTranslator(nativeTranslator);
            }
            else
            {
                SAFE_DELETE(nativeTranslator);
                nativeTranslator = new QTranslator;
                installTranslator(nativeTranslator);
            }
        }

        // Remove old translators then change them to new.
        removeTranslator(appTranslator);
        if (appTranslator->load(filename))
        {
            installTranslator(appTranslator);
            framework->GetConfigManager()->SetSetting(Framework::ConfigurationGroup(), "language", file.toStdString());
        }

        emit LanguageChanged();
    }

    bool NaaliApplication::notify(QObject *receiver, QEvent *event)
    {
        try
        {
            return QApplication::notify(receiver, event);
        } catch(const std::exception &e)
        {
            std::cout << std::string("QApp::notify caught an exception: ") << (e.what() ? e.what() : "(null)") << std::endl;
            RootLogCritical(std::string("QApp::notify caught an exception: ") + (e.what() ? e.what() : "(null)"));
            throw;
        } catch(...)
        {
            std::cout << std::string("QApp::notify caught an unknown exception!") << std::endl;
            RootLogCritical(std::string("QApp::notify caught an unknown exception!"));
            throw;
        }
    }

    void NaaliApplication::UpdateFrame()
    {
        try
        {
            QApplication::processEvents(QEventLoop::AllEvents, 1);
            QApplication::sendPostedEvents();

            framework->ProcessOneFrame();

            // Reduce framerate when unfocused
            if (appActivated)
                frameUpdateTimer.start(0);
            else
                frameUpdateTimer.start(5);
        }
        catch(const std::exception &e)
        {
            std::cout << "QApp::UpdateFrame caught an exception: " << (e.what() ? e.what() : "(null)") << std::endl;
            RootLogCritical(std::string("QApp::UpdateFrame caught an exception: ") + (e.what() ? e.what() : "(null)"));
            throw;
        }
        catch(...)
        {
            std::cout << "QApp::UpdateFrame caught an unknown exception!" << std::endl;
            RootLogCritical(std::string("QApp::UpdateFrame caught an unknown exception!"));
            throw;
        }
    }

    void NaaliApplication::AboutToExit()
    {
        emit ExitRequested();

        // If no-one canceled the exit as a response to the signal, exit
        if (framework->IsExiting())
            quit();
    }
}
<commit_msg>Removed wrongly applied setcwd command from startup.<commit_after>// For conditions of distribution and use, see copyright notice in license.txt

#include "StableHeaders.h"
#include "DebugOperatorNew.h"

#include "NaaliApplication.h"
#include "Framework.h"
#include "ConfigurationManager.h"
#include "CoreStringUtils.h"

#include <QDir>
#include <QGraphicsView>
#include <QTranslator>
#include <QLocale>
#include <QIcon>
#include <QWebSettings>

#include "MemoryLeakCheck.h"

namespace Foundation
{
    NaaliApplication::NaaliApplication(Framework *framework_, int &argc, char **argv) :
        QApplication(argc, argv),
        framework(framework_),
        appActivated(true),
        nativeTranslator(new QTranslator),
        appTranslator(new QTranslator)
    {
        QApplication::setApplicationName("realXtend-Naali");

#ifdef Q_WS_WIN
        // If under windows, add run_dir/plugins as library path
        // unix users will get plugins from their OS Qt installation folder automatically

        QString runDirectory = QString::fromStdString(ReplaceChar(framework->GetPlatform()->GetInstallDirectory(), '\\', '/'));
        runDirectory += "/qtplugins";
        addLibraryPath(runDirectory);
#endif

        QDir dir("data/translations/qt_native_translations");
        QStringList qmFiles = GetQmFiles(dir);

        // Search then that is there corresponding native translations for system locals.
        QString loc = QLocale::system().name();
        loc.chop(3);

        QString name = "data/translations/qt_native_translations/qt_" + loc + ".qm";
        QStringList lst = qmFiles.filter(name);
        if (!lst.empty() )
            nativeTranslator->load(lst[0]);

        this->installTranslator(nativeTranslator);

        std::string default_language = framework->GetConfigManager()->DeclareSetting(Framework::ConfigurationGroup(),
            "language", std::string("data/translations/naali_en"));
        ChangeLanguage(QString::fromStdString(default_language));

        QWebSettings::globalSettings()->setAttribute(QWebSettings::PluginsEnabled, true); //enablig flash
    }

    NaaliApplication::~NaaliApplication()
    {
        SAFE_DELETE(nativeTranslator);
        SAFE_DELETE(appTranslator);
    }

    QStringList NaaliApplication::GetQmFiles(const QDir& dir)
    {
         QStringList fileNames = dir.entryList(QStringList("*.qm"), QDir::Files, QDir::Name);
         QMutableStringListIterator i(fileNames);
         while (i.hasNext())
         {
             i.next();
             i.setValue(dir.filePath(i.value()));
         }
         return fileNames;
    }

    void NaaliApplication::Go()
    {
        installEventFilter(this);

        QObject::connect(&frameUpdateTimer, SIGNAL(timeout()), this, SLOT(UpdateFrame()));
        frameUpdateTimer.setSingleShot(true);
        frameUpdateTimer.start(0);

        try
        {
            exec ();
        }
        catch(const std::exception &e)
        {
            RootLogCritical(std::string("NaaliApplication::Go caught an exception: ") + (e.what() ? e.what() : "(null)"));
            throw;
        }
        catch(...)
        {
            RootLogCritical(std::string("NaaliApplication::Go caught an unknown exception!"));
            throw;
        }
    }

    bool NaaliApplication::eventFilter(QObject *obj, QEvent *event)
    {
        try
        {
            if (obj == this)
            {
                if (event->type() == QEvent::ApplicationActivate)
                    appActivated = true;
                if (event->type() == QEvent::ApplicationDeactivate)
                    appActivated = false;
            }
            return QObject::eventFilter(obj, event);
        }
        catch(const std::exception &e)
        {
            std::cout << std::string("QApp::eventFilter caught an exception: ") + (e.what() ? e.what() : "(null)") << std::endl;
            RootLogCritical(std::string("QApp::eventFilter caught an exception: ") + (e.what() ? e.what() : "(null)"));
            throw;
        } catch(...)
        {
            std::cout << std::string("QApp::eventFilter caught an unknown exception!") << std::endl;
            RootLogCritical(std::string("QApp::eventFilter caught an unknown exception!"));
            throw;
        }
        return true;
    }

    void NaaliApplication::ChangeLanguage(const QString& file)
    {
        QString filename = file;
        if (!filename.endsWith(".qm", Qt::CaseInsensitive))
            filename.append(".qm");
        QString tmp = filename;
        tmp.chop(3);
        QString str = tmp.right(2);

        QString name = "data/translations/qt_native_translations/qt_" + str + ".qm";

        // Remove old translators then change them to new.
        removeTranslator(nativeTranslator);

        if (QFile::exists(name))
        {
            if (nativeTranslator != 0)
            {
                nativeTranslator->load(name);
                installTranslator(nativeTranslator);
            }
        }
        else
        {
            if (nativeTranslator != 0 && nativeTranslator->isEmpty())
            {
                installTranslator(nativeTranslator);
            }
            else
            {
                SAFE_DELETE(nativeTranslator);
                nativeTranslator = new QTranslator;
                installTranslator(nativeTranslator);
            }
        }

        // Remove old translators then change them to new.
        removeTranslator(appTranslator);
        if (appTranslator->load(filename))
        {
            installTranslator(appTranslator);
            framework->GetConfigManager()->SetSetting(Framework::ConfigurationGroup(), "language", file.toStdString());
        }

        emit LanguageChanged();
    }

    bool NaaliApplication::notify(QObject *receiver, QEvent *event)
    {
        try
        {
            return QApplication::notify(receiver, event);
        } catch(const std::exception &e)
        {
            std::cout << std::string("QApp::notify caught an exception: ") << (e.what() ? e.what() : "(null)") << std::endl;
            RootLogCritical(std::string("QApp::notify caught an exception: ") + (e.what() ? e.what() : "(null)"));
            throw;
        } catch(...)
        {
            std::cout << std::string("QApp::notify caught an unknown exception!") << std::endl;
            RootLogCritical(std::string("QApp::notify caught an unknown exception!"));
            throw;
        }
    }

    void NaaliApplication::UpdateFrame()
    {
        try
        {
            QApplication::processEvents(QEventLoop::AllEvents, 1);
            QApplication::sendPostedEvents();

            framework->ProcessOneFrame();

            // Reduce framerate when unfocused
            if (appActivated)
                frameUpdateTimer.start(0);
            else
                frameUpdateTimer.start(5);
        }
        catch(const std::exception &e)
        {
            std::cout << "QApp::UpdateFrame caught an exception: " << (e.what() ? e.what() : "(null)") << std::endl;
            RootLogCritical(std::string("QApp::UpdateFrame caught an exception: ") + (e.what() ? e.what() : "(null)"));
            throw;
        }
        catch(...)
        {
            std::cout << "QApp::UpdateFrame caught an unknown exception!" << std::endl;
            RootLogCritical(std::string("QApp::UpdateFrame caught an unknown exception!"));
            throw;
        }
    }

    void NaaliApplication::AboutToExit()
    {
        emit ExitRequested();

        // If no-one canceled the exit as a response to the signal, exit
        if (framework->IsExiting())
            quit();
    }
}
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "..\includes\CPatch.h"
#include "..\includes\IniReader.h"

HWND hWnd;
DWORD jmpAddress;
void patch_res();

void patch_res_x1(), patch_res_x2(), patch_res_x3(), patch_res_x4(), patch_res_x5(), patch_res_x6(), patch_res_x7(), patch_res_x8(), patch_res_x9(), patch_res_x10();
void patch_res_y1(), patch_res_y2(), patch_res_y3(), patch_res_y4(), patch_res_y5(), patch_res_y6(), patch_res_y7();
void patch_player_a(); void patch_player_a2();

int res_x;
int res_y;
int res_x43;

DWORD WINAPI Thread(LPVOID)
{
	CPatch::RedirectJump(0x42B512, patch_player_a);
	CPatch::RedirectJump(0x4274FF, patch_player_a2);

	CIniReader iniReader("gta1_res.ini");
	res_x = iniReader.ReadInteger("MAIN", "X", 0);
	res_y = iniReader.ReadInteger("MAIN", "Y", 0);

	if (!res_x || !res_y) {
		HMONITOR monitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
		MONITORINFO info;
		info.cbSize = sizeof(MONITORINFO);
		GetMonitorInfo(monitor, &info);
		res_x = info.rcMonitor.right - info.rcMonitor.left;
		res_y = info.rcMonitor.bottom - info.rcMonitor.top;
	}

	CPatch::RedirectJump(0x491E4C, patch_res);

	CPatch::RedirectJump(0x414FF7, patch_res_x1);
	CPatch::RedirectJump(0x43B7CF, patch_res_x2);

	res_x43 = static_cast<int>(res_y * (4.0f / 3.0f));
	CPatch::RedirectJump(0x46453B, patch_res_x3);
	//CPatch::RedirectJump(0x46452C, patch_res_x4);
	//CPatch::RedirectJump(0x486848, patch_res_x5);
	//CPatch::RedirectJump(0x486852, patch_res_x6);
	/*CPatch::RedirectJump(0x48C137, patch_res_x7);
	CPatch::RedirectJump(0x48C276, patch_res_x8);
	CPatch::RedirectJump(0x48C159, patch_res_x9);*/
	//CPatch::RedirectJump(0x49168B, patch_res_x10);

	CPatch::RedirectJump(0x415008, patch_res_y1);
	CPatch::RedirectJump(0x43B7D8, patch_res_y2);
	CPatch::RedirectJump(0x464532, patch_res_y3);
	CPatch::RedirectJump(0x48683A, patch_res_y4);
	CPatch::RedirectJump(0x48C13D, patch_res_y5);
	CPatch::RedirectJump(0x48C2B0, patch_res_y6);
	//CPatch::RedirectJump(0x, patch_res_y7);

	//menu
	CPatch::SetUInt(0x4898C3 + 0x1, res_x);
	return 0;
}

void __declspec(naked)patch_res()
{
	_asm
	{
		mov eax, res_x
		MOV DWORD PTR DS : [0x787310], EAX
		MOV DWORD PTR DS : [0x787370], EAX
		MOV EAX, DWORD PTR DS : [EBX + 1B4h]
		INC EAX
		TEST ECX, ECX
		mov eax, res_y
		MOV DWORD PTR DS : [0x787314], EAX
		MOV DWORD PTR DS : [0x787388], EAX

		mov jmpAddress, 0x491E69
		jmp jmpAddress
	}
}

void __declspec(naked)patch_res_x1()
{
	_asm
	{
		mov eax, res_x
		MOV DWORD PTR DS : [0x504CC0], EAX
		mov jmpAddress, 0x414FFC
		jmp jmpAddress
	}
}

void __declspec(naked)patch_res_x2()
{
	_asm
	{
		mov edx, res_x
		MOV DWORD PTR DS : [0x5C0C00], EDX
		mov jmpAddress, 0x43B7D5
		jmp jmpAddress
	}
}

void __declspec(naked)patch_res_x3()
{
	_asm
	{
		mov esi, res_x43
		MOV DWORD PTR DS : [ECX + 0x74F168], ESI
		mov jmpAddress, 0x464541
		jmp jmpAddress
	}
}

void __declspec(naked)patch_res_x4()
{
	_asm
	{
		mov edx, res_x
		MOV DWORD PTR DS : [ECX + 0x74F170], EDX

		mov jmpAddress, 0x464532
		jmp jmpAddress
	}
}

void __declspec(naked)patch_res_x5()
{
	_asm
	{
		mov ecx, res_x
		MOV DWORD PTR DS : [0x785170], ECX
		mov jmpAddress, 0x48684E
		jmp jmpAddress
	}
}

void __declspec(naked)patch_res_x6()
{
	_asm
	{
		mov ecx, res_x
		MOV DWORD PTR DS : [0x785178], ECX
		mov jmpAddress, 0x486858
		jmp jmpAddress
	}
}

void __declspec(naked)patch_res_x7()
{
	_asm
	{
		mov esi, res_x
		MOV DWORD PTR DS : [0x787AD4], ESI
		mov jmpAddress, 0x48C13D
		jmp jmpAddress
	}
}

void __declspec(naked)patch_res_x8()
{
	_asm
	{
		mov eax, res_x
		MOV DWORD PTR DS : [0x787AEC], EAX
		mov jmpAddress, 0x48C27B
		jmp jmpAddress
	}
}

void __declspec(naked)patch_res_x9()
{
	_asm
	{
		mov eax, res_x
		MOV DWORD PTR DS : [0x787CB0], EAX
		mov jmpAddress, 0x48C15E
		jmp jmpAddress
	}
}

void __declspec(naked)patch_res_x10()
{
	_asm
	{
		mov eax, res_x
		MOV DWORD PTR DS : [EDI + 16Ch], EAX
		mov jmpAddress, 0x491691
		jmp jmpAddress
	}
}

void __declspec(naked)patch_res_y1()
{
	_asm
	{
		mov eax, res_y
		MOV DWORD PTR DS : [0x504CC4], EAX
		mov jmpAddress, 0x41500D
		jmp jmpAddress
	}
}

void __declspec(naked)patch_res_y2()
{
	_asm
	{
		mov eax, res_y
		MOV DWORD PTR DS : [0x5BFAB0], EAX
		mov jmpAddress, 0x43B7DD
		jmp jmpAddress
	}
}

void __declspec(naked)patch_res_y3()
{
	_asm
	{
		mov edi, res_y
		MOV DWORD PTR DS : [ECX + 0x74F16C], EDI
		mov jmpAddress, 0x464538
		jmp jmpAddress
	}
}

void __declspec(naked)patch_res_y4()
{
	_asm
	{
		mov edx, res_y
		MOV DWORD PTR DS : [0x785174], EDX
		mov jmpAddress, 0x486840
		jmp jmpAddress
	}
}

void __declspec(naked)patch_res_y5()
{
	_asm
	{
		mov edi, res_y
		MOV DWORD PTR DS : [0x787AD8], EDI
		mov jmpAddress, 0x48C143
		jmp jmpAddress
	}
}

void __declspec(naked)patch_res_y6()
{
	_asm
	{
		mov eax, res_y
		MOV DWORD PTR DS : [0x787AF0], EAX
		mov jmpAddress, 0x48C2B5
		jmp jmpAddress
	}
}

void __declspec(naked)patch_res_y7()
{
	_asm
	{
		mov edx, res_y
		MOV DWORD PTR DS : [0x4B48C0], EDX
		mov jmpAddress, 0x48AE8B
		jmp jmpAddress
	}
}

void __declspec(naked)patch_player_a()
{
	_asm
	{
		MOV BYTE PTR DS : [0x51029C], 0x06
		mov jmpAddress, 0x42B518
		jmp jmpAddress
	}
}

void __declspec(naked)patch_player_a2()
{
	_asm
	{
		MOV BYTE PTR DS : [0x51029C], 0x06
		mov jmpAddress, 0x427504
		jmp jmpAddress
	}
}

BOOL APIENTRY DllMain(HMODULE /*hModule*/, DWORD reason, LPVOID /*lpReserved*/)
{
	if (reason == DLL_PROCESS_ATTACH)
	{
		CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&Thread, NULL, 0, NULL);
	}
	return TRUE;
}

<commit_msg>WFP v2.9.2<commit_after>#include "stdafx.h"
#include "..\includes\CPatch.h"
#include "..\includes\IniReader.h"

HWND hWnd;
DWORD jmpAddress;
void patch_res();

void patch_res_x1(), patch_res_x2(), patch_res_x3(), patch_res_x4(), patch_res_x5(), patch_res_x6(), patch_res_x7(), patch_res_x8(), patch_res_x9(), patch_res_x10();
void patch_res_y1(), patch_res_y2(), patch_res_y3(), patch_res_y4(), patch_res_y5(), patch_res_y6(), patch_res_y7();
void patch_player_a(); void patch_player_a2();

int res_x;
int res_y;
int res_x43;
int Var_480 = 480;

DWORD WINAPI Thread(LPVOID)
{
	CPatch::RedirectJump(0x42B512, patch_player_a);
	CPatch::RedirectJump(0x4274FF, patch_player_a2);

	CIniReader iniReader("gta1_res.ini");
	res_x = iniReader.ReadInteger("MAIN", "X", 0);
	res_y = iniReader.ReadInteger("MAIN", "Y", 0);

	if (!res_x || !res_y) {
		HMONITOR monitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
		MONITORINFO info;
		info.cbSize = sizeof(MONITORINFO);
		GetMonitorInfo(monitor, &info);
		res_x = info.rcMonitor.right - info.rcMonitor.left;
		res_y = info.rcMonitor.bottom - info.rcMonitor.top;
	}

	CPatch::RedirectJump(0x491E4C, patch_res);

	CPatch::RedirectJump(0x414FF7, patch_res_x1);
	CPatch::RedirectJump(0x43B7CF, patch_res_x2);

	res_x43 = static_cast<int>(res_y * (4.0f / 3.0f));
	CPatch::RedirectJump(0x46453B, patch_res_x3);
	//CPatch::RedirectJump(0x46452C, patch_res_x4);
	//CPatch::RedirectJump(0x486848, patch_res_x5);
	//CPatch::RedirectJump(0x486852, patch_res_x6);
	/*CPatch::RedirectJump(0x48C137, patch_res_x7);
	CPatch::RedirectJump(0x48C276, patch_res_x8);
	CPatch::RedirectJump(0x48C159, patch_res_x9);*/
	//CPatch::RedirectJump(0x49168B, patch_res_x10);

	CPatch::RedirectJump(0x415008, patch_res_y1);
	CPatch::RedirectJump(0x43B7D8, patch_res_y2);
	CPatch::RedirectJump(0x464532, patch_res_y3);
	CPatch::RedirectJump(0x48683A, patch_res_y4);
	CPatch::RedirectJump(0x48C13D, patch_res_y5);
	CPatch::RedirectJump(0x48C2B0, patch_res_y6);
	//CPatch::RedirectJump(0x, patch_res_y7);

	//menu
	CPatch::SetUInt(0x4898C3 + 0x1, res_x);

	//FMV crashfix
	//CPatch::SetPointer(0x4152D6 + 2, &Var_640);
	//CPatch::SetPointer(0x4152E7 + 1, &Var_480);

	CPatch::SetPointer(0x42D830 + 0xA + 1, &Var_480);
	CPatch::SetPointer(0x42D830 + 0x5B + 2, &Var_480);
	CPatch::SetPointer(0x42D830 + 0x9C + 2, &Var_480);

	//CPatch::SetPointer(0x42D830 + 0x3B + 2, &Var_640);
	//CPatch::SetPointer(0x42D830 + 0x71 + 2, &Var_640);
	return 0;
}

void __declspec(naked)patch_res()
{
	_asm
	{
		mov eax, res_x
		MOV DWORD PTR DS : [0x787310], EAX
		MOV DWORD PTR DS : [0x787370], EAX
		MOV EAX, DWORD PTR DS : [EBX + 1B4h]
		INC EAX
		TEST ECX, ECX
		mov eax, res_y
		MOV DWORD PTR DS : [0x787314], EAX
		MOV DWORD PTR DS : [0x787388], EAX

		mov jmpAddress, 0x491E69
		jmp jmpAddress
	}
}

void __declspec(naked)patch_res_x1()
{
	_asm
	{
		mov eax, res_x
		MOV DWORD PTR DS : [0x504CC0], EAX
		mov jmpAddress, 0x414FFC
		jmp jmpAddress
	}
}

void __declspec(naked)patch_res_x2()
{
	_asm
	{
		mov edx, res_x
		MOV DWORD PTR DS : [0x5C0C00], EDX
		mov jmpAddress, 0x43B7D5
		jmp jmpAddress
	}
}

void __declspec(naked)patch_res_x3()
{
	_asm
	{
		mov esi, res_x43
		MOV DWORD PTR DS : [ECX + 0x74F168], ESI
		mov jmpAddress, 0x464541
		jmp jmpAddress
	}
}

void __declspec(naked)patch_res_x4()
{
	_asm
	{
		mov edx, res_x
		MOV DWORD PTR DS : [ECX + 0x74F170], EDX

		mov jmpAddress, 0x464532
		jmp jmpAddress
	}
}

void __declspec(naked)patch_res_x5()
{
	_asm
	{
		mov ecx, res_x
		MOV DWORD PTR DS : [0x785170], ECX
		mov jmpAddress, 0x48684E
		jmp jmpAddress
	}
}

void __declspec(naked)patch_res_x6()
{
	_asm
	{
		mov ecx, res_x
		MOV DWORD PTR DS : [0x785178], ECX
		mov jmpAddress, 0x486858
		jmp jmpAddress
	}
}

void __declspec(naked)patch_res_x7()
{
	_asm
	{
		mov esi, res_x
		MOV DWORD PTR DS : [0x787AD4], ESI
		mov jmpAddress, 0x48C13D
		jmp jmpAddress
	}
}

void __declspec(naked)patch_res_x8()
{
	_asm
	{
		mov eax, res_x
		MOV DWORD PTR DS : [0x787AEC], EAX
		mov jmpAddress, 0x48C27B
		jmp jmpAddress
	}
}

void __declspec(naked)patch_res_x9()
{
	_asm
	{
		mov eax, res_x
		MOV DWORD PTR DS : [0x787CB0], EAX
		mov jmpAddress, 0x48C15E
		jmp jmpAddress
	}
}

void __declspec(naked)patch_res_x10()
{
	_asm
	{
		mov eax, res_x
		MOV DWORD PTR DS : [EDI + 16Ch], EAX
		mov jmpAddress, 0x491691
		jmp jmpAddress
	}
}

void __declspec(naked)patch_res_y1()
{
	_asm
	{
		mov eax, res_y
		MOV DWORD PTR DS : [0x504CC4], EAX
		mov jmpAddress, 0x41500D
		jmp jmpAddress
	}
}

void __declspec(naked)patch_res_y2()
{
	_asm
	{
		mov eax, res_y
		MOV DWORD PTR DS : [0x5BFAB0], EAX
		mov jmpAddress, 0x43B7DD
		jmp jmpAddress
	}
}

void __declspec(naked)patch_res_y3()
{
	_asm
	{
		mov edi, res_y
		MOV DWORD PTR DS : [ECX + 0x74F16C], EDI
		mov jmpAddress, 0x464538
		jmp jmpAddress
	}
}

void __declspec(naked)patch_res_y4()
{
	_asm
	{
		mov edx, res_y
		MOV DWORD PTR DS : [0x785174], EDX
		mov jmpAddress, 0x486840
		jmp jmpAddress
	}
}

void __declspec(naked)patch_res_y5()
{
	_asm
	{
		mov edi, res_y
		MOV DWORD PTR DS : [0x787AD8], EDI
		mov jmpAddress, 0x48C143
		jmp jmpAddress
	}
}

void __declspec(naked)patch_res_y6()
{
	_asm
	{
		mov eax, res_y
		MOV DWORD PTR DS : [0x787AF0], EAX
		mov jmpAddress, 0x48C2B5
		jmp jmpAddress
	}
}

void __declspec(naked)patch_res_y7()
{
	_asm
	{
		mov edx, res_y
		MOV DWORD PTR DS : [0x4B48C0], EDX
		mov jmpAddress, 0x48AE8B
		jmp jmpAddress
	}
}

void __declspec(naked)patch_player_a()
{
	_asm
	{
		MOV BYTE PTR DS : [0x51029C], 0x06
		mov jmpAddress, 0x42B518
		jmp jmpAddress
	}
}

void __declspec(naked)patch_player_a2()
{
	_asm
	{
		MOV BYTE PTR DS : [0x51029C], 0x06
		mov jmpAddress, 0x427504
		jmp jmpAddress
	}
}

BOOL APIENTRY DllMain(HMODULE /*hModule*/, DWORD reason, LPVOID /*lpReserved*/)
{
	if (reason == DLL_PROCESS_ATTACH)
	{
		CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&Thread, NULL, 0, NULL);
	}
	return TRUE;
}

<|endoftext|>


<commit_before>// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "build/build_config.h"
#include "cc/layers/solid_color_layer.h"
#include "cc/test/layer_tree_pixel_test.h"
#include "cc/test/pixel_comparator.h"

#if !defined(OS_ANDROID)

namespace cc {
namespace {

class LayerTreeHostFiltersPixelTest : public LayerTreePixelTest {};

TEST_F(LayerTreeHostFiltersPixelTest, BackgroundFilterBlur) {
  scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer(
      gfx::Rect(200, 200), SK_ColorWHITE);

  // The green box is entirely behind a layer with background blur, so it
  // should appear blurred on its edges.
  scoped_refptr<SolidColorLayer> green = CreateSolidColorLayer(
      gfx::Rect(50, 50, 100, 100), kCSSGreen);
  scoped_refptr<SolidColorLayer> blur = CreateSolidColorLayer(
      gfx::Rect(30, 30, 140, 140), SK_ColorTRANSPARENT);
  background->AddChild(green);
  background->AddChild(blur);

  FilterOperations filters;
  filters.Append(FilterOperation::CreateBlurFilter(2.f));
  blur->SetBackgroundFilters(filters);

#if defined(OS_WIN)
  // Windows has 436 pixels off by 1: crbug.com/259915
  float percentage_pixels_large_error = 1.09f;  // 436px / (200*200)
  float percentage_pixels_small_error = 0.0f;
  float average_error_allowed_in_bad_pixels = 1.f;
  int large_error_allowed = 1;
  int small_error_allowed = 0;
  pixel_comparator_.reset(new FuzzyPixelComparator(
      true,  // discard_alpha
      percentage_pixels_large_error,
      percentage_pixels_small_error,
      average_error_allowed_in_bad_pixels,
      large_error_allowed,
      small_error_allowed));
#endif

  RunPixelTest(GL_WITH_BITMAP,
               background,
               base::FilePath(FILE_PATH_LITERAL("background_filter_blur.png")));
}

TEST_F(LayerTreeHostFiltersPixelTest, DISABLED_BackgroundFilterBlurOutsets) {
  scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer(
      gfx::Rect(200, 200), SK_ColorWHITE);

  // The green border is outside the layer with background blur, but the
  // background blur should use pixels from outside its layer borders, up to the
  // radius of the blur effect. So the border should be blurred underneath the
  // top layer causing the green to bleed under the transparent layer, but not
  // in the 1px region between the transparent layer and the green border.
  scoped_refptr<SolidColorLayer> green_border = CreateSolidColorLayerWithBorder(
      gfx::Rect(1, 1, 198, 198), SK_ColorWHITE, 10, kCSSGreen);
  scoped_refptr<SolidColorLayer> blur = CreateSolidColorLayer(
      gfx::Rect(12, 12, 176, 176), SK_ColorTRANSPARENT);
  background->AddChild(green_border);
  background->AddChild(blur);

  FilterOperations filters;
  filters.Append(FilterOperation::CreateBlurFilter(5.f));
  blur->SetBackgroundFilters(filters);

#if defined(OS_WIN)
  // Windows has 2250 pixels off by at most 2: crbug.com/259922
  float percentage_pixels_large_error = 5.625f;  // 2250px / (200*200)
  float percentage_pixels_small_error = 0.0f;
  float average_error_allowed_in_bad_pixels = 1.f;
  int large_error_allowed = 2;
  int small_error_allowed = 0;
  pixel_comparator_.reset(new FuzzyPixelComparator(
      true,  // discard_alpha
      percentage_pixels_large_error,
      percentage_pixels_small_error,
      average_error_allowed_in_bad_pixels,
      large_error_allowed,
      small_error_allowed));
#endif

  RunPixelTest(GL_WITH_BITMAP,
               background,
               base::FilePath(FILE_PATH_LITERAL(
                   "background_filter_blur_outsets.png")));
}

TEST_F(LayerTreeHostFiltersPixelTest, BackgroundFilterBlurOffAxis) {
  scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer(
      gfx::Rect(200, 200), SK_ColorWHITE);

  // This verifies that the perspective of the clear layer (with black border)
  // does not influence the blending of the green box behind it. Also verifies
  // that the blur is correctly clipped inside the transformed clear layer.
  scoped_refptr<SolidColorLayer> green = CreateSolidColorLayer(
      gfx::Rect(50, 50, 100, 100), kCSSGreen);
  scoped_refptr<SolidColorLayer> blur = CreateSolidColorLayerWithBorder(
      gfx::Rect(30, 30, 120, 120), SK_ColorTRANSPARENT, 1, SK_ColorBLACK);
  background->AddChild(green);
  background->AddChild(blur);

  background->SetPreserves3d(true);
  gfx::Transform background_transform;
  background_transform.ApplyPerspectiveDepth(200.0);
  background->SetTransform(background_transform);

  blur->SetPreserves3d(true);
  gfx::Transform blur_transform;
  blur_transform.Translate(55.0, 65.0);
  blur_transform.RotateAboutXAxis(85.0);
  blur_transform.RotateAboutYAxis(180.0);
  blur_transform.RotateAboutZAxis(20.0);
  blur_transform.Translate(-60.0, -60.0);
  blur->SetTransform(blur_transform);

  FilterOperations filters;
  filters.Append(FilterOperation::CreateBlurFilter(2.f));
  blur->SetBackgroundFilters(filters);

#if defined(OS_WIN)
  // Windows has 151 pixels off by at most 2: crbug.com/225027
  float percentage_pixels_large_error = 0.3775f;  // 151px / (200*200)
  float percentage_pixels_small_error = 0.0f;
  float average_error_allowed_in_bad_pixels = 1.f;
  int large_error_allowed = 2;
  int small_error_allowed = 0;
  pixel_comparator_.reset(new FuzzyPixelComparator(
      true,  // discard_alpha
      percentage_pixels_large_error,
      percentage_pixels_small_error,
      average_error_allowed_in_bad_pixels,
      large_error_allowed,
      small_error_allowed));
#endif

  RunPixelTest(GL_WITH_BITMAP,
               background,
               base::FilePath(FILE_PATH_LITERAL(
                   "background_filter_blur_off_axis.png")));
}

}  // namespace
}  // namespace cc

#endif  // OS_ANDROID
<commit_msg>Re-enable cc_unittest LayerTreeHostFiltersPixelTest.BackgroundFilterBlurOutsets, and adjust the fuzzy match threshold on Windows.<commit_after>// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "build/build_config.h"
#include "cc/layers/solid_color_layer.h"
#include "cc/test/layer_tree_pixel_test.h"
#include "cc/test/pixel_comparator.h"

#if !defined(OS_ANDROID)

namespace cc {
namespace {

class LayerTreeHostFiltersPixelTest : public LayerTreePixelTest {};

TEST_F(LayerTreeHostFiltersPixelTest, BackgroundFilterBlur) {
  scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer(
      gfx::Rect(200, 200), SK_ColorWHITE);

  // The green box is entirely behind a layer with background blur, so it
  // should appear blurred on its edges.
  scoped_refptr<SolidColorLayer> green = CreateSolidColorLayer(
      gfx::Rect(50, 50, 100, 100), kCSSGreen);
  scoped_refptr<SolidColorLayer> blur = CreateSolidColorLayer(
      gfx::Rect(30, 30, 140, 140), SK_ColorTRANSPARENT);
  background->AddChild(green);
  background->AddChild(blur);

  FilterOperations filters;
  filters.Append(FilterOperation::CreateBlurFilter(2.f));
  blur->SetBackgroundFilters(filters);

#if defined(OS_WIN)
  // Windows has 436 pixels off by 1: crbug.com/259915
  float percentage_pixels_large_error = 1.09f;  // 436px / (200*200)
  float percentage_pixels_small_error = 0.0f;
  float average_error_allowed_in_bad_pixels = 1.f;
  int large_error_allowed = 1;
  int small_error_allowed = 0;
  pixel_comparator_.reset(new FuzzyPixelComparator(
      true,  // discard_alpha
      percentage_pixels_large_error,
      percentage_pixels_small_error,
      average_error_allowed_in_bad_pixels,
      large_error_allowed,
      small_error_allowed));
#endif

  RunPixelTest(GL_WITH_BITMAP,
               background,
               base::FilePath(FILE_PATH_LITERAL("background_filter_blur.png")));
}

TEST_F(LayerTreeHostFiltersPixelTest, BackgroundFilterBlurOutsets) {
  scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer(
      gfx::Rect(200, 200), SK_ColorWHITE);

  // The green border is outside the layer with background blur, but the
  // background blur should use pixels from outside its layer borders, up to the
  // radius of the blur effect. So the border should be blurred underneath the
  // top layer causing the green to bleed under the transparent layer, but not
  // in the 1px region between the transparent layer and the green border.
  scoped_refptr<SolidColorLayer> green_border = CreateSolidColorLayerWithBorder(
      gfx::Rect(1, 1, 198, 198), SK_ColorWHITE, 10, kCSSGreen);
  scoped_refptr<SolidColorLayer> blur = CreateSolidColorLayer(
      gfx::Rect(12, 12, 176, 176), SK_ColorTRANSPARENT);
  background->AddChild(green_border);
  background->AddChild(blur);

  FilterOperations filters;
  filters.Append(FilterOperation::CreateBlurFilter(5.f));
  blur->SetBackgroundFilters(filters);

#if defined(OS_WIN)
  // Windows has 2596 pixels off by at most 2: crbug.com/259922
  float percentage_pixels_large_error = 6.49f;  // 2596px / (200*200)
  float percentage_pixels_small_error = 0.0f;
  float average_error_allowed_in_bad_pixels = 1.f;
  int large_error_allowed = 2;
  int small_error_allowed = 0;
  pixel_comparator_.reset(new FuzzyPixelComparator(
      true,  // discard_alpha
      percentage_pixels_large_error,
      percentage_pixels_small_error,
      average_error_allowed_in_bad_pixels,
      large_error_allowed,
      small_error_allowed));
#endif

  RunPixelTest(GL_WITH_BITMAP,
               background,
               base::FilePath(FILE_PATH_LITERAL(
                   "background_filter_blur_outsets.png")));
}

TEST_F(LayerTreeHostFiltersPixelTest, BackgroundFilterBlurOffAxis) {
  scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer(
      gfx::Rect(200, 200), SK_ColorWHITE);

  // This verifies that the perspective of the clear layer (with black border)
  // does not influence the blending of the green box behind it. Also verifies
  // that the blur is correctly clipped inside the transformed clear layer.
  scoped_refptr<SolidColorLayer> green = CreateSolidColorLayer(
      gfx::Rect(50, 50, 100, 100), kCSSGreen);
  scoped_refptr<SolidColorLayer> blur = CreateSolidColorLayerWithBorder(
      gfx::Rect(30, 30, 120, 120), SK_ColorTRANSPARENT, 1, SK_ColorBLACK);
  background->AddChild(green);
  background->AddChild(blur);

  background->SetPreserves3d(true);
  gfx::Transform background_transform;
  background_transform.ApplyPerspectiveDepth(200.0);
  background->SetTransform(background_transform);

  blur->SetPreserves3d(true);
  gfx::Transform blur_transform;
  blur_transform.Translate(55.0, 65.0);
  blur_transform.RotateAboutXAxis(85.0);
  blur_transform.RotateAboutYAxis(180.0);
  blur_transform.RotateAboutZAxis(20.0);
  blur_transform.Translate(-60.0, -60.0);
  blur->SetTransform(blur_transform);

  FilterOperations filters;
  filters.Append(FilterOperation::CreateBlurFilter(2.f));
  blur->SetBackgroundFilters(filters);

#if defined(OS_WIN)
  // Windows has 151 pixels off by at most 2: crbug.com/225027
  float percentage_pixels_large_error = 0.3775f;  // 151px / (200*200)
  float percentage_pixels_small_error = 0.0f;
  float average_error_allowed_in_bad_pixels = 1.f;
  int large_error_allowed = 2;
  int small_error_allowed = 0;
  pixel_comparator_.reset(new FuzzyPixelComparator(
      true,  // discard_alpha
      percentage_pixels_large_error,
      percentage_pixels_small_error,
      average_error_allowed_in_bad_pixels,
      large_error_allowed,
      small_error_allowed));
#endif

  RunPixelTest(GL_WITH_BITMAP,
               background,
               base::FilePath(FILE_PATH_LITERAL(
                   "background_filter_blur_off_axis.png")));
}

}  // namespace
}  // namespace cc

#endif  // OS_ANDROID
<|endoftext|>


<commit_before>/*
** Copyright 2014-2015 Robert Fratto. See the LICENSE.txt file at the top-level
** directory of this distribution.
**
** Licensed under the MIT license <http://opensource.org/licenses/MIT>. This file
** may not be copied, modified, or distributed except according to those terms.
*/

#include <orange/VarExpr.h>
#include <orange/generator.h>

VarExpr* VarExpr::symtabVar() {
	SymTable* tab = GE::runner()->topBlock()->symtab();
	ASTNode* tabVar = tab->find(m_name);
	return tabVar ? (VarExpr*)tabVar : this;
}

Value* VarExpr::Codegen() {
	// "Generating" a variable doesn't actually do anything;
	// its creation is handled by other classes like BinOpExpr.
	GE::runner()->topBlock()->symtab()->activate(m_name, this);
	return getValue();
}

void VarExpr::initialize() {
	// Initialization should happen after a variable is created for the first
	// time. If we are a constant, we will set ourselves to "initialized,"
	// which means that we can't have our value changed.
	if (m_constant || symtabVar()->m_constant) {
		m_initialized = true;
		symtabVar()->m_initialized = true;
	}
}

Value* VarExpr::getValue() {
	// IF we have a value, just return it.
	if (m_value) return m_value;

	// If a variable exists in the symtab by this name,
	SymTable* tab = GE::runner()->topBlock()->symtab();

	ASTNode* node = tab->find(m_name);
	if (node == nullptr) return m_value;

	if (node->getClass() != getClass()) {
		throw std::runtime_error(node->string() + " is not a variable!");
	}

	if (node == this) return nullptr;
	return node->getValue();
}

std::string VarExpr::string() {
	return "(" + getType()->string() + ")" + m_name;
}

OrangeTy* VarExpr::getType() {
	// If we've been assigned a value, we'll return that, otherwise
	// we'll return the default type from ASTNode.
	if (m_type) {
		return m_type;
	}

	if (GE::runner()->topBlock()->symtab()->find(m_name)) {
		ASTNode* node = GE::runner()->topBlock()->symtab()->find(m_name);

		if (node->getClass() != getClass()) {
			throw std::runtime_error(node->string() + " is not a variable!");
		}

		VarExpr* nodeExpr = (VarExpr*)node;

		if (nodeExpr != this) {
			return nodeExpr->m_type ? nodeExpr->m_type : nodeExpr->getType();
		}
	}

	return ASTNode::getType();
}

void VarExpr::setType(OrangeTy* type) {
	m_type = type;

	// If this variable exists in the symtab, set this type for that, too.
	SymTable* tab = GE::runner()->topBlock()->symtab();
	ASTNode* tabVar = tab->find(m_name);

	if (tabVar && tabVar->getClass() == "VarExpr" && tabVar != this) {
			((VarExpr *)tabVar)->setType(type);
	}
}

bool VarExpr::isLocked() {
	if (m_locked) return true;

	// we may not be referring to the VarExpr here; look in the symtab.
	SymTable* tab = GE::runner()->topBlock()->symtab();
	ASTNode* tabVar = tab->find(m_name);

	if (tabVar && tabVar->getClass() == "VarExpr" && tabVar != this) {
		return ((VarExpr *)tabVar)->isLocked();
	}

	return false;
}

void VarExpr::resolve() {
	if (m_resolved) return;
	m_resolved = true;

	if (getType()->isVariadicArray()) {
		std::vector<Expression *> variadicElements;

		auto ptr = getType();
		while (ptr->isVariadicArray()) {
			variadicElements.push_back(ptr->getVariadicArrayElement());
			ptr = ptr->getArrayElementType();
		}

		for (auto expr : variadicElements) {
			if (expr) expr->resolve();
		}
	}
}

void VarExpr::create(bool throwError) {
	// Tries to add this variable to the symbol table.
	// If it already exists in the symbol table, and it's not this, throw an error.
	SymTable* tab = GE::runner()->topBlock()->symtab();

	if (tab->create(m_name, this) == false && throwError) {
		// We couldn't create it because it already exists.
		// If the ASTNode in the table isn't this var, throw an error.
		if (tab->find(m_name) && tab->find(m_name) != this) {
			throw std::runtime_error("A variable by this name already exists!");
		}
	}
}

bool VarExpr::existsInParent() {
	SymTable* tab = GE::runner()->topBlock()->symtab();
	return tab->find(m_name) != nullptr;
}

void VarExpr::setValue(Value* value) {

	if (m_initialized || symtabVar()->m_initialized) {
		throw CompilerMessage(*this, "cannot modify the value of a constant!");
	}

	m_value = GE::builder()->CreateAlloca(value->getType(), nullptr, m_name);
	GE::builder()->CreateStore(value, m_value);
}

void VarExpr::setValueTo(Value *value) {
	if (m_initialized || symtabVar()->m_initialized) {
		throw CompilerMessage(*this, "cannot modify the value of a constant!");
	}

	m_value = value;
}

bool VarExpr::returnsPtr() {
	return true;
}

Value* VarExpr::allocate() {
	if (m_value != nullptr) {
		throw CompilerMessage(*this, "variable already allocated!");
	}

	// If we're variadic array, getLLVMType() will just return type*.
	// However, we need to actually initialize ourselves with the number
	// of elements, so handle that here

	Type* llvmType = getLLVMType();

	if (llvmType == nullptr) {
		throw std::runtime_error("VarExpr::allocate(): getLLVMType returned nullptr!");
	}

	if (getType()->isVariadicArray()) {
		Type* baseType = llvmType;
		while (baseType->isPointerTy()) {
			baseType = baseType->getPointerElementType();
		}

		std::vector<Expression *> variadicElements;

		auto ptr = getType();
		while (ptr->isVariadicArray()) {
			variadicElements.push_back(ptr->getVariadicArrayElement());
			ptr = ptr->getArrayElementType();
		}

		// Codegen all of the types into values
		std::vector<Value*> values;

		for (auto expr : variadicElements) {
			auto value = expr->Codegen();

			if (value == nullptr) {
				throw std::runtime_error("VarExpr::allocate(): expr did not generate a value!");
			}

			if (expr->returnsPtr() == true) {
				value = GE::builder()->CreateLoad(value);
			}

			if (value->getType()->isIntegerTy() == false) {
				throw CompilerMessage(*expr, "Type is not an integer!");
			}

			values.push_back(value);
		}

		// The total size of this array is all the elements in the vector multiplied together.
		Value *totSize = values[0];
		for (int i = 1; i < values.size(); i++) {
			totSize = GE::builder()->CreateMul(totSize, values[i]);
		}

		Value *v = GE::builder()->CreateAlloca(baseType, totSize, name());
		setValueTo(v);
		return v;
	}

	Value* v = GE::builder()->CreateAlloca(llvmType, nullptr, name());
	setValueTo(v);
	return v;
}

VarExpr::VarExpr(std::string name) : m_name(name) {

}

VarExpr::VarExpr(std::string name, bool constant) : m_name(name) {
	m_constant = constant;
}

VarExpr::VarExpr(std::string name, OrangeTy* type) : m_name(name) {
	m_locked = true;
	m_type = type;
}

VarExpr::VarExpr(std::string name, OrangeTy* type, bool constant) : m_name(name) {
	m_locked = true;
	m_constant = constant;
	m_type = type;
}
<commit_msg>Change VarExpr to cache type.<commit_after>/*
** Copyright 2014-2015 Robert Fratto. See the LICENSE.txt file at the top-level
** directory of this distribution.
**
** Licensed under the MIT license <http://opensource.org/licenses/MIT>. This file
** may not be copied, modified, or distributed except according to those terms.
*/

#include <orange/VarExpr.h>
#include <orange/generator.h>

VarExpr* VarExpr::symtabVar() {
	SymTable* tab = GE::runner()->topBlock()->symtab();
	ASTNode* tabVar = tab->find(m_name);
	return tabVar ? (VarExpr*)tabVar : this;
}

Value* VarExpr::Codegen() {
	// "Generating" a variable doesn't actually do anything;
	// its creation is handled by other classes like BinOpExpr.
	GE::runner()->topBlock()->symtab()->activate(m_name, this);
	return getValue();
}

void VarExpr::initialize() {
	// Initialization should happen after a variable is created for the first
	// time. If we are a constant, we will set ourselves to "initialized,"
	// which means that we can't have our value changed.
	if (m_constant || symtabVar()->m_constant) {
		m_initialized = true;
		symtabVar()->m_initialized = true;
	}
}

Value* VarExpr::getValue() {
	// IF we have a value, just return it.
	if (m_value) return m_value;

	// If a variable exists in the symtab by this name,
	SymTable* tab = GE::runner()->topBlock()->symtab();

	ASTNode* node = tab->find(m_name);
	if (node == nullptr) return m_value;

	if (node->getClass() != getClass()) {
		throw std::runtime_error(node->string() + " is not a variable!");
	}

	if (node == this) return nullptr;
	m_value = node->getValue();
	return m_value;
}

std::string VarExpr::string() {
	return "(" + getType()->string() + ")" + m_name;
}

OrangeTy* VarExpr::getType() {
	// If we've been assigned a value, we'll return that, otherwise
	// we'll return the default type from ASTNode.
	if (m_type) {
		return m_type;
	}

	if (GE::runner()->topBlock()->symtab()->find(m_name)) {
		ASTNode* node = GE::runner()->topBlock()->symtab()->find(m_name);

		if (node->getClass() != getClass()) {
			throw std::runtime_error(node->string() + " is not a variable!");
		}

		VarExpr* nodeExpr = (VarExpr*)node;

		if (nodeExpr != this) {
			return nodeExpr->m_type ? nodeExpr->m_type : nodeExpr->getType();
		}
	}

	return ASTNode::getType();
}

void VarExpr::setType(OrangeTy* type) {
	m_type = type;

	// If this variable exists in the symtab, set this type for that, too.
	SymTable* tab = GE::runner()->topBlock()->symtab();
	ASTNode* tabVar = tab->find(m_name);

	if (tabVar && tabVar->getClass() == "VarExpr" && tabVar != this) {
			((VarExpr *)tabVar)->setType(type);
	}
}

bool VarExpr::isLocked() {
	if (m_locked) return true;

	// we may not be referring to the VarExpr here; look in the symtab.
	SymTable* tab = GE::runner()->topBlock()->symtab();
	ASTNode* tabVar = tab->find(m_name);

	if (tabVar && tabVar->getClass() == "VarExpr" && tabVar != this) {
		return ((VarExpr *)tabVar)->isLocked();
	}

	return false;
}

void VarExpr::resolve() {
	if (m_resolved) return;
	m_resolved = true;

	if (getType()->isVariadicArray()) {
		std::vector<Expression *> variadicElements;

		auto ptr = getType();
		while (ptr->isVariadicArray()) {
			variadicElements.push_back(ptr->getVariadicArrayElement());
			ptr = ptr->getArrayElementType();
		}

		for (auto expr : variadicElements) {
			if (expr) expr->resolve();
		}
	}
}

void VarExpr::create(bool throwError) {
	// Tries to add this variable to the symbol table.
	// If it already exists in the symbol table, and it's not this, throw an error.
	SymTable* tab = GE::runner()->topBlock()->symtab();

	if (tab->create(m_name, this) == false && throwError) {
		// We couldn't create it because it already exists.
		// If the ASTNode in the table isn't this var, throw an error.
		if (tab->find(m_name) && tab->find(m_name) != this) {
			throw std::runtime_error("A variable by this name already exists!");
		}
	}
}

bool VarExpr::existsInParent() {
	SymTable* tab = GE::runner()->topBlock()->symtab();
	return tab->find(m_name) != nullptr;
}

void VarExpr::setValue(Value* value) {

	if (m_initialized || symtabVar()->m_initialized) {
		throw CompilerMessage(*this, "cannot modify the value of a constant!");
	}

	m_value = GE::builder()->CreateAlloca(value->getType(), nullptr, m_name);
	GE::builder()->CreateStore(value, m_value);
}

void VarExpr::setValueTo(Value *value) {
	if (m_initialized || symtabVar()->m_initialized) {
		throw CompilerMessage(*this, "cannot modify the value of a constant!");
	}

	m_value = value;
}

bool VarExpr::returnsPtr() {
	return true;
}

Value* VarExpr::allocate() {
	if (m_value != nullptr) {
		throw CompilerMessage(*this, "variable already allocated!");
	}

	// If we're variadic array, getLLVMType() will just return type*.
	// However, we need to actually initialize ourselves with the number
	// of elements, so handle that here

	Type* llvmType = getLLVMType();

	if (llvmType == nullptr) {
		throw std::runtime_error("VarExpr::allocate(): getLLVMType returned nullptr!");
	}

	if (getType()->isVariadicArray()) {
		Type* baseType = llvmType;
		while (baseType->isPointerTy()) {
			baseType = baseType->getPointerElementType();
		}

		std::vector<Expression *> variadicElements;

		auto ptr = getType();
		while (ptr->isVariadicArray()) {
			variadicElements.push_back(ptr->getVariadicArrayElement());
			ptr = ptr->getArrayElementType();
		}

		// Codegen all of the types into values
		std::vector<Value*> values;

		for (auto expr : variadicElements) {
			auto value = expr->Codegen();

			if (value == nullptr) {
				throw std::runtime_error("VarExpr::allocate(): expr did not generate a value!");
			}

			if (expr->returnsPtr() == true) {
				value = GE::builder()->CreateLoad(value);
			}

			if (value->getType()->isIntegerTy() == false) {
				throw CompilerMessage(*expr, "Type is not an integer!");
			}

			values.push_back(value);
		}

		// The total size of this array is all the elements in the vector multiplied together.
		Value *totSize = values[0];
		for (int i = 1; i < values.size(); i++) {
			totSize = GE::builder()->CreateMul(totSize, values[i]);
		}

		Value *v = GE::builder()->CreateAlloca(baseType, totSize, name());
		setValueTo(v);
		return v;
	}

	Value* v = GE::builder()->CreateAlloca(llvmType, nullptr, name());
	setValueTo(v);
	return v;
}

VarExpr::VarExpr(std::string name) : m_name(name) {

}

VarExpr::VarExpr(std::string name, bool constant) : m_name(name) {
	m_constant = constant;
}

VarExpr::VarExpr(std::string name, OrangeTy* type) : m_name(name) {
	m_locked = true;
	m_type = type;
}

VarExpr::VarExpr(std::string name, OrangeTy* type, bool constant) : m_name(name) {
	m_locked = true;
	m_constant = constant;
	m_type = type;
}
<|endoftext|>