<commit_before>#include "ram.h"

u8 Ram::read_byte(u16 adress, u32 cycles_passed)
{
	if (adress >= 0xC000 && adress < 0xD000)
		return memory[adress - 0xC000];

	else if (adress >= 0xD000 && adress < 0xE000)
		return memory[adress - 0xC000 + bank_num * 0x1000];

	else if (adress >= 0xE000 && adress < 0xFE00) //TODO: propably it should read from current bank, not 1
		return memory[adress - 0xE000];

	else if (cgb_mode && adress == 0xFF70)
		return bank_num;

	else if (adress >= 0xFF80 && adress < 0xFFFF)
		return high_ram[adress - 0xFF80];

	else
		return 0xFF;
}

void Ram::write_byte(u16 adress, u8 value, u32 cycles_passed)
{
	if (adress >= 0xC000 && adress < 0xD000)
		memory[adress - 0xC000] = value;

	else if (adress >= 0xD000 && adress < 0xE000)
		memory[adress - 0xC000 + bank_num * 0x1000] = value;

	else if (adress >= 0xE000 && adress < 0xFE00) //TODO: propably it should write to current bank, not 1
		memory[adress - 0xE000] = value;

	else if (cgb_mode && adress == 0xFF70)
		bank_num = std::max(1, value & 0x7);

	else if (adress >= 0xFF80 && adress < 0xFFFF)
		high_ram[adress - 0xFF80] = value;

	//else ignore it
}

<commit_msg>small fixes in internal ram (echo memory now echoes memory banks also)<commit_after>#include "ram.h"

u8 Ram::read_byte(u16 adress, u32 cycles_passed)
{
	if (adress >= 0xC000 && adress < 0xD000)
		return memory[adress - 0xC000];

	else if (adress >= 0xD000 && adress < 0xE000)
		return memory[adress - 0xC000 + bank_num * 0x1000];

	else if (adress >= 0xE000 && adress < 0xF000)
		return memory[adress - 0xE000];

	else if (adress >= 0xF000 && adress < 0xFE00)
		return memory[adress - 0xF000 + bank_num * 0x1000];

	else if (cgb_mode && adress == 0xFF70)
		return bank_num;

	else if (adress >= 0xFF80 && adress < 0xFFFF)
		return high_ram[adress - 0xFF80];

	else
		return 0xFF;
}

void Ram::write_byte(u16 adress, u8 value, u32 cycles_passed)
{
	if (adress >= 0xC000 && adress < 0xD000)
		memory[adress - 0xC000] = value;

	else if (adress >= 0xD000 && adress < 0xE000)
		memory[adress - 0xC000 + bank_num * 0x1000] = value;

	else if (adress >= 0xE000 && adress < 0xF000)
		memory[adress - 0xE000] = value;

	else if (adress >= 0xF000 && adress < 0xFE00)
		memory[adress - 0xF000 + bank_num * 0x1000] = value;

	else if (cgb_mode && adress == 0xFF70)
		bank_num = std::max(1, value & 0x7);

	else if (adress >= 0xFF80 && adress < 0xFFFF)
		high_ram[adress - 0xFF80] = value;

	//else ignore it
}

<|endoftext|>


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

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

#define WIRE_FRAME_WIDTH    1.1f

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    canvas->drawPath(path, paint);

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

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

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

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

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

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

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

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

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

    canvas->translate(320, 0);

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

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

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

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

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

    canvas->translate(320, 0);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

private:
    typedef skiagm::GM INHERITED;
};

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

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

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

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

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

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

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

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

#define WIRE_FRAME_WIDTH    1.1f

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    canvas->drawPath(path, paint);

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

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

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

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

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

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

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

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

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

    canvas->translate(320, 0);

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

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

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

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

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

    canvas->translate(320, 0);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

private:
    typedef skiagm::GM INHERITED;
};

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

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

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

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

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

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

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2014-2015 Pavel Dolgov
 *
 * See the LICENSE file for terms of use.
 */

#include <iomanip>
#include <iostream>
#include <limits>

#include "ConsoleBotView.hpp"

static int numberOfDigits(int number) {
    int digits = 0;
    while (number) {
        number /= 10;
        digits++;
    }
    return digits;
}

static void printSpaces(int spaces) {
    for (int i = 0; i < spaces; i++) {
        std::cout << " ";
    }
}

void ConsoleBotView::view() {
    while (true) {
        start();
        char mode;
        std::cin >> mode;
        switch (mode) {
            case 't':
                gameWithTime();
                break;
            case 'w':
                gameForWin();
                break;
            case 's':
                gameForScore();
                break;
            case 'q':
                return;
            default:
                sendHelpMessage_impl();
        }
    }
}

void ConsoleBotView::timeNumberMessage() const {
    std::cout << "How many minutes you want to play?" << std::endl;
    std::cout << "The default is " << Rules::DEFAULT_TIME
              << std::endl;
    prompt();
}

void ConsoleBotView::winNumberMessage() const {
    int square = getBoardsSquare();
    std::cout << "What score you want to finish the "
                 "game?" << std::endl;
    std::cout << "The default is " << square * 4
              << std::endl;
    prompt();
}

void ConsoleBotView::deskSizeMessage() const {
    std::cout << "Please enter size of the game board."
              << std::endl;
    std::cout << "Your board will have x * x square."
              << std::endl;
    std::cout << "(Where x is input size)" << std::endl;
    std::cout << "Minimum size is " << Rules::MIN_WIDTH
              << " and maximum is " << Rules::MAX_WIDTH
              << std::endl;
    std::cout << "Please note that you can change font's "
                 "size in your Terminal Preferences if"
              << std::endl;
    std::cout << "you have size mismatch of screen and "
                 "game board."
              << std::endl;
    prompt();
}

void ConsoleBotView::outputGeneral() const {
    int digits = numberOfDigits(maxDeskNumber());
    int width = Console::NUMBER_OF_SPACES + digits;
    int row_number = game_->desk->getRowNumber();
    for (int i = row_number - 1; i >= 0; i--) {
        std::cout << std::right
                  << std::setw(Console::MAX_INDEX_LENGTH)
                  << i << " ||";
        for (int x = 0; x < row_number; x++) {
            Point point;
            point.col = i;
            point.row = x;
            std::cout << std::right << std::setw(width)
                      << game_->desk->getDeskNumber(point);
        }
        std::cout << std::endl;
    }
    rowIndices(width);
    std::cout << std::endl;
}

void ConsoleBotView::prompt() const {
    std::cout << ">>> ";
}

void ConsoleBotView::typeError() const {
    std::cout << "Error: you must enter the NUMBER" << std::endl;
    std::cout << "Try again: " << std::endl;
    std::cin.clear();
    std::cin.ignore(std::numeric_limits<int>::max(), '\n');
}

void ConsoleBotView::rangeError(TypeOfChecking type) const {
    int max_int = std::numeric_limits<int>::max();
    std::cout << "This number is out of allowable "
                 "range." << std::endl;
    if (type == TIME) {
        std::cout << "Please enter a POSITIVE INTEGER"
                  << std::endl;
        std::cout << "Maximum is " << max_int << std::endl;
    } else if (type == SCORE) {
        int square = getBoardsSquare();
        std::cout << "For this size of the game board "
                  << "minimum is " << square * 2 + 1
                  << std::endl;
        std::cout << "Maximum is " << max_int << std::endl;

    }
    std::cout << "Try again: " << std::endl;
    std::cin.clear();
    std::cin.ignore(max_int, '\n');
}

bool ConsoleBotView::checkRange(int verifiable,
                                TypeOfChecking type) const {
    switch (type) {
        case BOARDS_SIZE:
            return ((verifiable >= Rules::MIN_WIDTH) &&
                    (verifiable <= Rules::MAX_WIDTH));
        case TIME:
            // By checking that verifiable is greater than
            // zero we make sure that it's less or equal
            // to the allowable maximum for int also.
            // See cyclic mechanism of ints in C++.
            return (verifiable > 0);
        case SCORE:
            int square = getBoardsSquare();
            return (verifiable > square * 2);
    }
}

int ConsoleBotView::getBoardsSquare() const {
    int boards_size = game_->desk->getRowNumber();
    return boards_size * boards_size;
}

const GameDesk* ConsoleBotView::getDesk() const {
    return game_->desk.data();
}

void ConsoleBotView::finish_impl(bool fail, int score,
                                 int steps_number) const {
    if (fail) {
        std::cout << "You are loser... Your score is " << score << std::endl;
    } else {
        std::cout << "You are winner! Your score is " << score << std::endl;
    }
    std::cout << "You have completed the game in " << steps_number << " steps." << std::endl;
}

void ConsoleBotView::sendHelpMessage_impl() const {
    std::cout << "You must enter t, w, s or q" << std::endl;
    std::cout << "Try again please." << std::endl;
}

void ConsoleBotView::startGame_impl(int row_number) {
    try {
        game_ = Game::make(row_number);
        game_->controller->initialStateOfBoard();
    } catch (std::exception& e) {
        errorHandling_impl(e);
    }
}

void ConsoleBotView::errorHandling_impl(std::exception& e) const {
    std::cout << e.what() << std::endl;
}

int ConsoleBotView::maxDeskNumber() const {
    const GameDesk* desk = game_->desk.data();
    int boards_size = desk->getRowNumber();
    int max = 0;
    for (int i = boards_size - 1; i >= 0; i--) {
        for (int x = 0; x < boards_size; x++) {
            Point pt;
            pt.col = i;
            pt.row = x;
            int current_number = desk->getDeskNumber(pt);
            if (current_number > max) {
                max = current_number;
            }
        }
    }
    return max;
}

void ConsoleBotView::rowIndices(int width) const {
    int boards_size = game_->desk->getRowNumber();
    printSpaces(Console::INDEX_FIELD);
    for (int i = 0; i < width * boards_size; i++) {
        std::cout << "=";
    }
    std::cout << std::endl;
    printSpaces(Console::INDEX_FIELD);
    for (int i = 0; i < boards_size; i++) {
        std::cout << std::right << std::setw(width) << i;
    }
}

void ConsoleBotView::start() const {
    std::cout << "*** BIN_GAME ***" << std::endl;
    std::cout << "----------------" << std::endl;
    std::cout << "t: time mode | w: play for score | s: "
                 "play while not lose" << std::endl;
    std::cout << "q: quit" << std::endl;
    prompt();
}

void ConsoleBotView::gameForWin() {
    int desk_size = getDeskSize_impl();
    startGame_impl(desk_size);
    int win_number = getWinNumber_impl();
    const GameDesk* desk = game_->desk.data();
    output_impl();
    int steps_number = 0;
    while (!checkFail(*desk) && !checkWin(*desk,
                                          win_number)) {
        steps_number += 1;
        play();
    }
    finish_impl(checkFail(*desk), score(*desk),
                steps_number);
}

void ConsoleBotView::gameForScore() {
    int desk_size = getDeskSize_impl();
    startGame_impl(desk_size);
    const GameDesk* desk = game_->desk.data();
    output_impl();
    int steps_number = 0;
    while (!checkFail(*desk)) {
        steps_number += 1;
        play();
    }
    finish_impl(checkFail(*desk), score(*desk),
                steps_number);
}

void ConsoleBotView::gameWithTime() {
    int desk_size = getDeskSize_impl();
    int time_number = getTimeNumber_impl();
    startGame_impl(desk_size);
    int t1 = time(NULL);
    int t2 = 0;
    const GameDesk* desk = game_->desk.data();
    output_impl();
    int steps_number = 0;
    while (!checkFail(*desk) &&
           ((t2 - t1) < time_number * 60)) {
        steps_number += 1;
        play();
        t2 = time(NULL);
    }
    finish_impl(checkFail(*desk), score(*desk),
                steps_number);
}

void ConsoleBotView::play() {
    Points points = getIndex_impl();
    try {
        game_->controller->replace(points);
    } catch (std::exception& e) {
        errorHandling_impl(e);
    }
    output_impl();
}
<commit_msg>Console: print prompt in typeError()<commit_after>/*
 * Copyright (C) 2014-2015 Pavel Dolgov
 *
 * See the LICENSE file for terms of use.
 */

#include <iomanip>
#include <iostream>
#include <limits>

#include "ConsoleBotView.hpp"

static int numberOfDigits(int number) {
    int digits = 0;
    while (number) {
        number /= 10;
        digits++;
    }
    return digits;
}

static void printSpaces(int spaces) {
    for (int i = 0; i < spaces; i++) {
        std::cout << " ";
    }
}

void ConsoleBotView::view() {
    while (true) {
        start();
        char mode;
        std::cin >> mode;
        switch (mode) {
            case 't':
                gameWithTime();
                break;
            case 'w':
                gameForWin();
                break;
            case 's':
                gameForScore();
                break;
            case 'q':
                return;
            default:
                sendHelpMessage_impl();
        }
    }
}

void ConsoleBotView::timeNumberMessage() const {
    std::cout << "How many minutes you want to play?" << std::endl;
    std::cout << "The default is " << Rules::DEFAULT_TIME
              << std::endl;
    prompt();
}

void ConsoleBotView::winNumberMessage() const {
    int square = getBoardsSquare();
    std::cout << "What score you want to finish the "
                 "game?" << std::endl;
    std::cout << "The default is " << square * 4
              << std::endl;
    prompt();
}

void ConsoleBotView::deskSizeMessage() const {
    std::cout << "Please enter size of the game board."
              << std::endl;
    std::cout << "Your board will have x * x square."
              << std::endl;
    std::cout << "(Where x is input size)" << std::endl;
    std::cout << "Minimum size is " << Rules::MIN_WIDTH
              << " and maximum is " << Rules::MAX_WIDTH
              << std::endl;
    std::cout << "Please note that you can change font's "
                 "size in your Terminal Preferences if"
              << std::endl;
    std::cout << "you have size mismatch of screen and "
                 "game board."
              << std::endl;
    prompt();
}

void ConsoleBotView::outputGeneral() const {
    int digits = numberOfDigits(maxDeskNumber());
    int width = Console::NUMBER_OF_SPACES + digits;
    int row_number = game_->desk->getRowNumber();
    for (int i = row_number - 1; i >= 0; i--) {
        std::cout << std::right
                  << std::setw(Console::MAX_INDEX_LENGTH)
                  << i << " ||";
        for (int x = 0; x < row_number; x++) {
            Point point;
            point.col = i;
            point.row = x;
            std::cout << std::right << std::setw(width)
                      << game_->desk->getDeskNumber(point);
        }
        std::cout << std::endl;
    }
    rowIndices(width);
    std::cout << std::endl;
}

void ConsoleBotView::prompt() const {
    std::cout << ">>> ";
}

void ConsoleBotView::typeError() const {
    std::cout << "Error: you must enter the NUMBER" << std::endl;
    std::cout << "Try again please." << std::endl;
    prompt();
    std::cin.clear();
    std::cin.ignore(std::numeric_limits<int>::max(), '\n');
}

void ConsoleBotView::rangeError(TypeOfChecking type) const {
    int max_int = std::numeric_limits<int>::max();
    std::cout << "This number is out of allowable "
                 "range." << std::endl;
    if (type == TIME) {
        std::cout << "Please enter a POSITIVE INTEGER"
                  << std::endl;
        std::cout << "Maximum is " << max_int << std::endl;
    } else if (type == SCORE) {
        int square = getBoardsSquare();
        std::cout << "For this size of the game board "
                  << "minimum is " << square * 2 + 1
                  << std::endl;
        std::cout << "Maximum is " << max_int << std::endl;

    }
    std::cout << "Try again: " << std::endl;
    std::cin.clear();
    std::cin.ignore(max_int, '\n');
}

bool ConsoleBotView::checkRange(int verifiable,
                                TypeOfChecking type) const {
    switch (type) {
        case BOARDS_SIZE:
            return ((verifiable >= Rules::MIN_WIDTH) &&
                    (verifiable <= Rules::MAX_WIDTH));
        case TIME:
            // By checking that verifiable is greater than
            // zero we make sure that it's less or equal
            // to the allowable maximum for int also.
            // See cyclic mechanism of ints in C++.
            return (verifiable > 0);
        case SCORE:
            int square = getBoardsSquare();
            return (verifiable > square * 2);
    }
}

int ConsoleBotView::getBoardsSquare() const {
    int boards_size = game_->desk->getRowNumber();
    return boards_size * boards_size;
}

const GameDesk* ConsoleBotView::getDesk() const {
    return game_->desk.data();
}

void ConsoleBotView::finish_impl(bool fail, int score,
                                 int steps_number) const {
    if (fail) {
        std::cout << "You are loser... Your score is " << score << std::endl;
    } else {
        std::cout << "You are winner! Your score is " << score << std::endl;
    }
    std::cout << "You have completed the game in " << steps_number << " steps." << std::endl;
}

void ConsoleBotView::sendHelpMessage_impl() const {
    std::cout << "You must enter t, w, s or q" << std::endl;
    std::cout << "Try again please." << std::endl;
}

void ConsoleBotView::startGame_impl(int row_number) {
    try {
        game_ = Game::make(row_number);
        game_->controller->initialStateOfBoard();
    } catch (std::exception& e) {
        errorHandling_impl(e);
    }
}

void ConsoleBotView::errorHandling_impl(std::exception& e) const {
    std::cout << e.what() << std::endl;
}

int ConsoleBotView::maxDeskNumber() const {
    const GameDesk* desk = game_->desk.data();
    int boards_size = desk->getRowNumber();
    int max = 0;
    for (int i = boards_size - 1; i >= 0; i--) {
        for (int x = 0; x < boards_size; x++) {
            Point pt;
            pt.col = i;
            pt.row = x;
            int current_number = desk->getDeskNumber(pt);
            if (current_number > max) {
                max = current_number;
            }
        }
    }
    return max;
}

void ConsoleBotView::rowIndices(int width) const {
    int boards_size = game_->desk->getRowNumber();
    printSpaces(Console::INDEX_FIELD);
    for (int i = 0; i < width * boards_size; i++) {
        std::cout << "=";
    }
    std::cout << std::endl;
    printSpaces(Console::INDEX_FIELD);
    for (int i = 0; i < boards_size; i++) {
        std::cout << std::right << std::setw(width) << i;
    }
}

void ConsoleBotView::start() const {
    std::cout << "*** BIN_GAME ***" << std::endl;
    std::cout << "----------------" << std::endl;
    std::cout << "t: time mode | w: play for score | s: "
                 "play while not lose" << std::endl;
    std::cout << "q: quit" << std::endl;
    prompt();
}

void ConsoleBotView::gameForWin() {
    int desk_size = getDeskSize_impl();
    startGame_impl(desk_size);
    int win_number = getWinNumber_impl();
    const GameDesk* desk = game_->desk.data();
    output_impl();
    int steps_number = 0;
    while (!checkFail(*desk) && !checkWin(*desk,
                                          win_number)) {
        steps_number += 1;
        play();
    }
    finish_impl(checkFail(*desk), score(*desk),
                steps_number);
}

void ConsoleBotView::gameForScore() {
    int desk_size = getDeskSize_impl();
    startGame_impl(desk_size);
    const GameDesk* desk = game_->desk.data();
    output_impl();
    int steps_number = 0;
    while (!checkFail(*desk)) {
        steps_number += 1;
        play();
    }
    finish_impl(checkFail(*desk), score(*desk),
                steps_number);
}

void ConsoleBotView::gameWithTime() {
    int desk_size = getDeskSize_impl();
    int time_number = getTimeNumber_impl();
    startGame_impl(desk_size);
    int t1 = time(NULL);
    int t2 = 0;
    const GameDesk* desk = game_->desk.data();
    output_impl();
    int steps_number = 0;
    while (!checkFail(*desk) &&
           ((t2 - t1) < time_number * 60)) {
        steps_number += 1;
        play();
        t2 = time(NULL);
    }
    finish_impl(checkFail(*desk), score(*desk),
                steps_number);
}

void ConsoleBotView::play() {
    Points points = getIndex_impl();
    try {
        game_->controller->replace(points);
    } catch (std::exception& e) {
        errorHandling_impl(e);
    }
    output_impl();
}
<|endoftext|>


<commit_before>#include "condor_common.h"
#include "condor_api.h"
#include "status_types.h"
#include "totals.h"

extern AdTypes	type;
extern Mode		mode;
extern ppOption	ppStyle;

int matchPrefix (const char *, const char *);

char *
getPPStyleStr ()
{
	switch (ppStyle)
	{
    	case PP_NOTSET:			return "<Not set>";
    	case PP_STARTD_NORMAL:	return "Normal (Startd)";
    	case PP_SCHEDD_NORMAL:	return "Normal (Schedd)";
    	case PP_SCHEDD_SUBMITTORS:return "Normal (Schedd)";
    	case PP_MASTER_NORMAL:	return "Normal (Master)";
    	case PP_CKPT_SRVR_NORMAL:return"Normal (CkptSrvr)";
    	case PP_STARTD_SERVER:	return "Server";
    	case PP_STARTD_RUN:		return "Run";
    	case PP_VERBOSE:		return "Verbose";
    	case PP_CUSTOM:			return "Custom";
		default:				return "<Unknown!>";
	}
	// should not reach here
	exit (1);
}

void
setPPstyle (ppOption pps, int i, char *argv)
{
    static int setBy = 0;
    static char *setArg = NULL;

	if (argv == NULL) {
		printf ("Set by arg %d (%-10s), PrettyPrint style = %s\n",
				setBy, setArg, getPPStyleStr());
		return;
	}

	// if the style has already been set, and is trying to be reset by default
	// rules, override the default  (i.e., don't make a change)
	if (setBy != 0 && i == 0)
		return;

    if (ppStyle <= pps || setBy == 0) {
        ppStyle = pps;
        setBy = i;
        setArg = argv;
    } else {
        fprintf (stderr, "Error:  arg %d (%s) contradicts arg %d (%s)\n",
                            i, argv, setBy, setArg);
        exit (1);
    }
}

char *
getTypeStr ()
{
	switch (type)
	{
		case STARTD_AD:		return "STARTD";
		case SCHEDD_AD:		return "SCHEDD";
		case SUBMITTOR_AD:	return "SUBMITTOR";
		case MASTER_AD:		return "MASTER";
		case CKPT_SRVR_AD:	return "CKPT_SRVR";
		case GATEWAY_AD:	return "GATEWAYS";
		default: 			return "<Unknown type!>";
	}
	// should never get here
	exit (1);
}

void
setType (char *dtype, int i, char *argv)
{
    static int setBy = 0;
    static char *setArg = NULL;

	if (argv == NULL) {
		printf ("Set by arg %d (%-10s), Query type = %s\n",
				setBy, setArg, getTypeStr());
		return;
	}

	// if the type has already been set, and is trying to be reset by default
	// rules, override the default  (i.e., don't make a change)
	if (setBy != 0 && i == 0)
		return;

    if (setArg == NULL) {
        if (matchPrefix (dtype, "STARTD")) {
            type = STARTD_AD;
        } else
        if (matchPrefix (dtype, "SCHEDD")) {
            type = SCHEDD_AD;
        } else
		if (matchPrefix (dtype, "SUBMITTOR")) {
			type = SUBMITTOR_AD;
		} else
        if (matchPrefix (dtype, "MASTER")) {
            type = MASTER_AD;
        } else
        if (matchPrefix (dtype, "CKPT_SRVR")) {
            type = CKPT_SRVR_AD;
        } else
        if (matchPrefix (dtype, "GATEWAYS")) {
            type = GATEWAY_AD;
        } else {
            fprintf (stderr, "Error:  Unknown entity type: %s\n", dtype);
            exit (1);
        }
        setBy = i;
        setArg = argv;
    } else {
        fprintf (stderr,
        "Error:  Daemon type implied by arg %d (%s) contradicts arg %d (%s)\n",
        	i, argv, setBy, setArg);
    }
}

char *
getModeStr()
{
	switch (mode)
	{
		case MODE_NOTSET:				return "Not set";
		case MODE_STARTD_NORMAL:		return "Normal (Startd)";
		case MODE_STARTD_AVAIL:			return "Available (Startd)";
		case MODE_STARTD_RUN:			return "Run (Startd)";
		case MODE_SCHEDD_NORMAL:		return "Normal (Schedd)";
		case MODE_SCHEDD_SUBMITTORS:	return "Submittors (Schedd)";
		case MODE_MASTER_NORMAL:		return "Normal (Master)";
		case MODE_CKPT_SRVR_NORMAL:		return "Normal (CkptSrvr)";
		default:				return "<Unknown!>";
	}
	// should never get here
	exit (1);
}

void
setMode (Mode mod, int i, char *argv)
{
    static int setBy = 0;
    static char *setArg = NULL;

	if (argv == NULL) {
		printf("Set by arg %d (%-10s), Mode = %s\n",setBy,setArg,getModeStr());
		return;
	}

    if (setBy == 0) {
        mode = mod;
        switch (mod) {
          case MODE_STARTD_NORMAL:
            setType ("STARTD", i, argv);
            setPPstyle (PP_STARTD_NORMAL, i, argv);
            break;

          case MODE_STARTD_AVAIL:
            setType ("STARTD", i, argv);
            setPPstyle (PP_STARTD_NORMAL, i, argv);
            break;

          case MODE_STARTD_RUN:
            setType ("STARTD", i, argv);
            setPPstyle (PP_STARTD_RUN, i, argv);
            break;

		  case MODE_SCHEDD_NORMAL:
            setType ("SCHEDD", i, argv);
            setPPstyle (PP_SCHEDD_NORMAL, i, argv);
            break;

		  case MODE_SCHEDD_SUBMITTORS:
            setType ("SCHEDD", i, argv);
            setPPstyle (PP_SCHEDD_SUBMITTORS, i, argv);
            break;

		  case MODE_MASTER_NORMAL:
			setType ("MASTER", i, argv);
			setPPstyle (PP_MASTER_NORMAL, i, argv);
			break;

		  case MODE_CKPT_SRVR_NORMAL:
			setType ("CKPT_SRVR", i, argv);
			setPPstyle (PP_CKPT_SRVR_NORMAL, i, argv);
			break;

          default:
            fprintf (stderr, "Error:  Illegal mode %d\n", mode);
            break;
        }
        setBy = i;
        setArg = argv;
    } else {
        fprintf (stderr, "Error:  Arg %d (%s) contradicts arg %d (%s)\n",
                            i, argv, setBy, setArg);
        exit (1);
    }
}

<commit_msg>condor_status -sub should query for SUBMITTOR ads<commit_after>#include "condor_common.h"
#include "condor_api.h"
#include "status_types.h"
#include "totals.h"

extern AdTypes	type;
extern Mode		mode;
extern ppOption	ppStyle;

int matchPrefix (const char *, const char *);

char *
getPPStyleStr ()
{
	switch (ppStyle)
	{
    	case PP_NOTSET:			return "<Not set>";
    	case PP_STARTD_NORMAL:	return "Normal (Startd)";
    	case PP_SCHEDD_NORMAL:	return "Normal (Schedd)";
    	case PP_SCHEDD_SUBMITTORS:return "Normal (Schedd)";
    	case PP_MASTER_NORMAL:	return "Normal (Master)";
    	case PP_CKPT_SRVR_NORMAL:return"Normal (CkptSrvr)";
    	case PP_STARTD_SERVER:	return "Server";
    	case PP_STARTD_RUN:		return "Run";
    	case PP_VERBOSE:		return "Verbose";
    	case PP_CUSTOM:			return "Custom";
		default:				return "<Unknown!>";
	}
	// should not reach here
	exit (1);
}

void
setPPstyle (ppOption pps, int i, char *argv)
{
    static int setBy = 0;
    static char *setArg = NULL;

	if (argv == NULL) {
		printf ("Set by arg %d (%-10s), PrettyPrint style = %s\n",
				setBy, setArg, getPPStyleStr());
		return;
	}

	// if the style has already been set, and is trying to be reset by default
	// rules, override the default  (i.e., don't make a change)
	if (setBy != 0 && i == 0)
		return;

    if (ppStyle <= pps || setBy == 0) {
        ppStyle = pps;
        setBy = i;
        setArg = argv;
    } else {
        fprintf (stderr, "Error:  arg %d (%s) contradicts arg %d (%s)\n",
                            i, argv, setBy, setArg);
        exit (1);
    }
}

char *
getTypeStr ()
{
	switch (type)
	{
		case STARTD_AD:		return "STARTD";
		case SCHEDD_AD:		return "SCHEDD";
		case SUBMITTOR_AD:	return "SUBMITTOR";
		case MASTER_AD:		return "MASTER";
		case CKPT_SRVR_AD:	return "CKPT_SRVR";
		case GATEWAY_AD:	return "GATEWAYS";
		default: 			return "<Unknown type!>";
	}
	// should never get here
	exit (1);
}

void
setType (char *dtype, int i, char *argv)
{
    static int setBy = 0;
    static char *setArg = NULL;

	if (argv == NULL) {
		printf ("Set by arg %d (%-10s), Query type = %s\n",
				setBy, setArg, getTypeStr());
		return;
	}

	// if the type has already been set, and is trying to be reset by default
	// rules, override the default  (i.e., don't make a change)
	if (setBy != 0 && i == 0)
		return;

    if (setArg == NULL) {
        if (matchPrefix (dtype, "STARTD")) {
            type = STARTD_AD;
        } else
        if (matchPrefix (dtype, "SCHEDD")) {
            type = SCHEDD_AD;
        } else
		if (matchPrefix (dtype, "SUBMITTOR")) {
			type = SUBMITTOR_AD;
		} else
        if (matchPrefix (dtype, "MASTER")) {
            type = MASTER_AD;
        } else
        if (matchPrefix (dtype, "CKPT_SRVR")) {
            type = CKPT_SRVR_AD;
        } else
        if (matchPrefix (dtype, "GATEWAYS")) {
            type = GATEWAY_AD;
        } else {
            fprintf (stderr, "Error:  Unknown entity type: %s\n", dtype);
            exit (1);
        }
        setBy = i;
        setArg = argv;
    } else {
        fprintf (stderr,
        "Error:  Daemon type implied by arg %d (%s) contradicts arg %d (%s)\n",
        	i, argv, setBy, setArg);
    }
}

char *
getModeStr()
{
	switch (mode)
	{
		case MODE_NOTSET:				return "Not set";
		case MODE_STARTD_NORMAL:		return "Normal (Startd)";
		case MODE_STARTD_AVAIL:			return "Available (Startd)";
		case MODE_STARTD_RUN:			return "Run (Startd)";
		case MODE_SCHEDD_NORMAL:		return "Normal (Schedd)";
		case MODE_SCHEDD_SUBMITTORS:	return "Submittors (Schedd)";
		case MODE_MASTER_NORMAL:		return "Normal (Master)";
		case MODE_CKPT_SRVR_NORMAL:		return "Normal (CkptSrvr)";
		default:				return "<Unknown!>";
	}
	// should never get here
	exit (1);
}

void
setMode (Mode mod, int i, char *argv)
{
    static int setBy = 0;
    static char *setArg = NULL;

	if (argv == NULL) {
		printf("Set by arg %d (%-10s), Mode = %s\n",setBy,setArg,getModeStr());
		return;
	}

    if (setBy == 0) {
        mode = mod;
        switch (mod) {
          case MODE_STARTD_NORMAL:
            setType ("STARTD", i, argv);
            setPPstyle (PP_STARTD_NORMAL, i, argv);
            break;

          case MODE_STARTD_AVAIL:
            setType ("STARTD", i, argv);
            setPPstyle (PP_STARTD_NORMAL, i, argv);
            break;

          case MODE_STARTD_RUN:
            setType ("STARTD", i, argv);
            setPPstyle (PP_STARTD_RUN, i, argv);
            break;

		  case MODE_SCHEDD_NORMAL:
            setType ("SCHEDD", i, argv);
            setPPstyle (PP_SCHEDD_NORMAL, i, argv);
            break;

		  case MODE_SCHEDD_SUBMITTORS:
            setType ("SUBMITTOR", i, argv);
            setPPstyle (PP_SCHEDD_SUBMITTORS, i, argv);
            break;

		  case MODE_MASTER_NORMAL:
			setType ("MASTER", i, argv);
			setPPstyle (PP_MASTER_NORMAL, i, argv);
			break;

		  case MODE_CKPT_SRVR_NORMAL:
			setType ("CKPT_SRVR", i, argv);
			setPPstyle (PP_CKPT_SRVR_NORMAL, i, argv);
			break;

          default:
            fprintf (stderr, "Error:  Illegal mode %d\n", mode);
            break;
        }
        setBy = i;
        setArg = argv;
    } else {
        fprintf (stderr, "Error:  Arg %d (%s) contradicts arg %d (%s)\n",
                            i, argv, setBy, setArg);
        exit (1);
    }
}

<|endoftext|>


<commit_before>#include "Common.h"
#include "Config.h"
#include "OpenGL.h"
#include "Window.h"

/****** Variables *******/

static GLFWwindow* g_Window = NULL;
static int g_WindowWidth  = 0;
static int g_WindowHeight = 0;
static int g_FramebufferWidth  = 0;
static int g_FramebufferHeight = 0;
static FramebufferResizeFn g_FramebufferResizeFn = NULL;
static CursorMoveFn        g_CursorMoveFn = NULL;
static MouseButtonActionFn g_MouseButtonActionFn = NULL;
static MouseScrollFn       g_MouseScrollFn = NULL;
static KeyActionFn         g_KeyActionFn = NULL;

/****** General *******/

static void OnGLFWError( int code, const char* description );
static void OnDebugEvent( GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char* message, void* userParam );
static void OnWindowResize( GLFWwindow* window, int width, int height );
static void OnFramebufferResize( GLFWwindow* window, int width, int height );
static void OnMouseButtonAction( GLFWwindow* window, int button, int action, int mods );
static void OnMouseScroll( GLFWwindow* window, double xoffset, double yoffset );
static void OnCursorMove( GLFWwindow* window, double x, double y );
static void OnKeyAction( GLFWwindow* window, int key, int scancode, int action, int mods );

bool InitWindow()
{
    const int width  = GetConfigInt("window.width",  640);
    const int height = GetConfigInt("window.height", 480);
    const char* title = GetConfigString("window.title", "Apoapsis");

    const int versionMajor = GetConfigInt("opengl.major", 2);
    const int versionMinor = GetConfigInt("opengl.minor", 1);
    const bool debug = GetConfigBool("opengl.debug", false);
    const bool vsync = GetConfigBool("opengl.vsync", true);
    const bool experimentalDrivers = GetConfigBool("opengl.experimental-drivers", false);

    assert(g_Window == NULL);
    glfwSetErrorCallback(OnGLFWError);
    if(!glfwInit())
    {
        Error("GLFW init failed.");
        return false;
    }

    glfwDefaultWindowHints();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, versionMajor);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, versionMinor);
    glfwWindowHint(GLFW_DEPTH_BITS, GetConfigInt("opengl.depth-bits", 24));
    glfwWindowHint(GLFW_STENCIL_BITS, 0);
    glfwWindowHint(GLFW_SAMPLES, GetConfigInt("opengl.samples", 0));
    glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, debug ? GL_TRUE : GL_FALSE);

    g_Window = glfwCreateWindow(width, height, title, NULL, NULL);
    if(!g_Window)
    {
        Error("Window creation failed.");
        return false;
    }

    glfwGetWindowSize(g_Window, &g_WindowWidth, &g_WindowHeight);
    glfwGetFramebufferSize(g_Window, &g_FramebufferWidth, &g_FramebufferHeight);

    glfwMakeContextCurrent(g_Window);

    glewExperimental = experimentalDrivers ? GL_TRUE : GL_FALSE;
    GLenum glewErrorCode = glewInit();
    if(glewErrorCode != GLEW_OK)
    {
        Error("GLEW Error: %s", glewGetErrorString(glewErrorCode));
        return false;
    }

    Log(
        "Using OpenGL %s\n"
        "Vendor: %s\n"
        "Renderer: %s\n"
        "GLSL: %s\n"
        "GLEW: %s",

        glGetString(GL_VERSION),
        glGetString(GL_VENDOR),
        glGetString(GL_RENDERER),
        glGetString(GL_SHADING_LANGUAGE_VERSION),
        glewGetString(GLEW_VERSION)
    );

    if(vsync)
    {
#if defined(_WIN32)
        if(glfwExtensionSupported("WGL_EXT_swap_control_tear"))
#else
        if(glfwExtensionSupported("GLX_EXT_swap_control_tear"))
#endif
            glfwSwapInterval(-1); // enable vsync (allow the driver to swap even if a frame arrives a little bit late)
        else
            glfwSwapInterval(1); // enable vsync
    }

    glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
    glfwSetInputMode(g_Window, GLFW_STICKY_KEYS, GL_FALSE);
    glfwSetInputMode(g_Window, GLFW_STICKY_MOUSE_BUTTONS, GL_FALSE);

    if(GLEW_ARB_seamless_cube_map)
    {
        Log("Seamless cubemap filtering supported");
        glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
    }

    if(debug)
    {
        if(GLEW_ARB_debug_output)
        {
            glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
            glDebugMessageCallbackARB(OnDebugEvent, NULL);
            Log("Debug output supported! You may receive debug messages from your OpenGL driver.");
        }
        else
        {
            Error("Debug output requested, but it's not supported!");
        }
    }

    glfwSetWindowSizeCallback(g_Window, OnWindowResize);
    glfwSetFramebufferSizeCallback(g_Window, OnFramebufferResize);
    glfwSetMouseButtonCallback(g_Window, OnMouseButtonAction);
    glfwSetScrollCallback(g_Window, OnMouseScroll);
    glfwSetCursorPosCallback(g_Window, OnCursorMove);
    glfwSetKeyCallback(g_Window, OnKeyAction);

    return true;
}

void DestroyWindow()
{
    assert(g_Window != NULL);
    glfwDestroyWindow(g_Window);
    glfwTerminate();
}

void SwapBuffers()
{
    glfwSwapBuffers(g_Window);
    glfwPollEvents();
}

void SetWindowTitle( const char* title )
{
    glfwSetWindowTitle(g_Window, title);
}

void FlagWindowForClose()
{
    glfwSetWindowShouldClose(g_Window, GL_TRUE);
}

bool WindowShouldClose()
{
    return glfwWindowShouldClose(g_Window) == GL_TRUE;
}

void* GetGLFWwindow()
{
    return g_Window;
}

glm::ivec2 GetFramebufferSize()
{
    return glm::ivec2(g_FramebufferWidth, g_FramebufferHeight);
}

/****** Input ******/

void SetCursorMode( int mode )
{
    glfwSetInputMode(g_Window, GLFW_CURSOR, mode);
}

/******* Callback Setter *******/

void SetFrambufferFn( FramebufferResizeFn fn )
{
    g_FramebufferResizeFn = fn;
    OnFramebufferResize(NULL, g_FramebufferWidth, g_FramebufferHeight);
}

void SetCursorMoveFn( CursorMoveFn fn )
{
    g_CursorMoveFn = fn;
}

void SetMouseButtonActionFn( MouseButtonActionFn fn )
{
    g_MouseButtonActionFn = fn;
}

void SetMouseScrollFn( MouseScrollFn fn )
{
    g_MouseScrollFn = fn;
}

void SetKeyActionFn( KeyActionFn fn )
{
    g_KeyActionFn = fn;
}

/******* Callbacks ********/

static void OnGLFWError( int code, const char* description )
{
    Error("GLFW error %d: %s", code, description);
}

static void OnDebugEvent( GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char* message, void* userParam )
{
    const char* sourceName = "";
    switch(source)
    {
        case GL_DEBUG_SOURCE_API_ARB: sourceName = "API"; break;
        case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB: sourceName = "window system"; break;
        case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB: sourceName = "shader"; break;
        case GL_DEBUG_SOURCE_THIRD_PARTY_ARB: sourceName = "third party"; break;
        case GL_DEBUG_SOURCE_APPLICATION_ARB: sourceName = "application"; break;
        case GL_DEBUG_SOURCE_OTHER_ARB: sourceName = ""; break;
    }

    const char* typeName = "unknown issue";
    switch(type)
    {
        case GL_DEBUG_TYPE_ERROR_ARB: typeName = "error"; break;
        case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB: typeName = "deprecated behavior"; break;
        case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB: typeName = "undefined behavior"; break;
        case GL_DEBUG_TYPE_PORTABILITY_ARB: typeName = "partability issue"; break;
        case GL_DEBUG_TYPE_PERFORMANCE_ARB: typeName = "performance issue"; break;
        case GL_DEBUG_TYPE_OTHER_ARB: typeName = "unknown issue"; break;
    }

    const char* severityName = "";
    switch(severity)
    {
        case GL_DEBUG_SEVERITY_HIGH_ARB: severityName = "High"; break;
        case GL_DEBUG_SEVERITY_MEDIUM_ARB: severityName = "Medium"; break;
        case GL_DEBUG_SEVERITY_LOW_ARB: severityName = "Low"; break;
    }

    Error("%s severity %s %s %d, %s", severityName, sourceName, typeName, id, message);
    //Error("%s severity %s %s %d:\n%s", severityName, sourceName, typeName, id, message);
}

static void OnWindowResize( GLFWwindow* window, int width, int height )
{
    Log("window resize %dx%d", width, height);
    g_WindowWidth = width;
    g_WindowHeight = height;
    // TODO: Update cursor position
}

static void OnFramebufferResize( GLFWwindow* window, int width, int height )
{
    Log("framebuffer resize %dx%d", width, height);
    g_FramebufferWidth = width;
    g_FramebufferHeight = height;
    // TODO: Update cursor position
    if(g_FramebufferResizeFn)
        g_FramebufferResizeFn(width, height);
}

static void OnMouseButtonAction( GLFWwindow* window, int button, int action, int mods )
{
    if(g_MouseButtonActionFn)
        g_MouseButtonActionFn(button, action==GLFW_PRESS);
}

static void OnMouseScroll( GLFWwindow* window, double xoffset, double yoffset )
{
    if(g_MouseScrollFn)
        g_MouseScrollFn(xoffset, yoffset);
}

static void OnCursorMove( GLFWwindow* window, double x, double y )
{
    x *= g_FramebufferWidth / g_WindowWidth;
    y *= g_FramebufferHeight / g_WindowHeight;

    if(g_CursorMoveFn)
        g_CursorMoveFn(x, y);
}

static void OnKeyAction( GLFWwindow* window, int key, int scancode, int action, int mods )
{
    if(action != GLFW_REPEAT && g_KeyActionFn)
        g_KeyActionFn(key, scancode, action==GLFW_PRESS);
}
<commit_msg>Fixed OpenGL debug callback signature.<commit_after>#include "Common.h"
#include "Config.h"
#include "OpenGL.h"
#include "Window.h"

/****** Variables *******/

static GLFWwindow* g_Window = NULL;
static int g_WindowWidth  = 0;
static int g_WindowHeight = 0;
static int g_FramebufferWidth  = 0;
static int g_FramebufferHeight = 0;
static FramebufferResizeFn g_FramebufferResizeFn = NULL;
static CursorMoveFn        g_CursorMoveFn = NULL;
static MouseButtonActionFn g_MouseButtonActionFn = NULL;
static MouseScrollFn       g_MouseScrollFn = NULL;
static KeyActionFn         g_KeyActionFn = NULL;

/****** General *******/

static void OnGLFWError( int code, const char* description );
static void OnDebugEvent( GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char* message, const void* userParam );
static void OnWindowResize( GLFWwindow* window, int width, int height );
static void OnFramebufferResize( GLFWwindow* window, int width, int height );
static void OnMouseButtonAction( GLFWwindow* window, int button, int action, int mods );
static void OnMouseScroll( GLFWwindow* window, double xoffset, double yoffset );
static void OnCursorMove( GLFWwindow* window, double x, double y );
static void OnKeyAction( GLFWwindow* window, int key, int scancode, int action, int mods );

bool InitWindow()
{
    const int width  = GetConfigInt("window.width",  640);
    const int height = GetConfigInt("window.height", 480);
    const char* title = GetConfigString("window.title", "Apoapsis");

    const int versionMajor = GetConfigInt("opengl.major", 2);
    const int versionMinor = GetConfigInt("opengl.minor", 1);
    const bool debug = GetConfigBool("opengl.debug", false);
    const bool vsync = GetConfigBool("opengl.vsync", true);
    const bool experimentalDrivers = GetConfigBool("opengl.experimental-drivers", false);

    assert(g_Window == NULL);
    glfwSetErrorCallback(OnGLFWError);
    if(!glfwInit())
    {
        Error("GLFW init failed.");
        return false;
    }

    glfwDefaultWindowHints();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, versionMajor);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, versionMinor);
    glfwWindowHint(GLFW_DEPTH_BITS, GetConfigInt("opengl.depth-bits", 24));
    glfwWindowHint(GLFW_STENCIL_BITS, 0);
    glfwWindowHint(GLFW_SAMPLES, GetConfigInt("opengl.samples", 0));
    glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, debug ? GL_TRUE : GL_FALSE);

    g_Window = glfwCreateWindow(width, height, title, NULL, NULL);
    if(!g_Window)
    {
        Error("Window creation failed.");
        return false;
    }

    glfwGetWindowSize(g_Window, &g_WindowWidth, &g_WindowHeight);
    glfwGetFramebufferSize(g_Window, &g_FramebufferWidth, &g_FramebufferHeight);

    glfwMakeContextCurrent(g_Window);

    glewExperimental = experimentalDrivers ? GL_TRUE : GL_FALSE;
    GLenum glewErrorCode = glewInit();
    if(glewErrorCode != GLEW_OK)
    {
        Error("GLEW Error: %s", glewGetErrorString(glewErrorCode));
        return false;
    }

    Log(
        "Using OpenGL %s\n"
        "Vendor: %s\n"
        "Renderer: %s\n"
        "GLSL: %s\n"
        "GLEW: %s",

        glGetString(GL_VERSION),
        glGetString(GL_VENDOR),
        glGetString(GL_RENDERER),
        glGetString(GL_SHADING_LANGUAGE_VERSION),
        glewGetString(GLEW_VERSION)
    );

    if(vsync)
    {
#if defined(_WIN32)
        if(glfwExtensionSupported("WGL_EXT_swap_control_tear"))
#else
        if(glfwExtensionSupported("GLX_EXT_swap_control_tear"))
#endif
            glfwSwapInterval(-1); // enable vsync (allow the driver to swap even if a frame arrives a little bit late)
        else
            glfwSwapInterval(1); // enable vsync
    }

    glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
    glfwSetInputMode(g_Window, GLFW_STICKY_KEYS, GL_FALSE);
    glfwSetInputMode(g_Window, GLFW_STICKY_MOUSE_BUTTONS, GL_FALSE);

    if(GLEW_ARB_seamless_cube_map)
    {
        Log("Seamless cubemap filtering supported");
        glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
    }

    if(debug)
    {
        if(GLEW_ARB_debug_output)
        {
            glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
            glDebugMessageCallbackARB(OnDebugEvent, NULL);
            Log("Debug output supported! You may receive debug messages from your OpenGL driver.");
        }
        else
        {
            Error("Debug output requested, but it's not supported!");
        }
    }

    glfwSetWindowSizeCallback(g_Window, OnWindowResize);
    glfwSetFramebufferSizeCallback(g_Window, OnFramebufferResize);
    glfwSetMouseButtonCallback(g_Window, OnMouseButtonAction);
    glfwSetScrollCallback(g_Window, OnMouseScroll);
    glfwSetCursorPosCallback(g_Window, OnCursorMove);
    glfwSetKeyCallback(g_Window, OnKeyAction);

    return true;
}

void DestroyWindow()
{
    assert(g_Window != NULL);
    glfwDestroyWindow(g_Window);
    glfwTerminate();
}

void SwapBuffers()
{
    glfwSwapBuffers(g_Window);
    glfwPollEvents();
}

void SetWindowTitle( const char* title )
{
    glfwSetWindowTitle(g_Window, title);
}

void FlagWindowForClose()
{
    glfwSetWindowShouldClose(g_Window, GL_TRUE);
}

bool WindowShouldClose()
{
    return glfwWindowShouldClose(g_Window) == GL_TRUE;
}

void* GetGLFWwindow()
{
    return g_Window;
}

glm::ivec2 GetFramebufferSize()
{
    return glm::ivec2(g_FramebufferWidth, g_FramebufferHeight);
}

/****** Input ******/

void SetCursorMode( int mode )
{
    glfwSetInputMode(g_Window, GLFW_CURSOR, mode);
}

/******* Callback Setter *******/

void SetFrambufferFn( FramebufferResizeFn fn )
{
    g_FramebufferResizeFn = fn;
    OnFramebufferResize(NULL, g_FramebufferWidth, g_FramebufferHeight);
}

void SetCursorMoveFn( CursorMoveFn fn )
{
    g_CursorMoveFn = fn;
}

void SetMouseButtonActionFn( MouseButtonActionFn fn )
{
    g_MouseButtonActionFn = fn;
}

void SetMouseScrollFn( MouseScrollFn fn )
{
    g_MouseScrollFn = fn;
}

void SetKeyActionFn( KeyActionFn fn )
{
    g_KeyActionFn = fn;
}

/******* Callbacks ********/

static void OnGLFWError( int code, const char* description )
{
    Error("GLFW error %d: %s", code, description);
}

static void OnDebugEvent( GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char* message, const void* userParam )
{
    const char* sourceName = "";
    switch(source)
    {
        case GL_DEBUG_SOURCE_API_ARB: sourceName = "API"; break;
        case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB: sourceName = "window system"; break;
        case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB: sourceName = "shader"; break;
        case GL_DEBUG_SOURCE_THIRD_PARTY_ARB: sourceName = "third party"; break;
        case GL_DEBUG_SOURCE_APPLICATION_ARB: sourceName = "application"; break;
        case GL_DEBUG_SOURCE_OTHER_ARB: sourceName = ""; break;
    }

    const char* typeName = "unknown issue";
    switch(type)
    {
        case GL_DEBUG_TYPE_ERROR_ARB: typeName = "error"; break;
        case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB: typeName = "deprecated behavior"; break;
        case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB: typeName = "undefined behavior"; break;
        case GL_DEBUG_TYPE_PORTABILITY_ARB: typeName = "partability issue"; break;
        case GL_DEBUG_TYPE_PERFORMANCE_ARB: typeName = "performance issue"; break;
        case GL_DEBUG_TYPE_OTHER_ARB: typeName = "unknown issue"; break;
    }

    const char* severityName = "";
    switch(severity)
    {
        case GL_DEBUG_SEVERITY_HIGH_ARB: severityName = "High"; break;
        case GL_DEBUG_SEVERITY_MEDIUM_ARB: severityName = "Medium"; break;
        case GL_DEBUG_SEVERITY_LOW_ARB: severityName = "Low"; break;
    }

    Error("%s severity %s %s %d, %s", severityName, sourceName, typeName, id, message);
    //Error("%s severity %s %s %d:\n%s", severityName, sourceName, typeName, id, message);
}

static void OnWindowResize( GLFWwindow* window, int width, int height )
{
    Log("window resize %dx%d", width, height);
    g_WindowWidth = width;
    g_WindowHeight = height;
    // TODO: Update cursor position
}

static void OnFramebufferResize( GLFWwindow* window, int width, int height )
{
    Log("framebuffer resize %dx%d", width, height);
    g_FramebufferWidth = width;
    g_FramebufferHeight = height;
    // TODO: Update cursor position
    if(g_FramebufferResizeFn)
        g_FramebufferResizeFn(width, height);
}

static void OnMouseButtonAction( GLFWwindow* window, int button, int action, int mods )
{
    if(g_MouseButtonActionFn)
        g_MouseButtonActionFn(button, action==GLFW_PRESS);
}

static void OnMouseScroll( GLFWwindow* window, double xoffset, double yoffset )
{
    if(g_MouseScrollFn)
        g_MouseScrollFn(xoffset, yoffset);
}

static void OnCursorMove( GLFWwindow* window, double x, double y )
{
    x *= g_FramebufferWidth / g_WindowWidth;
    y *= g_FramebufferHeight / g_WindowHeight;

    if(g_CursorMoveFn)
        g_CursorMoveFn(x, y);
}

static void OnKeyAction( GLFWwindow* window, int key, int scancode, int action, int mods )
{
    if(action != GLFW_REPEAT && g_KeyActionFn)
        g_KeyActionFn(key, scancode, action==GLFW_PRESS);
}
<|endoftext|>


<commit_before>#include "master.hpp"

namespace factor
{

/* Simple wrappers for ANSI C I/O functions, used for bootstrapping.

Note the ugly loop logic in almost every function; we have to handle EINTR
and restart the operation if the system call was interrupted. Naive
applications don't do this, but then they quickly fail if one enables
itimer()s or other signals.

The Factor library provides platform-specific code for Unix and Windows
with many more capabilities so these words are not usually used in
normal operation. */

void factor_vm::init_c_io()
{
	special_objects[OBJ_STDIN] = allot_alien(false_object,(cell)stdin);
	special_objects[OBJ_STDOUT] = allot_alien(false_object,(cell)stdout);
	special_objects[OBJ_STDERR] = allot_alien(false_object,(cell)stderr);
}

void factor_vm::io_error()
{
	if(errno == EINTR)
		return;

	general_error(ERROR_IO,tag_fixnum(errno),false_object);
}

FILE *factor_vm::safe_fopen(char *filename, char *mode)
{
	FILE *file;
	for(;;)
	{
		file = fopen(filename,mode);
		if(file == NULL)
			io_error();
		else
			break;
	}
	return file;
}

int factor_vm::safe_fgetc(FILE *stream)
{
	int c;
	for(;;)
	{
		c = getc(stream);
		if(c == EOF)
		{
			if(feof(stream))
				return EOF;
			else
				io_error();
		}
		else
			break;
	}
	return c;
}

size_t factor_vm::safe_fread(void *ptr, size_t size, size_t nitems, FILE *stream)
{
	size_t items_read = 0;
	size_t ret = 0;

	do
	{
		ret = fread((void*)((int*)ptr+items_read*size),size,nitems-items_read,stream);
		if(ret == 0)
		{
			if(feof(stream))
				break;
			else
				io_error();
		}
		items_read += ret;
	} while(items_read != nitems);

	return items_read;
}

void factor_vm::safe_fputc(int c, FILE *stream)
{
	for(;;)
	{
		if(putc(c,stream) == EOF)
			io_error();
		else
			break;
	}
}

size_t factor_vm::safe_fwrite(void *ptr, size_t size, size_t nitems, FILE *stream)
{
	size_t items_written = 0;
	size_t ret = 0;

	do {
		ret = fwrite((void*)((int*)ptr+items_written*size),size,nitems-items_written,stream);
		if(ret == 0)
			io_error();
		items_written += ret;
	} while(items_written != nitems);

	return items_written;
}

int factor_vm::safe_ftell(FILE *stream)
{
	off_t offset;
	for(;;)
	{
		if((offset = FTELL(stream)) == -1)
			io_error();
		else
			break;
	}
	return offset;
}

void factor_vm::safe_fseek(FILE *stream, off_t offset, int whence)
{
	switch(whence)
	{
	case 0: whence = SEEK_SET; break;
	case 1: whence = SEEK_CUR; break;
	case 2: whence = SEEK_END; break;
	default:
		critical_error("Bad value for whence",whence);
	}

	for(;;)
	{
		if(FSEEK(stream,offset,whence) == -1)
			io_error();
		else
			break;
	}
}

void factor_vm::safe_fflush(FILE *stream)
{
	for(;;)
	{
		if(fflush(stream) == EOF)
			io_error();
		else
			break;
	}
}

void factor_vm::safe_fclose(FILE *stream)
{
	for(;;)
	{
		if(fclose(stream) == EOF)
			io_error();
		else
			break;
	}
}

void factor_vm::primitive_fopen()
{
	data_root<byte_array> mode(ctx->pop(),this);
	data_root<byte_array> path(ctx->pop(),this);
	mode.untag_check(this);
	path.untag_check(this);

	FILE *file;
	file = safe_fopen((char *)(path.untagged() + 1),
		(char *)(mode.untagged() + 1));
	ctx->push(allot_alien(file));
}

FILE *factor_vm::pop_file_handle()
{
	return (FILE *)alien_offset(ctx->pop());
}

FILE *factor_vm::peek_file_handle()
{
	return (FILE *)alien_offset(ctx->peek());
}

void factor_vm::primitive_fgetc()
{
	FILE *file = peek_file_handle();

	int c = safe_fgetc(file);
	if(c == EOF && feof(file))
	{
		clearerr(file);
		ctx->replace(false_object);
	}
	else
		ctx->replace(tag_fixnum(c));
}

/* Allocates memory */
void factor_vm::primitive_fread()
{
	FILE *file = pop_file_handle();
	void *buf = (void*)alien_offset(ctx->peek());
	fixnum size = unbox_array_size();

	if(size == 0)
	{
		ctx->replace(from_unsigned_cell(0));
		return;
	}

	size_t c = safe_fread(buf,1,size,file);
	if(c == 0 || feof(file))
		clearerr(file);
	ctx->replace(from_unsigned_cell(c));
}

void factor_vm::primitive_fputc()
{
	FILE *file = pop_file_handle();
	fixnum ch = to_fixnum(ctx->pop());
	safe_fputc((int)ch, file);
}

void factor_vm::primitive_fwrite()
{
	FILE *file = pop_file_handle();
	cell length = to_cell(ctx->pop());
	char *text = alien_offset(ctx->pop());

	if(length == 0)
		return;

	size_t written = safe_fwrite(text,1,length,file);
	if(written != length)
		io_error();
}

void factor_vm::primitive_ftell()
{
	FILE *file = peek_file_handle();
	ctx->replace(from_signed_8(safe_ftell(file)));
}

void factor_vm::primitive_fseek()
{
	FILE *file = pop_file_handle();
	int whence = (int)to_fixnum(ctx->pop());
	off_t offset = (off_t)to_signed_8(ctx->pop());
	safe_fseek(file,offset,whence);
}

void factor_vm::primitive_fflush()
{
	FILE *file = pop_file_handle();
	safe_fflush(file);
}

void factor_vm::primitive_fclose()
{
	FILE *file = pop_file_handle();
	safe_fclose(file);
}

/* This function is used by FFI I/O. Accessing the errno global directly is
not portable, since on some libc's errno is not a global but a funky macro that
reads thread-local storage. */
VM_C_API int err_no()
{
	return errno;
}

VM_C_API void set_err_no(int err)
{
	errno = err;
}
}
<commit_msg>vm: use ctx->push since unbox_array_size needs to peek at the stack.<commit_after>#include "master.hpp"

namespace factor
{

/* Simple wrappers for ANSI C I/O functions, used for bootstrapping.

Note the ugly loop logic in almost every function; we have to handle EINTR
and restart the operation if the system call was interrupted. Naive
applications don't do this, but then they quickly fail if one enables
itimer()s or other signals.

The Factor library provides platform-specific code for Unix and Windows
with many more capabilities so these words are not usually used in
normal operation. */

void factor_vm::init_c_io()
{
	special_objects[OBJ_STDIN] = allot_alien(false_object,(cell)stdin);
	special_objects[OBJ_STDOUT] = allot_alien(false_object,(cell)stdout);
	special_objects[OBJ_STDERR] = allot_alien(false_object,(cell)stderr);
}

void factor_vm::io_error()
{
	if(errno == EINTR)
		return;

	general_error(ERROR_IO,tag_fixnum(errno),false_object);
}

FILE *factor_vm::safe_fopen(char *filename, char *mode)
{
	FILE *file;
	for(;;)
	{
		file = fopen(filename,mode);
		if(file == NULL)
			io_error();
		else
			break;
	}
	return file;
}

int factor_vm::safe_fgetc(FILE *stream)
{
	int c;
	for(;;)
	{
		c = getc(stream);
		if(c == EOF)
		{
			if(feof(stream))
				return EOF;
			else
				io_error();
		}
		else
			break;
	}
	return c;
}

size_t factor_vm::safe_fread(void *ptr, size_t size, size_t nitems, FILE *stream)
{
	size_t items_read = 0;
	size_t ret = 0;

	do
	{
		ret = fread((void*)((int*)ptr+items_read*size),size,nitems-items_read,stream);
		if(ret == 0)
		{
			if(feof(stream))
				break;
			else
				io_error();
		}
		items_read += ret;
	} while(items_read != nitems);

	return items_read;
}

void factor_vm::safe_fputc(int c, FILE *stream)
{
	for(;;)
	{
		if(putc(c,stream) == EOF)
			io_error();
		else
			break;
	}
}

size_t factor_vm::safe_fwrite(void *ptr, size_t size, size_t nitems, FILE *stream)
{
	size_t items_written = 0;
	size_t ret = 0;

	do {
		ret = fwrite((void*)((int*)ptr+items_written*size),size,nitems-items_written,stream);
		if(ret == 0)
			io_error();
		items_written += ret;
	} while(items_written != nitems);

	return items_written;
}

int factor_vm::safe_ftell(FILE *stream)
{
	off_t offset;
	for(;;)
	{
		if((offset = FTELL(stream)) == -1)
			io_error();
		else
			break;
	}
	return offset;
}

void factor_vm::safe_fseek(FILE *stream, off_t offset, int whence)
{
	switch(whence)
	{
	case 0: whence = SEEK_SET; break;
	case 1: whence = SEEK_CUR; break;
	case 2: whence = SEEK_END; break;
	default:
		critical_error("Bad value for whence",whence);
	}

	for(;;)
	{
		if(FSEEK(stream,offset,whence) == -1)
			io_error();
		else
			break;
	}
}

void factor_vm::safe_fflush(FILE *stream)
{
	for(;;)
	{
		if(fflush(stream) == EOF)
			io_error();
		else
			break;
	}
}

void factor_vm::safe_fclose(FILE *stream)
{
	for(;;)
	{
		if(fclose(stream) == EOF)
			io_error();
		else
			break;
	}
}

void factor_vm::primitive_fopen()
{
	data_root<byte_array> mode(ctx->pop(),this);
	data_root<byte_array> path(ctx->pop(),this);
	mode.untag_check(this);
	path.untag_check(this);

	FILE *file;
	file = safe_fopen((char *)(path.untagged() + 1),
		(char *)(mode.untagged() + 1));
	ctx->push(allot_alien(file));
}

FILE *factor_vm::pop_file_handle()
{
	return (FILE *)alien_offset(ctx->pop());
}

FILE *factor_vm::peek_file_handle()
{
	return (FILE *)alien_offset(ctx->peek());
}

void factor_vm::primitive_fgetc()
{
	FILE *file = peek_file_handle();

	int c = safe_fgetc(file);
	if(c == EOF && feof(file))
	{
		clearerr(file);
		ctx->replace(false_object);
	}
	else
		ctx->replace(tag_fixnum(c));
}

/* Allocates memory */
void factor_vm::primitive_fread()
{
	FILE *file = pop_file_handle();
	void *buf = (void*)alien_offset(ctx->pop());
	fixnum size = unbox_array_size();

	if(size == 0)
	{
		ctx->push(from_unsigned_cell(0));
		return;
	}

	size_t c = safe_fread(buf,1,size,file);
	if(c == 0 || feof(file))
		clearerr(file);
	ctx->push(from_unsigned_cell(c));
}

void factor_vm::primitive_fputc()
{
	FILE *file = pop_file_handle();
	fixnum ch = to_fixnum(ctx->pop());
	safe_fputc((int)ch, file);
}

void factor_vm::primitive_fwrite()
{
	FILE *file = pop_file_handle();
	cell length = to_cell(ctx->pop());
	char *text = alien_offset(ctx->pop());

	if(length == 0)
		return;

	size_t written = safe_fwrite(text,1,length,file);
	if(written != length)
		io_error();
}

void factor_vm::primitive_ftell()
{
	FILE *file = peek_file_handle();
	ctx->replace(from_signed_8(safe_ftell(file)));
}

void factor_vm::primitive_fseek()
{
	FILE *file = pop_file_handle();
	int whence = (int)to_fixnum(ctx->pop());
	off_t offset = (off_t)to_signed_8(ctx->pop());
	safe_fseek(file,offset,whence);
}

void factor_vm::primitive_fflush()
{
	FILE *file = pop_file_handle();
	safe_fflush(file);
}

void factor_vm::primitive_fclose()
{
	FILE *file = pop_file_handle();
	safe_fclose(file);
}

/* This function is used by FFI I/O. Accessing the errno global directly is
not portable, since on some libc's errno is not a global but a funky macro that
reads thread-local storage. */
VM_C_API int err_no()
{
	return errno;
}

VM_C_API void set_err_no(int err)
{
	errno = err;
}
}
<|endoftext|>


<commit_before>// __BEGIN_LICENSE__
// Copyright (C) 2006-2010 United States Government as represented by
// the Administrator of the National Aeronautics and Space Administration.
// All Rights Reserved.
// __END_LICENSE__

#include <vw/Cartography/Datum.h>
#include <vw/Math/Functions.h>

vw::cartography::Datum::Datum(std::string const& name,
                              std::string const& spheroid_name,
                              std::string const& meridian_name,
                              double semi_major_axis,
                              double semi_minor_axis,
                              double meridian_offset)
  : m_name(name),
    m_spheroid_name(spheroid_name),
    m_meridian_name(meridian_name),
    m_semi_major_axis(semi_major_axis),
    m_semi_minor_axis(semi_minor_axis),
    m_meridian_offset(meridian_offset),
    m_geocentric(false)
{
  std::ostringstream strm;
  strm << "+a=" << semi_major_axis << " +b=" << semi_minor_axis;
  m_proj_str = strm.str();
}

void vw::cartography::Datum::set_well_known_datum( std::string const& name ) {
  m_meridian_name = "Greenwich";
  m_geocentric = false;

  m_meridian_offset = 0;
  if (name == "WGS84") {
    m_name = "WGS_1984";
    m_spheroid_name="WGS 84";
    m_semi_major_axis = 6378137.0;
    m_semi_minor_axis = 6356752.3;
    m_proj_str = "+ellps=WGS84 +datum=WGS84";
    return;
  }

  if (name == "WGS72") {
    m_name="WGS_1972";
    m_spheroid_name="WGS 72";
    m_semi_major_axis = 6378135.0;
    m_semi_minor_axis = 6356750.5;
    m_proj_str = "+ellps=WGS72 +towgs84=0,0,4.5,0,0,0.554,0.2263";
    return;
  }

  if (name == "NAD83") {
    m_name="North_American_Datum_1983";
    m_spheroid_name="GRS 1980";
    m_semi_major_axis = 6378137;
    m_semi_minor_axis = 6356752.3;
    m_proj_str = "+ellps=GRS80 +datum=NAD83";
    return;
  }

  if (name == "NAD27") {
    m_name="North_American_Datum_1927";
    m_spheroid_name="Clarke 1866";
    m_semi_major_axis = 6378206.4;
    m_semi_minor_axis = 6356583.8;
    m_proj_str = "+ellps=clrk66 +datum=NAD27";
    return;
  }

  vw::vw_throw( vw::InputErr() << "Unknown datum string \"" << name << "\"!");
}

void vw::cartography::Datum::set_semi_major_axis(double val) {
  m_semi_major_axis = val;
  std::ostringstream strm;
  strm << "+a=" << m_semi_major_axis << " +b=" << m_semi_minor_axis;
  if (m_geocentric) strm << " +geoc";
  m_proj_str = strm.str();
}

void vw::cartography::Datum::set_semi_minor_axis(double val) {
  m_semi_minor_axis = val;
  std::ostringstream strm;
  strm << "+a=" << m_semi_major_axis << " +b=" << m_semi_minor_axis;
  if (m_geocentric) strm << " +geoc";
  m_proj_str = strm.str();
}

// return meridian radius of curvature.  NOT geocentric radius
double vw::cartography::Datum::radius(double /*lon*/, double lat) const {
  // Optimize in the case of spherical datum
  if (m_semi_major_axis == m_semi_minor_axis) {
    return m_semi_major_axis;
  }

  // Bi-axial Ellpisoid datum
  double a = m_semi_major_axis;
  double b = m_semi_minor_axis;
  double t = atan((a/b) * tan(lat * M_PI / 180.0));
  double x = a * cos(t);
  double y = b * sin(t);
  return sqrt(x*x + y*y);
}

double vw::cartography::Datum::geocentric_latitude(double lat) const {
   // Optimize in the case of spherical datum
  if (m_semi_major_axis == m_semi_minor_axis) {
    return m_semi_major_axis;
  }

  // Bi-axial Ellpisoid datum
  // http://mathworld.wolfram.com/GeocentricLatitude.html
  double a = m_semi_major_axis;
  double b = m_semi_minor_axis;
  double a2 = a * a;
  double b2 = b * b;
  double e2 = (a2 - b2) / a2;
  return atan((1-e2)*tan(lat * M_PI / 180.0));

}

double vw::cartography::Datum::radius_of_curvature(double /*lon*/, double lat) const {
  // Optimize in the case of spherical datum
  if (m_semi_major_axis == m_semi_minor_axis) {
    return m_semi_major_axis;
  }

  // Bi-axial Ellpisoid datum
  double a = m_semi_major_axis;
  double b = m_semi_minor_axis;
  double a2 = a * a;
  double b2 = b * b;
  double e2 = (a2 - b2) / a2;
  double slat = sin(M_PI/180*lat);
  return a / sqrt(1.0 - e2*slat*slat);
}

// return meridian radius of curvature.  NOT geocentric radius
double vw::cartography::Datum::geocentric_radius(double /*lon*/, double lat, double alt) const {
  // Optimize in the case of spherical datum
  if (m_semi_major_axis == m_semi_minor_axis) {
    return m_semi_major_axis + alt;
  }
  double a = m_semi_major_axis;
  double b = m_semi_minor_axis;
  double a2 = a * a;
  double b2 = b * b;
  double e2 = (a2 - b2) / a2;
  double rlat = lat * (M_PI/180);
  double slat = sin( rlat );
  double clat = cos( rlat );
  double Rn = a / sqrt(1.0-e2*slat*slat) + alt;

  return sqrt(Rn*Rn*(clat*clat + (1-e2)*(1-e2)*slat*slat));
}

double vw::cartography::Datum::inverse_flattening() const {
  return 1.0 / (1.0 - m_semi_minor_axis / m_semi_major_axis);
}

vw::Matrix3x3 vw::cartography::Datum::ecef_to_ned_matrix( vw::Vector3 const& p) const {
  double lat = p.y();
  if ( lat < -90 ) lat = -90;
  if ( lat > 90 ) lat = 90;

  double rlon = (p.x() + m_meridian_offset) * (M_PI/180);
  double rlat = lat * (M_PI/180);
  double slat = sin( rlat );
  double clat = cos( rlat );
  double slon = sin( rlon );
  double clon = cos( rlon );

  Matrix3x3 R;

  R(0,0) = -slat*clon;
  R(0,1) = -slat*slon;
  R(0,2) = clat;
  R(1,0) = -slon;
  R(1,1) = clon;
  R(1,2) = 0.0;
  R(2,0) = -clon*clat;
  R(2,1) = -slon*clat;
  R(2,2) = -slat;

  return R;
}

vw::Vector3 vw::cartography::Datum::geodetic_to_cartesian( vw::Vector3 const& p ) const {
  double a = m_semi_major_axis;
  double b = m_semi_minor_axis;
  double a2 = a * a;
  double b2 = b * b;
  double e2 = (a2 - b2) / a2;

  double lat = p.y();
  if ( lat < -90 ) lat = -90;
  if ( lat > 90 ) lat = 90;

  double rlon = (p.x() + m_meridian_offset) * (M_PI/180);
  double rlat = lat * (M_PI/180);
  double slat = sin( rlat );
  double clat = cos( rlat );
  double slon = sin( rlon );
  double clon = cos( rlon );
  double radius = a / sqrt(1.0-e2*slat*slat);

  return Vector3( (radius+p.z()) * clat * clon,
                  (radius+p.z()) * clat * slon,
                  (radius*(1-e2)+p.z()) * slat );
}

// This function is based heavily on the similar
// Proj.4 function pj_Convert_Geocentric_To_Geodetic.
vw::Vector3 vw::cartography::Datum::cartesian_to_geodetic( vw::Vector3 const& p ) const {
  double a = m_semi_major_axis;
  double b = m_semi_minor_axis;
  double a2 = a * a;
  double b2 = b * b;
  double e2 = (a2 - b2) / a2;

  static const double epsilon = 1.0e-12;
  static const double epsilon2 = epsilon*epsilon;
  static const int maxiter = 30;

  double normxy = sqrt(p.x()*p.x()+p.y()*p.y()); // distance between semi-minor axis and location
  double normp = norm_2(p);                      // distance between center and location

  double lon=0.0, alt=0.0;

  // compute the longitude
  if ( normxy/a < epsilon ) {
    // special case for the origin
    if ( normp/a < epsilon ) {
      return Vector3(0,90,-b);
    }
  }
  else {
    lon = atan2(p.y(),p.x()) / (M_PI/180);
  }

  // The following iterative algorithm was developped by
  // "Institut fur Erdmessung", University of Hannover, July 1988.
  // Internet: www.ife.uni-hannover.de
  double cgcl = normxy/normp;     // cos of geocentric latitude
  double sgcl = p.z()/normp;      // sin of geocentric latitude
  double rx = 1.0/sqrt(1.0-e2*(2.0-e2)*cgcl*cgcl);
  double clat = cgcl*(1.0-e2)*rx; // cos of geodetic latitude estimate
  double slat = sgcl*rx;          // sin of geodetic latitude estimate

  // loop to find lat (in quadrature) until |lat[i]-lat[i-1]|<epsilon, roughly
  for( int i=0; i<maxiter; ++i ) {
    double ri = a/sqrt(1.0-e2*slat*slat); // radius at estimated location
    alt = normxy*clat+p.z()*slat-ri*(1.0-e2*slat*slat);
    double rk = e2*ri/(ri+alt);
    rx = 1.0/sqrt(1.0-rk*(2.0-rk)*cgcl*cgcl);
    double new_clat = cgcl*(1.0-rk)*rx;
    double new_slat = sgcl*rx;
    // sin(lat[i]-lat[i-1]) ~= lat[i]-lat[i-1]
    double sdlat = new_slat*clat-new_clat*slat;
    clat = new_clat;
    slat = new_slat;
    if( sdlat*sdlat < epsilon2 ) break;
  }

  return Vector3( lon - m_meridian_offset, atan(slat/fabs(clat))/(M_PI/180), alt );
}

std::ostream& vw::cartography::operator<<( std::ostream& os, vw::cartography::Datum const& datum ) {
  os << "Geodeditic Datum --> Name: " << datum.name() << "  Spheroid: " << datum.spheroid_name()
     << "  Semi-major: " << datum.semi_major_axis()
     << "  Semi-minor: " << datum.semi_minor_axis()
     << "  Meridian: " << datum.meridian_name()
     << "  at " << datum.meridian_offset();
  return os;
}

<commit_msg>Added D_MOON and D_MARS to known datums<commit_after>// __BEGIN_LICENSE__
// Copyright (C) 2006-2010 United States Government as represented by
// the Administrator of the National Aeronautics and Space Administration.
// All Rights Reserved.
// __END_LICENSE__

#include <vw/Cartography/Datum.h>
#include <vw/Math/Functions.h>

vw::cartography::Datum::Datum(std::string const& name,
                              std::string const& spheroid_name,
                              std::string const& meridian_name,
                              double semi_major_axis,
                              double semi_minor_axis,
                              double meridian_offset)
  : m_name(name),
    m_spheroid_name(spheroid_name),
    m_meridian_name(meridian_name),
    m_semi_major_axis(semi_major_axis),
    m_semi_minor_axis(semi_minor_axis),
    m_meridian_offset(meridian_offset),
    m_geocentric(false)
{
  std::ostringstream strm;
  strm << "+a=" << semi_major_axis << " +b=" << semi_minor_axis;
  m_proj_str = strm.str();
}

void vw::cartography::Datum::set_well_known_datum( std::string const& name ) {
  m_meridian_name = "Greenwich";
  m_geocentric = false;

  m_meridian_offset = 0;
  if (name == "WGS84") {
    m_name = "WGS_1984";
    m_spheroid_name="WGS 84";
    m_semi_major_axis = 6378137.0;
    m_semi_minor_axis = 6356752.3;
    m_proj_str = "+ellps=WGS84 +datum=WGS84";
    return;
  }

  if (name == "WGS72") {
    m_name="WGS_1972";
    m_spheroid_name="WGS 72";
    m_semi_major_axis = 6378135.0;
    m_semi_minor_axis = 6356750.5;
    m_proj_str = "+ellps=WGS72 +towgs84=0,0,4.5,0,0,0.554,0.2263";
    return;
  }

  if (name == "NAD83") {
    m_name="North_American_Datum_1983";
    m_spheroid_name="GRS 1980";
    m_semi_major_axis = 6378137;
    m_semi_minor_axis = 6356752.3;
    m_proj_str = "+ellps=GRS80 +datum=NAD83";
    return;
  }

  if (name == "NAD27") {
    m_name="North_American_Datum_1927";
    m_spheroid_name="Clarke 1866";
    m_semi_major_axis = 6378206.4;
    m_semi_minor_axis = 6356583.8;
    m_proj_str = "+ellps=clrk66 +datum=NAD27";
    return;
  }

  if (name == "D_MOON") {
    m_name = "D_MOON";
    m_spheroid_name = "MOON";
    m_meridian_name = "Reference Meridian";
    m_semi_major_axis = m_semi_minor_axis = 1737400;
    m_meridian_offset = 0.0;
    m_geocentric = false;
    m_proj_str = "+a=1737400 +b=1737400";
    return;
  }

  if (name == "D_MARS") {
    m_name = "D_MARS";
    m_spheroid_name = "MARS";
    m_meridian_name = "Reference Meridian";
    m_semi_major_axis = m_semi_minor_axis = 3396190;
    m_meridian_offset = 0.0;
    m_geocentric = false;
    m_proj_str = "+a=3396190 +b=3396190";
    return;
  }

  vw::vw_throw( vw::InputErr() << "Unknown datum string \"" << name << "\"!");
}

void vw::cartography::Datum::set_semi_major_axis(double val) {
  m_semi_major_axis = val;
  std::ostringstream strm;
  strm << "+a=" << m_semi_major_axis << " +b=" << m_semi_minor_axis;
  if (m_geocentric) strm << " +geoc";
  m_proj_str = strm.str();
}

void vw::cartography::Datum::set_semi_minor_axis(double val) {
  m_semi_minor_axis = val;
  std::ostringstream strm;
  strm << "+a=" << m_semi_major_axis << " +b=" << m_semi_minor_axis;
  if (m_geocentric) strm << " +geoc";
  m_proj_str = strm.str();
}

// return meridian radius of curvature.  NOT geocentric radius
double vw::cartography::Datum::radius(double /*lon*/, double lat) const {
  // Optimize in the case of spherical datum
  if (m_semi_major_axis == m_semi_minor_axis) {
    return m_semi_major_axis;
  }

  // Bi-axial Ellpisoid datum
  double a = m_semi_major_axis;
  double b = m_semi_minor_axis;
  double t = atan((a/b) * tan(lat * M_PI / 180.0));
  double x = a * cos(t);
  double y = b * sin(t);
  return sqrt(x*x + y*y);
}

double vw::cartography::Datum::geocentric_latitude(double lat) const {
   // Optimize in the case of spherical datum
  if (m_semi_major_axis == m_semi_minor_axis) {
    return m_semi_major_axis;
  }

  // Bi-axial Ellpisoid datum
  // http://mathworld.wolfram.com/GeocentricLatitude.html
  double a = m_semi_major_axis;
  double b = m_semi_minor_axis;
  double a2 = a * a;
  double b2 = b * b;
  double e2 = (a2 - b2) / a2;
  return atan((1-e2)*tan(lat * M_PI / 180.0));

}

double vw::cartography::Datum::radius_of_curvature(double /*lon*/, double lat) const {
  // Optimize in the case of spherical datum
  if (m_semi_major_axis == m_semi_minor_axis) {
    return m_semi_major_axis;
  }

  // Bi-axial Ellpisoid datum
  double a = m_semi_major_axis;
  double b = m_semi_minor_axis;
  double a2 = a * a;
  double b2 = b * b;
  double e2 = (a2 - b2) / a2;
  double slat = sin(M_PI/180*lat);
  return a / sqrt(1.0 - e2*slat*slat);
}

// return meridian radius of curvature.  NOT geocentric radius
double vw::cartography::Datum::geocentric_radius(double /*lon*/, double lat, double alt) const {
  // Optimize in the case of spherical datum
  if (m_semi_major_axis == m_semi_minor_axis) {
    return m_semi_major_axis + alt;
  }
  double a = m_semi_major_axis;
  double b = m_semi_minor_axis;
  double a2 = a * a;
  double b2 = b * b;
  double e2 = (a2 - b2) / a2;
  double rlat = lat * (M_PI/180);
  double slat = sin( rlat );
  double clat = cos( rlat );
  double Rn = a / sqrt(1.0-e2*slat*slat) + alt;

  return sqrt(Rn*Rn*(clat*clat + (1-e2)*(1-e2)*slat*slat));
}

double vw::cartography::Datum::inverse_flattening() const {
  return 1.0 / (1.0 - m_semi_minor_axis / m_semi_major_axis);
}

vw::Matrix3x3 vw::cartography::Datum::ecef_to_ned_matrix( vw::Vector3 const& p) const {
  double lat = p.y();
  if ( lat < -90 ) lat = -90;
  if ( lat > 90 ) lat = 90;

  double rlon = (p.x() + m_meridian_offset) * (M_PI/180);
  double rlat = lat * (M_PI/180);
  double slat = sin( rlat );
  double clat = cos( rlat );
  double slon = sin( rlon );
  double clon = cos( rlon );

  Matrix3x3 R;

  R(0,0) = -slat*clon;
  R(0,1) = -slat*slon;
  R(0,2) = clat;
  R(1,0) = -slon;
  R(1,1) = clon;
  R(1,2) = 0.0;
  R(2,0) = -clon*clat;
  R(2,1) = -slon*clat;
  R(2,2) = -slat;

  return R;
}

vw::Vector3 vw::cartography::Datum::geodetic_to_cartesian( vw::Vector3 const& p ) const {
  double a = m_semi_major_axis;
  double b = m_semi_minor_axis;
  double a2 = a * a;
  double b2 = b * b;
  double e2 = (a2 - b2) / a2;

  double lat = p.y();
  if ( lat < -90 ) lat = -90;
  if ( lat > 90 ) lat = 90;

  double rlon = (p.x() + m_meridian_offset) * (M_PI/180);
  double rlat = lat * (M_PI/180);
  double slat = sin( rlat );
  double clat = cos( rlat );
  double slon = sin( rlon );
  double clon = cos( rlon );
  double radius = a / sqrt(1.0-e2*slat*slat);

  return Vector3( (radius+p.z()) * clat * clon,
                  (radius+p.z()) * clat * slon,
                  (radius*(1-e2)+p.z()) * slat );
}

// This function is based heavily on the similar
// Proj.4 function pj_Convert_Geocentric_To_Geodetic.
vw::Vector3 vw::cartography::Datum::cartesian_to_geodetic( vw::Vector3 const& p ) const {
  double a = m_semi_major_axis;
  double b = m_semi_minor_axis;
  double a2 = a * a;
  double b2 = b * b;
  double e2 = (a2 - b2) / a2;

  static const double epsilon = 1.0e-12;
  static const double epsilon2 = epsilon*epsilon;
  static const int maxiter = 30;

  double normxy = sqrt(p.x()*p.x()+p.y()*p.y()); // distance between semi-minor axis and location
  double normp = norm_2(p);                      // distance between center and location

  double lon=0.0, alt=0.0;

  // compute the longitude
  if ( normxy/a < epsilon ) {
    // special case for the origin
    if ( normp/a < epsilon ) {
      return Vector3(0,90,-b);
    }
  }
  else {
    lon = atan2(p.y(),p.x()) / (M_PI/180);
  }

  // The following iterative algorithm was developped by
  // "Institut fur Erdmessung", University of Hannover, July 1988.
  // Internet: www.ife.uni-hannover.de
  double cgcl = normxy/normp;     // cos of geocentric latitude
  double sgcl = p.z()/normp;      // sin of geocentric latitude
  double rx = 1.0/sqrt(1.0-e2*(2.0-e2)*cgcl*cgcl);
  double clat = cgcl*(1.0-e2)*rx; // cos of geodetic latitude estimate
  double slat = sgcl*rx;          // sin of geodetic latitude estimate

  // loop to find lat (in quadrature) until |lat[i]-lat[i-1]|<epsilon, roughly
  for( int i=0; i<maxiter; ++i ) {
    double ri = a/sqrt(1.0-e2*slat*slat); // radius at estimated location
    alt = normxy*clat+p.z()*slat-ri*(1.0-e2*slat*slat);
    double rk = e2*ri/(ri+alt);
    rx = 1.0/sqrt(1.0-rk*(2.0-rk)*cgcl*cgcl);
    double new_clat = cgcl*(1.0-rk)*rx;
    double new_slat = sgcl*rx;
    // sin(lat[i]-lat[i-1]) ~= lat[i]-lat[i-1]
    double sdlat = new_slat*clat-new_clat*slat;
    clat = new_clat;
    slat = new_slat;
    if( sdlat*sdlat < epsilon2 ) break;
  }

  return Vector3( lon - m_meridian_offset, atan(slat/fabs(clat))/(M_PI/180), alt );
}

std::ostream& vw::cartography::operator<<( std::ostream& os, vw::cartography::Datum const& datum ) {
  os << "Geodeditic Datum --> Name: " << datum.name() << "  Spheroid: " << datum.spheroid_name()
     << "  Semi-major: " << datum.semi_major_axis()
     << "  Semi-minor: " << datum.semi_minor_axis()
     << "  Meridian: " << datum.meridian_name()
     << "  at " << datum.meridian_offset();
  return os;
}

<|endoftext|>