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

namespace skiagm {

static void make_bitmaps(int w, int h, SkBitmap* src, SkBitmap* dst) {
    src->setConfig(SkBitmap::kARGB_8888_Config, w, h);
    src->allocPixels();
    src->eraseColor(0);

    SkCanvas c(*src);
    SkPaint p;
    SkRect r;
    SkScalar ww = SkIntToScalar(w);
    SkScalar hh = SkIntToScalar(h);

    p.setAntiAlias(true);
    p.setColor(0xFFFFCC44);
    r.set(0, 0, ww*3/4, hh*3/4);
    c.drawOval(r, p);

    dst->setConfig(SkBitmap::kARGB_8888_Config, w, h);
    dst->allocPixels();
    dst->eraseColor(0);
    c.setBitmapDevice(*dst);

    p.setColor(0xFF66AAFF);
    r.set(ww/3, hh/3, ww*19/20, hh*19/20);
    c.drawRect(r, p);
}

static const uint16_t gBG[] = { 0xFFFF, 0xCCCF, 0xCCCF, 0xFFFF };

class XfermodesGM : public GM {
    SkBitmap    fBG;
    SkBitmap    fSrcB, fDstB;
    bool        fOnce;

    void draw_mode(SkCanvas* canvas, SkXfermode* mode, int alpha,
                   SkScalar x, SkScalar y) {
        SkPaint p;

        canvas->drawBitmap(fSrcB, x, y, &p);
        p.setAlpha(alpha);
        p.setXfermode(mode);
        canvas->drawBitmap(fDstB, x, y, &p);
    }

    void init() {
        if (!fOnce) {
            // Do all this work in a temporary so we get a deep copy,
            // especially of gBG.
            SkBitmap scratchBitmap;
            scratchBitmap.setConfig(SkBitmap::kARGB_4444_Config, 2, 2, 4);
            scratchBitmap.setPixels(gBG);
            scratchBitmap.setIsOpaque(true);
            scratchBitmap.copyTo(&fBG, SkBitmap::kARGB_4444_Config);

            make_bitmaps(W, H, &fSrcB, &fDstB);
            fOnce = true;
        }
    }

public:
    const static int W = 64;
    const static int H = 64;
    XfermodesGM() : fOnce(false) {}

protected:
    virtual SkString onShortName() {
        return SkString("xfermodes");
    }

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

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

        canvas->translate(SkIntToScalar(10), SkIntToScalar(20));

        const struct {
            SkXfermode::Mode  fMode;
            const char*         fLabel;
        } gModes[] = {
            { SkXfermode::kClear_Mode,    "Clear"     },
            { SkXfermode::kSrc_Mode,      "Src"       },
            { SkXfermode::kDst_Mode,      "Dst"       },
            { SkXfermode::kSrcOver_Mode,  "SrcOver"   },
            { SkXfermode::kDstOver_Mode,  "DstOver"   },
            { SkXfermode::kSrcIn_Mode,    "SrcIn"     },
            { SkXfermode::kDstIn_Mode,    "DstIn"     },
            { SkXfermode::kSrcOut_Mode,   "SrcOut"    },
            { SkXfermode::kDstOut_Mode,   "DstOut"    },
            { SkXfermode::kSrcATop_Mode,  "SrcATop"   },
            { SkXfermode::kDstATop_Mode,  "DstATop"   },
            { SkXfermode::kXor_Mode,      "Xor"       },

            { SkXfermode::kPlus_Mode,         "Plus"          },
            { SkXfermode::kMultiply_Mode,     "Multiply"      },
            { SkXfermode::kScreen_Mode,       "Screen"        },
            { SkXfermode::kOverlay_Mode,      "Overlay"       },
            { SkXfermode::kDarken_Mode,       "Darken"        },
            { SkXfermode::kLighten_Mode,      "Lighten"       },
            { SkXfermode::kColorDodge_Mode,   "ColorDodge"    },
            { SkXfermode::kColorBurn_Mode,    "ColorBurn"     },
            { SkXfermode::kHardLight_Mode,    "HardLight"     },
            { SkXfermode::kSoftLight_Mode,    "SoftLight"     },
            { SkXfermode::kDifference_Mode,   "Difference"    },
            { SkXfermode::kExclusion_Mode,    "Exclusion"     },
        };

        const SkScalar w = SkIntToScalar(W);
        const SkScalar h = SkIntToScalar(H);
        SkShader* s = SkShader::CreateBitmapShader(fBG,
                                                   SkShader::kRepeat_TileMode,
                                                   SkShader::kRepeat_TileMode);
        SkMatrix m;
        m.setScale(SkIntToScalar(6), SkIntToScalar(6));
        s->setLocalMatrix(m);

        SkPaint labelP;
        labelP.setAntiAlias(true);
        labelP.setTextAlign(SkPaint::kCenter_Align);

        const int W = 5;

        SkScalar x0 = 0;
        for (int twice = 0; twice < 2; twice++) {
            SkScalar x = x0, y = 0;
            for (size_t i = 0; i < SK_ARRAY_COUNT(gModes); i++) {
                SkXfermode* mode = SkXfermode::Create(gModes[i].fMode);
                SkAutoUnref aur(mode);
                SkRect r;
                r.set(x, y, x+w, y+h);

                SkPaint p;
                p.setStyle(SkPaint::kFill_Style);
                p.setShader(s);
                canvas->drawRect(r, p);

                canvas->saveLayer(&r, NULL, SkCanvas::kARGB_ClipLayer_SaveFlag);
                draw_mode(canvas, mode, twice ? 0x88 : 0xFF, r.fLeft, r.fTop);
                canvas->restore();

                r.inset(-SK_ScalarHalf, -SK_ScalarHalf);
                p.setStyle(SkPaint::kStroke_Style);
                p.setShader(NULL);
                canvas->drawRect(r, p);

#if 1
                canvas->drawText(gModes[i].fLabel, strlen(gModes[i].fLabel),
                                 x + w/2, y - labelP.getTextSize()/2, labelP);
#endif
                x += w + SkIntToScalar(10);
                if ((i % W) == W - 1) {
                    x = x0;
                    y += h + SkIntToScalar(30);
                }
            }
            x0 += SkIntToScalar(400);
        }
        s->unref();
    }

private:
    typedef GM INHERITED;
};

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

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

}
<commit_msg>can't pass const to setPixels :(<commit_after>
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "gm.h"
#include "SkBitmap.h"
#include "SkShader.h"
#include "SkXfermode.h"

namespace skiagm {

static void make_bitmaps(int w, int h, SkBitmap* src, SkBitmap* dst) {
    src->setConfig(SkBitmap::kARGB_8888_Config, w, h);
    src->allocPixels();
    src->eraseColor(0);

    SkCanvas c(*src);
    SkPaint p;
    SkRect r;
    SkScalar ww = SkIntToScalar(w);
    SkScalar hh = SkIntToScalar(h);

    p.setAntiAlias(true);
    p.setColor(0xFFFFCC44);
    r.set(0, 0, ww*3/4, hh*3/4);
    c.drawOval(r, p);

    dst->setConfig(SkBitmap::kARGB_8888_Config, w, h);
    dst->allocPixels();
    dst->eraseColor(0);
    c.setBitmapDevice(*dst);

    p.setColor(0xFF66AAFF);
    r.set(ww/3, hh/3, ww*19/20, hh*19/20);
    c.drawRect(r, p);
}

class XfermodesGM : public GM {
    SkBitmap    fBG;
    SkBitmap    fSrcB, fDstB;
    bool        fOnce;

    void draw_mode(SkCanvas* canvas, SkXfermode* mode, int alpha,
                   SkScalar x, SkScalar y) {
        SkPaint p;

        canvas->drawBitmap(fSrcB, x, y, &p);
        p.setAlpha(alpha);
        p.setXfermode(mode);
        canvas->drawBitmap(fDstB, x, y, &p);
    }

    void init() {
        if (!fOnce) {
            // Do all this work in a temporary so we get a deep copy
            uint16_t localData[] = { 0xFFFF, 0xCCCF, 0xCCCF, 0xFFFF };
            SkBitmap scratchBitmap;
            scratchBitmap.setConfig(SkBitmap::kARGB_4444_Config, 2, 2, 4);
            scratchBitmap.setPixels(localData);
            scratchBitmap.setIsOpaque(true);
            scratchBitmap.copyTo(&fBG, SkBitmap::kARGB_4444_Config);

            make_bitmaps(W, H, &fSrcB, &fDstB);
            fOnce = true;
        }
    }

public:
    const static int W = 64;
    const static int H = 64;
    XfermodesGM() : fOnce(false) {}

protected:
    virtual SkString onShortName() {
        return SkString("xfermodes");
    }

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

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

        canvas->translate(SkIntToScalar(10), SkIntToScalar(20));

        const struct {
            SkXfermode::Mode  fMode;
            const char*         fLabel;
        } gModes[] = {
            { SkXfermode::kClear_Mode,    "Clear"     },
            { SkXfermode::kSrc_Mode,      "Src"       },
            { SkXfermode::kDst_Mode,      "Dst"       },
            { SkXfermode::kSrcOver_Mode,  "SrcOver"   },
            { SkXfermode::kDstOver_Mode,  "DstOver"   },
            { SkXfermode::kSrcIn_Mode,    "SrcIn"     },
            { SkXfermode::kDstIn_Mode,    "DstIn"     },
            { SkXfermode::kSrcOut_Mode,   "SrcOut"    },
            { SkXfermode::kDstOut_Mode,   "DstOut"    },
            { SkXfermode::kSrcATop_Mode,  "SrcATop"   },
            { SkXfermode::kDstATop_Mode,  "DstATop"   },
            { SkXfermode::kXor_Mode,      "Xor"       },

            { SkXfermode::kPlus_Mode,         "Plus"          },
            { SkXfermode::kMultiply_Mode,     "Multiply"      },
            { SkXfermode::kScreen_Mode,       "Screen"        },
            { SkXfermode::kOverlay_Mode,      "Overlay"       },
            { SkXfermode::kDarken_Mode,       "Darken"        },
            { SkXfermode::kLighten_Mode,      "Lighten"       },
            { SkXfermode::kColorDodge_Mode,   "ColorDodge"    },
            { SkXfermode::kColorBurn_Mode,    "ColorBurn"     },
            { SkXfermode::kHardLight_Mode,    "HardLight"     },
            { SkXfermode::kSoftLight_Mode,    "SoftLight"     },
            { SkXfermode::kDifference_Mode,   "Difference"    },
            { SkXfermode::kExclusion_Mode,    "Exclusion"     },
        };

        const SkScalar w = SkIntToScalar(W);
        const SkScalar h = SkIntToScalar(H);
        SkShader* s = SkShader::CreateBitmapShader(fBG,
                                                   SkShader::kRepeat_TileMode,
                                                   SkShader::kRepeat_TileMode);
        SkMatrix m;
        m.setScale(SkIntToScalar(6), SkIntToScalar(6));
        s->setLocalMatrix(m);

        SkPaint labelP;
        labelP.setAntiAlias(true);
        labelP.setTextAlign(SkPaint::kCenter_Align);

        const int W = 5;

        SkScalar x0 = 0;
        for (int twice = 0; twice < 2; twice++) {
            SkScalar x = x0, y = 0;
            for (size_t i = 0; i < SK_ARRAY_COUNT(gModes); i++) {
                SkXfermode* mode = SkXfermode::Create(gModes[i].fMode);
                SkAutoUnref aur(mode);
                SkRect r;
                r.set(x, y, x+w, y+h);

                SkPaint p;
                p.setStyle(SkPaint::kFill_Style);
                p.setShader(s);
                canvas->drawRect(r, p);

                canvas->saveLayer(&r, NULL, SkCanvas::kARGB_ClipLayer_SaveFlag);
                draw_mode(canvas, mode, twice ? 0x88 : 0xFF, r.fLeft, r.fTop);
                canvas->restore();

                r.inset(-SK_ScalarHalf, -SK_ScalarHalf);
                p.setStyle(SkPaint::kStroke_Style);
                p.setShader(NULL);
                canvas->drawRect(r, p);

#if 1
                canvas->drawText(gModes[i].fLabel, strlen(gModes[i].fLabel),
                                 x + w/2, y - labelP.getTextSize()/2, labelP);
#endif
                x += w + SkIntToScalar(10);
                if ((i % W) == W - 1) {
                    x = x0;
                    y += h + SkIntToScalar(30);
                }
            }
            x0 += SkIntToScalar(400);
        }
        s->unref();
    }

private:
    typedef GM INHERITED;
};

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

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

}
<|endoftext|>


<commit_before>/***********************************************************************************
**
** Target.cpp
**
** Copyright (C) August 2016 Hotride
**
************************************************************************************
*/
//----------------------------------------------------------------------------------
#include "Target.h"
#include "Game objects/GameWorld.h"
#include "Network/Packets.h"
#include "OrionUO.h"
#include "Managers/MapManager.h"
#include "Managers/PacketManager.h"
//----------------------------------------------------------------------------------
CTarget g_Target;
//----------------------------------------------------------------------------------
CTarget::CTarget()
: m_Type(0), m_Targeting(false), m_MultiGraphic(0), m_Multi(NULL), m_CursorID(0)
{
	//
	memset(m_Data, 0, sizeof(m_Data));
	memset(m_LastData, 0, sizeof(m_LastData));
}
//----------------------------------------------------------------------------------
void CTarget::Reset()
{
	//
	memset(m_Data, 0, sizeof(m_Data));
	memset(m_LastData, 0, sizeof(m_LastData));

	if (m_Multi != NULL)
	{
		delete m_Multi;
		m_Multi = NULL;
	}

	m_Type = 0;
	m_CursorType = 0;
	m_CursorID = 0;
	m_Targeting = false;
	m_MultiGraphic = 0;
}
//----------------------------------------------------------------------------------
void CTarget::SetData(WISP_DATASTREAM::CDataReader &reader)
{
	//
	memcpy(&m_Data[0], reader.Start, reader.Size);

	//
	m_Type = reader.ReadUInt8();
	m_CursorID = reader.ReadUInt32BE();
	m_CursorType = reader.ReadUInt8();
	m_Targeting = true;
	m_MultiGraphic = false;
}
//----------------------------------------------------------------------------------
void CTarget::SetMultiData(WISP_DATASTREAM::CDataReader &reader)
{
	//
	m_Type = 1;
	m_CursorType = 0;
	m_Targeting = true;
	m_CursorID = reader.ReadUInt32BE(1);

	//
	memset(&m_Data[0], 0, 19);
	m_Data[0] = 0x6C;
	m_Data[1] = 1; //
	memcpy(m_Data + 2, reader.Start + 2, 4); // ID  (ID )

	reader.ResetPtr();
	m_MultiGraphic = reader.ReadUInt16BE(18);
}
//----------------------------------------------------------------------------------
void CTarget::SendTargetObject(const uint &serial)
{
	if (!m_Targeting)
		return; //     -

	//  ,    ,  -
	pack32(m_Data + 7, serial);
	m_Data[1] = 0;

	CGameObject *obj = (g_World != NULL ? g_World->FindWorldObject(serial) : NULL);

	if (obj != NULL)
	{
		pack16(m_Data + 11, obj->X);
		pack16(m_Data + 13, obj->Y);
		m_Data[15] = 0xFF;
		m_Data[16] = obj->Z;
		pack16(m_Data + 17, obj->Graphic);
	}
	else
	{
		pack32(m_Data + 11, 0);
		pack32(m_Data + 15, 0);
	}

	if (serial != g_PlayerSerial)
	{
		g_LastTargetObject = serial;

		//  LastTarget
		memcpy(m_LastData, m_Data, sizeof(m_Data));

		if (serial < 0x40000000)
			CPacketStatusRequest(serial).Send();
	}

	SendTarget();
}
//----------------------------------------------------------------------------------
void CTarget::SendTargetTile(const ushort &tileID, const short &x, const short &y, char z)
{
	if (!m_Targeting)
		return; //     -

	m_Data[1] = 1;

	//    ,   ,
	pack32(m_Data + 7, 0);
	pack16(m_Data + 11, x);
	pack16(m_Data + 13, y);
	m_Data[15] = 0xFF;

	if (m_MultiGraphic != 0)
	{
		int grZ = 0;
		int stZ = 0;
		g_MapManager->GetMapZ(x, y, grZ, stZ);
		z = grZ;
	}

	m_Data[16] = z;
	pack16(m_Data + 17, tileID);

	//  LastTarget
	memcpy(m_LastData, m_Data, sizeof(m_Data));

	SendTarget();
}
//----------------------------------------------------------------------------------
void CTarget::SendCancelTarget()
{
	if (!m_Targeting)
		return; //     -

	//
	pack32(m_Data + 7, 0);
	pack32(m_Data + 11, 0xFFFFFFFF);
	pack32(m_Data + 15, 0);

	SendTarget();
}
//----------------------------------------------------------------------------------
void CTarget::SendLastTarget()
{
	if (!m_Targeting)
		return; //     -

	//
	memcpy(m_Data, m_LastData, sizeof(m_Data));
	m_Data[0] = 0x6C;
	m_Data[1] = m_Type;
	m_Data[6] = m_CursorType;
	pack32(m_Data + 2, m_CursorID);

	SendTarget();
}
//----------------------------------------------------------------------------------
void CTarget::SendTarget()
{
	g_Orion.Send(m_Data, sizeof(m_Data));

	//
	memset(m_Data, 0, sizeof(m_Data));
	m_Targeting = false;
	m_MultiGraphic = 0;
}
//----------------------------------------------------------------------------------
void CTarget::UnloadMulti()
{
	if (m_Multi != NULL)
	{
		delete m_Multi;
		m_Multi = NULL;
	}
}
//----------------------------------------------------------------------------------
void CTarget::LoadMulti(const int &x, const int &y, const char &z)
{
	UnloadMulti();

	CIndexMulti &index = g_Orion.m_MultiDataIndex[m_MultiGraphic];

	if (index.Address != NULL)
	{
		int count = (int)index.Count;

		int itemOffset = sizeof(MULTI_BLOCK);

		if (g_PacketManager.ClientVersion >= CV_7090)
			itemOffset = sizeof(MULTI_BLOCK_NEW);

		IFOR(j, 0, count)
		{
			PMULTI_BLOCK pmb = (PMULTI_BLOCK)(index.Address + (j * itemOffset));

			CMultiObject *mo = new CMultiObject(pmb->ID, x + pmb->X, y + pmb->Y, z + (char)pmb->Z, 2);
			g_MapManager->AddRender(mo);
			AddMultiObject(mo);
		}
	}
}
//----------------------------------------------------------------------------------
void CTarget::AddMultiObject(CMultiObject *obj)
{
	if (m_Multi == NULL)
	{
		m_Multi = new CMulti(obj->X, obj->Y);
		m_Multi->m_Next = NULL;
		m_Multi->m_Prev = NULL;
		m_Multi->m_Items = obj;
		obj->m_Next = NULL;
		obj->m_Prev = NULL;
	}
	else
	{
		CMulti *multi = GetMultiAtXY(obj->X, obj->Y);

		if (multi != NULL)
		{
			QFOR(multiobj, multi->m_Items, CMultiObject*)
			{
				if (obj->Z < multiobj->Z)
				{
					if (multiobj->m_Prev == NULL)
						multi->Insert(multiobj->m_Prev, obj);
					else
						multi->Insert(multiobj, obj);

					return;
				}

				if (multiobj->m_Next == NULL)
				{
					multiobj->m_Next = obj;
					obj->m_Prev = multiobj;
					obj->m_Next = NULL;

					return;
				}
			}

			//   - -
		}
		else
		{
			CMulti *newmulti = new CMulti(obj->X, obj->Y);
			newmulti->m_Next = NULL;
			newmulti->m_Items = obj;
			obj->m_Next = NULL;
			obj->m_Prev = NULL;

			multi = m_Multi;

			while (multi != NULL)
			{
				if (multi->m_Next == NULL)
				{
					multi->m_Next = newmulti;
					newmulti->m_Prev = multi;
					break;
				}

				multi = (CMulti*)multi->m_Next;
			}
		}
	}
}
//----------------------------------------------------------------------------------
CMulti *CTarget::GetMultiAtXY(const short &x, const short &y)
{
	CMulti *multi = m_Multi;

	while (multi != NULL)
	{
		if (multi->X == x && multi->Y == y)
			break;

		multi = (CMulti*)multi->m_Next;
	}

	return multi;
}
//----------------------------------------------------------------------------------
<commit_msg>Поправил сброс таргета от сервера.<commit_after>/***********************************************************************************
**
** Target.cpp
**
** Copyright (C) August 2016 Hotride
**
************************************************************************************
*/
//----------------------------------------------------------------------------------
#include "Target.h"
#include "Game objects/GameWorld.h"
#include "Network/Packets.h"
#include "OrionUO.h"
#include "Managers/MapManager.h"
#include "Managers/PacketManager.h"
//----------------------------------------------------------------------------------
CTarget g_Target;
//----------------------------------------------------------------------------------
CTarget::CTarget()
: m_Type(0), m_Targeting(false), m_MultiGraphic(0), m_Multi(NULL), m_CursorID(0)
{
	//
	memset(m_Data, 0, sizeof(m_Data));
	memset(m_LastData, 0, sizeof(m_LastData));
}
//----------------------------------------------------------------------------------
void CTarget::Reset()
{
	//
	memset(m_Data, 0, sizeof(m_Data));
	memset(m_LastData, 0, sizeof(m_LastData));

	if (m_Multi != NULL)
	{
		delete m_Multi;
		m_Multi = NULL;
	}

	m_Type = 0;
	m_CursorType = 0;
	m_CursorID = 0;
	m_Targeting = false;
	m_MultiGraphic = 0;
}
//----------------------------------------------------------------------------------
void CTarget::SetData(WISP_DATASTREAM::CDataReader &reader)
{
	//
	memcpy(&m_Data[0], reader.Start, reader.Size);

	//
	m_Type = reader.ReadUInt8();
	m_CursorID = reader.ReadUInt32BE();
	m_CursorType = reader.ReadUInt8();
	m_Targeting = (m_CursorType < 3);
	m_MultiGraphic = false;
}
//----------------------------------------------------------------------------------
void CTarget::SetMultiData(WISP_DATASTREAM::CDataReader &reader)
{
	//
	m_Type = 1;
	m_CursorType = 0;
	m_Targeting = true;
	m_CursorID = reader.ReadUInt32BE(1);

	//
	memset(&m_Data[0], 0, 19);
	m_Data[0] = 0x6C;
	m_Data[1] = 1; //
	memcpy(m_Data + 2, reader.Start + 2, 4); // ID  (ID )

	reader.ResetPtr();
	m_MultiGraphic = reader.ReadUInt16BE(18);
}
//----------------------------------------------------------------------------------
void CTarget::SendTargetObject(const uint &serial)
{
	if (!m_Targeting)
		return; //     -

	//  ,    ,  -
	pack32(m_Data + 7, serial);
	m_Data[1] = 0;

	CGameObject *obj = (g_World != NULL ? g_World->FindWorldObject(serial) : NULL);

	if (obj != NULL)
	{
		pack16(m_Data + 11, obj->X);
		pack16(m_Data + 13, obj->Y);
		m_Data[15] = 0xFF;
		m_Data[16] = obj->Z;
		pack16(m_Data + 17, obj->Graphic);
	}
	else
	{
		pack32(m_Data + 11, 0);
		pack32(m_Data + 15, 0);
	}

	if (serial != g_PlayerSerial)
	{
		g_LastTargetObject = serial;

		//  LastTarget
		memcpy(m_LastData, m_Data, sizeof(m_Data));

		if (serial < 0x40000000)
			CPacketStatusRequest(serial).Send();
	}

	SendTarget();
}
//----------------------------------------------------------------------------------
void CTarget::SendTargetTile(const ushort &tileID, const short &x, const short &y, char z)
{
	if (!m_Targeting)
		return; //     -

	m_Data[1] = 1;

	//    ,   ,
	pack32(m_Data + 7, 0);
	pack16(m_Data + 11, x);
	pack16(m_Data + 13, y);
	m_Data[15] = 0xFF;

	if (m_MultiGraphic != 0)
	{
		int grZ = 0;
		int stZ = 0;
		g_MapManager->GetMapZ(x, y, grZ, stZ);
		z = grZ;
	}

	m_Data[16] = z;
	pack16(m_Data + 17, tileID);

	//  LastTarget
	memcpy(m_LastData, m_Data, sizeof(m_Data));

	SendTarget();
}
//----------------------------------------------------------------------------------
void CTarget::SendCancelTarget()
{
	if (!m_Targeting)
		return; //     -

	//
	pack32(m_Data + 7, 0);
	pack32(m_Data + 11, 0xFFFFFFFF);
	pack32(m_Data + 15, 0);

	SendTarget();
}
//----------------------------------------------------------------------------------
void CTarget::SendLastTarget()
{
	if (!m_Targeting)
		return; //     -

	//
	memcpy(m_Data, m_LastData, sizeof(m_Data));
	m_Data[0] = 0x6C;
	m_Data[1] = m_Type;
	m_Data[6] = m_CursorType;
	pack32(m_Data + 2, m_CursorID);

	SendTarget();
}
//----------------------------------------------------------------------------------
void CTarget::SendTarget()
{
	g_Orion.Send(m_Data, sizeof(m_Data));

	//
	memset(m_Data, 0, sizeof(m_Data));
	m_Targeting = false;
	m_MultiGraphic = 0;
}
//----------------------------------------------------------------------------------
void CTarget::UnloadMulti()
{
	if (m_Multi != NULL)
	{
		delete m_Multi;
		m_Multi = NULL;
	}
}
//----------------------------------------------------------------------------------
void CTarget::LoadMulti(const int &x, const int &y, const char &z)
{
	UnloadMulti();

	CIndexMulti &index = g_Orion.m_MultiDataIndex[m_MultiGraphic];

	if (index.Address != NULL)
	{
		int count = (int)index.Count;

		int itemOffset = sizeof(MULTI_BLOCK);

		if (g_PacketManager.ClientVersion >= CV_7090)
			itemOffset = sizeof(MULTI_BLOCK_NEW);

		IFOR(j, 0, count)
		{
			PMULTI_BLOCK pmb = (PMULTI_BLOCK)(index.Address + (j * itemOffset));

			CMultiObject *mo = new CMultiObject(pmb->ID, x + pmb->X, y + pmb->Y, z + (char)pmb->Z, 2);
			g_MapManager->AddRender(mo);
			AddMultiObject(mo);
		}
	}
}
//----------------------------------------------------------------------------------
void CTarget::AddMultiObject(CMultiObject *obj)
{
	if (m_Multi == NULL)
	{
		m_Multi = new CMulti(obj->X, obj->Y);
		m_Multi->m_Next = NULL;
		m_Multi->m_Prev = NULL;
		m_Multi->m_Items = obj;
		obj->m_Next = NULL;
		obj->m_Prev = NULL;
	}
	else
	{
		CMulti *multi = GetMultiAtXY(obj->X, obj->Y);

		if (multi != NULL)
		{
			QFOR(multiobj, multi->m_Items, CMultiObject*)
			{
				if (obj->Z < multiobj->Z)
				{
					if (multiobj->m_Prev == NULL)
						multi->Insert(multiobj->m_Prev, obj);
					else
						multi->Insert(multiobj, obj);

					return;
				}

				if (multiobj->m_Next == NULL)
				{
					multiobj->m_Next = obj;
					obj->m_Prev = multiobj;
					obj->m_Next = NULL;

					return;
				}
			}

			//   - -
		}
		else
		{
			CMulti *newmulti = new CMulti(obj->X, obj->Y);
			newmulti->m_Next = NULL;
			newmulti->m_Items = obj;
			obj->m_Next = NULL;
			obj->m_Prev = NULL;

			multi = m_Multi;

			while (multi != NULL)
			{
				if (multi->m_Next == NULL)
				{
					multi->m_Next = newmulti;
					newmulti->m_Prev = multi;
					break;
				}

				multi = (CMulti*)multi->m_Next;
			}
		}
	}
}
//----------------------------------------------------------------------------------
CMulti *CTarget::GetMultiAtXY(const short &x, const short &y)
{
	CMulti *multi = m_Multi;

	while (multi != NULL)
	{
		if (multi->X == x && multi->Y == y)
			break;

		multi = (CMulti*)multi->m_Next;
	}

	return multi;
}
//----------------------------------------------------------------------------------
<|endoftext|>


<commit_before>#include "retracer.h"

#include "apitracecall.h"
#include "thumbnail.h"

#include "image.hpp"

#include <QDebug>
#include <QVariant>
#include <QList>
#include <QImage>

#include <qjson/parser.h>

/**
 * Wrapper around a QProcess which enforces IO to block .
 *
 * Several QIODevice users (notably QJSON) expect blocking semantics, e.g.,
 * they expect that QIODevice::read() will blocked until the requested ammount
 * of bytes is read or end of file is reached. But by default QProcess, does
 * not block.  And passing QIODevice::Unbuffered mitigates but does not fully
 * address the problem either.
 *
 * This class wraps around QProcess, providing QIODevice interface, while
 * ensuring that all reads block.
 *
 * This class also works around a bug in QProcess::atEnd() implementation.
 *
 * See also:
 * - http://qt-project.org/wiki/Simple_Crypt_IO_Device
 * - http://qt-project.org/wiki/Custom_IO_Device
 */
class BlockingIODevice : public QIODevice
{
    /* We don't use the Q_OBJECT in this class given we don't declare any
     * signals and slots or use any other services provided by Qt's meta-object
     * system. */
public:
    BlockingIODevice(QProcess * io);
    bool isSequential() const;
    bool atEnd() const;
    bool waitForReadyRead(int msecs = -1);

protected:
    qint64 readData(char * data, qint64 maxSize);
    qint64 writeData(const char * data, qint64 maxSize);

private:
    QProcess *m_device;
};

BlockingIODevice::BlockingIODevice(QProcess * io) :
    m_device(io)
{
    /*
     * We pass QIODevice::Unbuffered to prevent the base QIODevice class to do
     * its own buffering on top of the overridden readData() method.
     *
     * The only buffering used will be to satisfy QIODevice::peek() and
     * QIODevice::ungetChar().
     */
    setOpenMode(ReadOnly | Unbuffered);
}

bool BlockingIODevice::isSequential() const
{
    return true;
}

bool BlockingIODevice::atEnd() const
{
    /*
     * XXX: QProcess::atEnd() documentation is wrong -- it will return true
     * even when the process is running --, so we try to workaround that here.
     */
    if (m_device->atEnd()) {
        if (m_device->state() == QProcess::Running) {
            if (!m_device->waitForReadyRead(-1)) {
                return true;
            }
        }
    }
    return false;
}

bool BlockingIODevice::waitForReadyRead(int msecs)
{
    Q_UNUSED(msecs);
    return true;
}

qint64 BlockingIODevice::readData(char * data, qint64 maxSize)
{
    qint64 bytesToRead = maxSize;
    qint64 readSoFar = 0;
    do {
        qint64 chunkSize = m_device->read(data + readSoFar, bytesToRead);
        if (chunkSize < 0) {
            if (readSoFar) {
                return readSoFar;
            } else {
                return chunkSize;
            }
        }
        Q_ASSERT(chunkSize <= bytesToRead);
        bytesToRead -= chunkSize;
        readSoFar += chunkSize;
        if (bytesToRead) {
            if (!m_device->waitForReadyRead(-1)) {
                qDebug() << "waitForReadyRead failed\n";
                break;
            }
        }
    } while(bytesToRead);

    return readSoFar;
}

qint64 BlockingIODevice::writeData(const char * data, qint64 maxSize)
{
    Q_ASSERT(false);
    return -1;
}

Q_DECLARE_METATYPE(QList<ApiTraceError>);

Retracer::Retracer(QObject *parent)
    : QThread(parent),
      m_benchmarking(false),
      m_doubleBuffered(true),
      m_captureState(false),
      m_captureCall(0)
{
    qRegisterMetaType<QList<ApiTraceError> >();

#ifdef Q_OS_WIN
    QString format = QLatin1String("%1;");
#else
    QString format = QLatin1String("%1:");
#endif
    QString buildPath = format.arg(APITRACE_BINARY_DIR);
    m_processEnvironment = QProcessEnvironment::systemEnvironment();
    m_processEnvironment.insert("PATH", buildPath +
                                m_processEnvironment.value("PATH"));

    qputenv("PATH",
            m_processEnvironment.value("PATH").toLatin1());
}

QString Retracer::fileName() const
{
    return m_fileName;
}

void Retracer::setFileName(const QString &name)
{
    m_fileName = name;
}

void Retracer::setAPI(trace::API api)
{
    m_api = api;
}

bool Retracer::isBenchmarking() const
{
    return m_benchmarking;
}

void Retracer::setBenchmarking(bool bench)
{
    m_benchmarking = bench;
}

bool Retracer::isDoubleBuffered() const
{
    return m_doubleBuffered;
}

void Retracer::setDoubleBuffered(bool db)
{
    m_doubleBuffered = db;
}

void Retracer::setCaptureAtCallNumber(qlonglong num)
{
    m_captureCall = num;
}

qlonglong Retracer::captureAtCallNumber() const
{
    return m_captureCall;
}

bool Retracer::captureState() const
{
    return m_captureState;
}

void Retracer::setCaptureState(bool enable)
{
    m_captureState = enable;
}

bool Retracer::captureThumbnails() const
{
    return m_captureThumbnails;
}

void Retracer::setCaptureThumbnails(bool enable)
{
    m_captureThumbnails = enable;
}

/**
 * Starting point for the retracing thread.
 *
 * Overrides QThread::run().
 */
void Retracer::run()
{
    QString msg = QLatin1String("Replay finished!");

    /*
     * Construct command line
     */

    QString prog;
    QStringList arguments;

    switch (m_api) {
    case trace::API_GL:
        prog = QLatin1String("glretrace");
        break;
    case trace::API_EGL:
        prog = QLatin1String("eglretrace");
        break;
    case trace::API_DX:
    case trace::API_D3D7:
    case trace::API_D3D8:
    case trace::API_D3D9:
    case trace::API_D3D10:
    case trace::API_D3D10_1:
    case trace::API_D3D11:
#ifdef Q_OS_WIN
        prog = QLatin1String("d3dretrace");
#else
        prog = QLatin1String("wine");
        arguments << QLatin1String("d3dretrace.exe");
#endif
        break;
    default:
        emit finished(QLatin1String("Unsupported API"));
        return;
    }

    if (m_doubleBuffered) {
        arguments << QLatin1String("-db");
    } else {
        arguments << QLatin1String("-sb");
    }

    if (m_captureState) {
        arguments << QLatin1String("-D");
        arguments << QString::number(m_captureCall);
    } else if (m_captureThumbnails) {
        arguments << QLatin1String("-s"); // emit snapshots
        arguments << QLatin1String("-"); // emit to stdout
    } else if (m_benchmarking) {
        arguments << QLatin1String("-b");
    }

    arguments << m_fileName;

    /*
     * Start the process.
     */

    QProcess process;

    process.start(prog, arguments, QIODevice::ReadOnly);
    if (!process.waitForStarted(-1)) {
        emit finished(QLatin1String("Could not start process"));
        return;
    }

    /*
     * Process standard output
     */

    QList<QImage> thumbnails;
    QVariantMap parsedJson;

    process.setReadChannel(QProcess::StandardOutput);
    if (process.waitForReadyRead(-1)) {
        BlockingIODevice io(&process);

        if (m_captureState) {
            /*
             * Parse JSON from the output.
             *
             * XXX: QJSON's scanner is inneficient as it abuses single
             * character QIODevice::peek (not cheap), instead of maintaining a
             * lookahead character on its own.
             */

            bool ok = false;
            QJson::Parser jsonParser;
#if 0
            parsedJson = jsonParser.parse(&io, &ok).toMap();
#else
            /*
             * XXX: QJSON expects blocking IO, and it looks like
             * BlockingIODevice does not work reliably in all cases.
             */
            process.waitForFinished(-1);
            parsedJson = jsonParser.parse(&process, &ok).toMap();
#endif
            if (!ok) {
                msg = QLatin1String("failed to parse JSON");
            }
        } else if (m_captureThumbnails) {
            /*
             * Parse concatenated PNM images from output.
             */

            while (!io.atEnd()) {
                unsigned channels = 0;
                unsigned width = 0;
                unsigned height = 0;

                char header[512];
                qint64 headerSize = 0;
                int headerLines = 3; // assume no optional comment line

                for (int headerLine = 0; headerLine < headerLines; ++headerLine) {
                    qint64 headerRead = io.readLine(&header[headerSize], sizeof(header) - headerSize);

                    // if header actually contains optional comment line, ...
                    if (headerLine == 1 && header[headerSize] == '#') {
                        ++headerLines;
                    }

                    headerSize += headerRead;
                }

                const char *headerEnd = image::readPNMHeader(header, headerSize, &channels, &width, &height);

                // if invalid PNM header was encountered, ...
                if (header == headerEnd) {
                    qDebug() << "error: invalid snapshot stream encountered";
                    break;
                }

                // qDebug() << "channels: " << channels << ", width: " << width << ", height: " << height";

                QImage snapshot = QImage(width, height, channels == 1 ? QImage::Format_Mono : QImage::Format_RGB888);

                int rowBytes = channels * width;
                for (int y = 0; y < height; ++y) {
                    unsigned char *scanLine = snapshot.scanLine(y);
                    qint64 readBytes = io.read((char *) scanLine, rowBytes);
                    Q_ASSERT(readBytes == rowBytes);
                }

                QImage thumb = thumbnail(snapshot);
                thumbnails.append(thumb);
            }

            Q_ASSERT(process.state() != QProcess::Running);

        } else {
            QByteArray output;
            output = process.readAllStandardOutput();
            if (output.length() < 80) {
                msg = QString::fromUtf8(output);
            }
        }
    }

    /*
     * Wait for process termination
     */

    process.waitForFinished(-1);

    if (process.exitStatus() != QProcess::NormalExit) {
        msg = QLatin1String("Process crashed");
    } else if (process.exitCode() != 0) {
        msg = QLatin1String("Process exited with non zero exit code");
    }

    /*
     * Parse errors.
     */

    QList<ApiTraceError> errors;
    process.setReadChannel(QProcess::StandardError);
    QRegExp regexp("(^\\d+): +(\\b\\w+\\b): ([^\\r\\n]+)[\\r\\n]*$");
    while (!process.atEnd()) {
        QString line = process.readLine();
        if (regexp.indexIn(line) != -1) {
            ApiTraceError error;
            error.callIndex = regexp.cap(1).toInt();
            error.type = regexp.cap(2);
            error.message = regexp.cap(3);
            errors.append(error);
        }
    }

    /*
     * Emit signals
     */

    if (m_captureState) {
        ApiTraceState *state = new ApiTraceState(parsedJson);
        emit foundState(state);
        msg = QLatin1String("State fetched.");
    }

    if (m_captureThumbnails && !thumbnails.isEmpty()) {
        emit foundThumbnails(thumbnails);
    }

    if (!errors.isEmpty()) {
        emit retraceErrors(errors);
    }

    emit finished(msg);
}

#include "retracer.moc"
<commit_msg>glsl edit: grep multiline error/warning messages<commit_after>#include "retracer.h"

#include "apitracecall.h"
#include "thumbnail.h"

#include "image.hpp"

#include <QDebug>
#include <QVariant>
#include <QList>
#include <QImage>

#include <qjson/parser.h>

/**
 * Wrapper around a QProcess which enforces IO to block .
 *
 * Several QIODevice users (notably QJSON) expect blocking semantics, e.g.,
 * they expect that QIODevice::read() will blocked until the requested ammount
 * of bytes is read or end of file is reached. But by default QProcess, does
 * not block.  And passing QIODevice::Unbuffered mitigates but does not fully
 * address the problem either.
 *
 * This class wraps around QProcess, providing QIODevice interface, while
 * ensuring that all reads block.
 *
 * This class also works around a bug in QProcess::atEnd() implementation.
 *
 * See also:
 * - http://qt-project.org/wiki/Simple_Crypt_IO_Device
 * - http://qt-project.org/wiki/Custom_IO_Device
 */
class BlockingIODevice : public QIODevice
{
    /* We don't use the Q_OBJECT in this class given we don't declare any
     * signals and slots or use any other services provided by Qt's meta-object
     * system. */
public:
    BlockingIODevice(QProcess * io);
    bool isSequential() const;
    bool atEnd() const;
    bool waitForReadyRead(int msecs = -1);

protected:
    qint64 readData(char * data, qint64 maxSize);
    qint64 writeData(const char * data, qint64 maxSize);

private:
    QProcess *m_device;
};

BlockingIODevice::BlockingIODevice(QProcess * io) :
    m_device(io)
{
    /*
     * We pass QIODevice::Unbuffered to prevent the base QIODevice class to do
     * its own buffering on top of the overridden readData() method.
     *
     * The only buffering used will be to satisfy QIODevice::peek() and
     * QIODevice::ungetChar().
     */
    setOpenMode(ReadOnly | Unbuffered);
}

bool BlockingIODevice::isSequential() const
{
    return true;
}

bool BlockingIODevice::atEnd() const
{
    /*
     * XXX: QProcess::atEnd() documentation is wrong -- it will return true
     * even when the process is running --, so we try to workaround that here.
     */
    if (m_device->atEnd()) {
        if (m_device->state() == QProcess::Running) {
            if (!m_device->waitForReadyRead(-1)) {
                return true;
            }
        }
    }
    return false;
}

bool BlockingIODevice::waitForReadyRead(int msecs)
{
    Q_UNUSED(msecs);
    return true;
}

qint64 BlockingIODevice::readData(char * data, qint64 maxSize)
{
    qint64 bytesToRead = maxSize;
    qint64 readSoFar = 0;
    do {
        qint64 chunkSize = m_device->read(data + readSoFar, bytesToRead);
        if (chunkSize < 0) {
            if (readSoFar) {
                return readSoFar;
            } else {
                return chunkSize;
            }
        }
        Q_ASSERT(chunkSize <= bytesToRead);
        bytesToRead -= chunkSize;
        readSoFar += chunkSize;
        if (bytesToRead) {
            if (!m_device->waitForReadyRead(-1)) {
                qDebug() << "waitForReadyRead failed\n";
                break;
            }
        }
    } while(bytesToRead);

    return readSoFar;
}

qint64 BlockingIODevice::writeData(const char * data, qint64 maxSize)
{
    Q_ASSERT(false);
    return -1;
}

Q_DECLARE_METATYPE(QList<ApiTraceError>);

Retracer::Retracer(QObject *parent)
    : QThread(parent),
      m_benchmarking(false),
      m_doubleBuffered(true),
      m_captureState(false),
      m_captureCall(0)
{
    qRegisterMetaType<QList<ApiTraceError> >();

#ifdef Q_OS_WIN
    QString format = QLatin1String("%1;");
#else
    QString format = QLatin1String("%1:");
#endif
    QString buildPath = format.arg(APITRACE_BINARY_DIR);
    m_processEnvironment = QProcessEnvironment::systemEnvironment();
    m_processEnvironment.insert("PATH", buildPath +
                                m_processEnvironment.value("PATH"));

    qputenv("PATH",
            m_processEnvironment.value("PATH").toLatin1());
}

QString Retracer::fileName() const
{
    return m_fileName;
}

void Retracer::setFileName(const QString &name)
{
    m_fileName = name;
}

void Retracer::setAPI(trace::API api)
{
    m_api = api;
}

bool Retracer::isBenchmarking() const
{
    return m_benchmarking;
}

void Retracer::setBenchmarking(bool bench)
{
    m_benchmarking = bench;
}

bool Retracer::isDoubleBuffered() const
{
    return m_doubleBuffered;
}

void Retracer::setDoubleBuffered(bool db)
{
    m_doubleBuffered = db;
}

void Retracer::setCaptureAtCallNumber(qlonglong num)
{
    m_captureCall = num;
}

qlonglong Retracer::captureAtCallNumber() const
{
    return m_captureCall;
}

bool Retracer::captureState() const
{
    return m_captureState;
}

void Retracer::setCaptureState(bool enable)
{
    m_captureState = enable;
}

bool Retracer::captureThumbnails() const
{
    return m_captureThumbnails;
}

void Retracer::setCaptureThumbnails(bool enable)
{
    m_captureThumbnails = enable;
}

/**
 * Starting point for the retracing thread.
 *
 * Overrides QThread::run().
 */
void Retracer::run()
{
    QString msg = QLatin1String("Replay finished!");

    /*
     * Construct command line
     */

    QString prog;
    QStringList arguments;

    switch (m_api) {
    case trace::API_GL:
        prog = QLatin1String("glretrace");
        break;
    case trace::API_EGL:
        prog = QLatin1String("eglretrace");
        break;
    case trace::API_DX:
    case trace::API_D3D7:
    case trace::API_D3D8:
    case trace::API_D3D9:
    case trace::API_D3D10:
    case trace::API_D3D10_1:
    case trace::API_D3D11:
#ifdef Q_OS_WIN
        prog = QLatin1String("d3dretrace");
#else
        prog = QLatin1String("wine");
        arguments << QLatin1String("d3dretrace.exe");
#endif
        break;
    default:
        emit finished(QLatin1String("Unsupported API"));
        return;
    }

    if (m_doubleBuffered) {
        arguments << QLatin1String("-db");
    } else {
        arguments << QLatin1String("-sb");
    }

    if (m_captureState) {
        arguments << QLatin1String("-D");
        arguments << QString::number(m_captureCall);
    } else if (m_captureThumbnails) {
        arguments << QLatin1String("-s"); // emit snapshots
        arguments << QLatin1String("-"); // emit to stdout
    } else if (m_benchmarking) {
        arguments << QLatin1String("-b");
    }

    arguments << m_fileName;

    /*
     * Start the process.
     */

    QProcess process;

    process.start(prog, arguments, QIODevice::ReadOnly);
    if (!process.waitForStarted(-1)) {
        emit finished(QLatin1String("Could not start process"));
        return;
    }

    /*
     * Process standard output
     */

    QList<QImage> thumbnails;
    QVariantMap parsedJson;

    process.setReadChannel(QProcess::StandardOutput);
    if (process.waitForReadyRead(-1)) {
        BlockingIODevice io(&process);

        if (m_captureState) {
            /*
             * Parse JSON from the output.
             *
             * XXX: QJSON's scanner is inneficient as it abuses single
             * character QIODevice::peek (not cheap), instead of maintaining a
             * lookahead character on its own.
             */

            bool ok = false;
            QJson::Parser jsonParser;
#if 0
            parsedJson = jsonParser.parse(&io, &ok).toMap();
#else
            /*
             * XXX: QJSON expects blocking IO, and it looks like
             * BlockingIODevice does not work reliably in all cases.
             */
            process.waitForFinished(-1);
            parsedJson = jsonParser.parse(&process, &ok).toMap();
#endif
            if (!ok) {
                msg = QLatin1String("failed to parse JSON");
            }
        } else if (m_captureThumbnails) {
            /*
             * Parse concatenated PNM images from output.
             */

            while (!io.atEnd()) {
                unsigned channels = 0;
                unsigned width = 0;
                unsigned height = 0;

                char header[512];
                qint64 headerSize = 0;
                int headerLines = 3; // assume no optional comment line

                for (int headerLine = 0; headerLine < headerLines; ++headerLine) {
                    qint64 headerRead = io.readLine(&header[headerSize], sizeof(header) - headerSize);

                    // if header actually contains optional comment line, ...
                    if (headerLine == 1 && header[headerSize] == '#') {
                        ++headerLines;
                    }

                    headerSize += headerRead;
                }

                const char *headerEnd = image::readPNMHeader(header, headerSize, &channels, &width, &height);

                // if invalid PNM header was encountered, ...
                if (header == headerEnd) {
                    qDebug() << "error: invalid snapshot stream encountered";
                    break;
                }

                // qDebug() << "channels: " << channels << ", width: " << width << ", height: " << height";

                QImage snapshot = QImage(width, height, channels == 1 ? QImage::Format_Mono : QImage::Format_RGB888);

                int rowBytes = channels * width;
                for (int y = 0; y < height; ++y) {
                    unsigned char *scanLine = snapshot.scanLine(y);
                    qint64 readBytes = io.read((char *) scanLine, rowBytes);
                    Q_ASSERT(readBytes == rowBytes);
                }

                QImage thumb = thumbnail(snapshot);
                thumbnails.append(thumb);
            }

            Q_ASSERT(process.state() != QProcess::Running);

        } else {
            QByteArray output;
            output = process.readAllStandardOutput();
            if (output.length() < 80) {
                msg = QString::fromUtf8(output);
            }
        }
    }

    /*
     * Wait for process termination
     */

    process.waitForFinished(-1);

    if (process.exitStatus() != QProcess::NormalExit) {
        msg = QLatin1String("Process crashed");
    } else if (process.exitCode() != 0) {
        msg = QLatin1String("Process exited with non zero exit code");
    }

    /*
     * Parse errors.
     */

    QList<ApiTraceError> errors;
    process.setReadChannel(QProcess::StandardError);
    QRegExp regexp("(^\\d+): +(\\b\\w+\\b): ([^\\r\\n]+)[\\r\\n]*$");
    while (!process.atEnd()) {
        QString line = process.readLine();
        if (regexp.indexIn(line) != -1) {
            ApiTraceError error;
            error.callIndex = regexp.cap(1).toInt();
            error.type = regexp.cap(2);
            error.message = regexp.cap(3);
            errors.append(error);
        } else if (!errors.isEmpty()) {
            // Probably a multiligne message
            ApiTraceError &previous = errors.last();
            if (line.endsWith("\n")) {
                line.chop(1);
            }
            previous.message.append('\n');
            previous.message.append(line);
        }
    }

    /*
     * Emit signals
     */

    if (m_captureState) {
        ApiTraceState *state = new ApiTraceState(parsedJson);
        emit foundState(state);
        msg = QLatin1String("State fetched.");
    }

    if (m_captureThumbnails && !thumbnails.isEmpty()) {
        emit foundThumbnails(thumbnails);
    }

    if (!errors.isEmpty()) {
        emit retraceErrors(errors);
    }

    emit finished(msg);
}

#include "retracer.moc"
<|endoftext|>


<commit_before>/*
* Copyright (c) 2003-2009 Rony Shapiro <ronys@users.sourceforge.net>.
* All rights reserved. Use of the code is allowed under the
* Artistic License 2.0 terms, as specified in the LICENSE file
* distributed with this code, or available from
* http://www.opensource.org/licenses/artistic-license-2.0.php
*/

// MFilterXMLProcessor.cpp : implementation file
//

#include "../XMLDefs.h"

#if USE_XML_LIBRARY == MSXML

#include "MFilterXMLProcessor.h"
#include "MFilterSAX2Handlers.h"
#include <msxml6.h>

#include "../../corelib.h"

#include <sys/types.h>
#include <sys/stat.h>
#include <comutil.h>

#include <map>
#include <algorithm>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

MFilterXMLProcessor::MFilterXMLProcessor(PWSFilters &mapfilters, const FilterPool fpool,
                                         Asker *pAsker)
  : m_MSXML_Version(60), m_MapFilters(mapfilters), m_FPool(fpool), m_pAsker(pAsker)
{
}

MFilterXMLProcessor::~MFilterXMLProcessor()
{
}

bool MFilterXMLProcessor::Process(const bool &bvalidation,
                                  const StringX &strXMLData,
                                  const stringT &strXMLFileName,
                                  const stringT &strXSDFileName)
{
  HRESULT hr, hr0, hr60, hr40, hr30;
  bool b_ok = false;
  stringT cs_validation;
  LoadAString(cs_validation, IDSC_XMLVALIDATION);
  stringT cs_import;
  LoadAString(cs_import, IDSC_XMLIMPORT);

  m_strResultText = _T("");
  m_bValidation = bvalidation;  // Validate or Import

  //  Create SAXReader object
  ISAXXMLReader* pSAX2Reader = NULL;
  //  Get ready for XSD schema validation
  IXMLDOMSchemaCollection2* pSchemaCache = NULL;

  if (m_bValidation) { //XMLValidate
    // Try 60
    hr60 = CoCreateInstance(__uuidof(SAXXMLReader60), NULL, CLSCTX_ALL,
                            __uuidof(ISAXXMLReader), (void **)&pSAX2Reader);
    if (FAILED(hr60)) {
      // Try 40
      hr40 = CoCreateInstance(__uuidof(SAXXMLReader40), NULL, CLSCTX_ALL,
                              __uuidof(ISAXXMLReader), (void **)&pSAX2Reader);
      if (FAILED(hr40)) {
        // Try 30
        hr30 = CoCreateInstance(__uuidof(SAXXMLReader30), NULL, CLSCTX_ALL,
                                __uuidof(ISAXXMLReader), (void **)&pSAX2Reader);
        if (FAILED(hr30)) {
          LoadAString(m_strResultText, IDSC_NOMSXMLREADER);
          goto exit;
        } else {
          m_MSXML_Version = 30;
        }
      } else {
        m_MSXML_Version = 40;
      }
    } else {
      m_MSXML_Version = 60;
    }
  } else {  // XMLImport
    switch (m_MSXML_Version) {
      case 60:
        hr0 = CoCreateInstance(__uuidof(SAXXMLReader60), NULL, CLSCTX_ALL,
                               __uuidof(ISAXXMLReader), (void **)&pSAX2Reader);
        break;
      case 40:
        hr0 = CoCreateInstance(__uuidof(SAXXMLReader40), NULL, CLSCTX_ALL,
                               __uuidof(ISAXXMLReader), (void **)&pSAX2Reader);
        break;
      case 30:
        hr0 = CoCreateInstance(__uuidof(SAXXMLReader30), NULL, CLSCTX_ALL,
                               __uuidof(ISAXXMLReader), (void **)&pSAX2Reader);
        break;
      default:
        // Should never get here as validate would have sorted it and this doesn't get called if it fails
        ASSERT(0);
    }
  }

  //  Create ContentHandlerImpl object
  MFilterSAX2ContentHandler* pCH = new MFilterSAX2ContentHandler;
  //  Create ErrorHandlerImpl object
  MFilterSAX2ErrorHandler* pEH = new MFilterSAX2ErrorHandler;

  pCH->SetVariables(m_pAsker, &m_MapFilters, m_FPool, m_bValidation);

  //  Set Content Handler
  hr = pSAX2Reader->putContentHandler(pCH);

  //  Set Error Handler
  hr = pSAX2Reader->putErrorHandler(pEH);

  switch (m_MSXML_Version) {
    case 60:
      hr = CoCreateInstance(__uuidof(XMLSchemaCache60), NULL, CLSCTX_ALL,
                            __uuidof(IXMLDOMSchemaCollection2), (void **)&pSchemaCache);
      break;
    case 40:
      hr = CoCreateInstance(__uuidof(XMLSchemaCache40), NULL, CLSCTX_ALL,
                            __uuidof(IXMLDOMSchemaCollection2), (void **)&pSchemaCache);
      break;
    case 30:
      hr = CoCreateInstance(__uuidof(XMLSchemaCache30), NULL, CLSCTX_ALL,
                            __uuidof(IXMLDOMSchemaCollection2), (void **)&pSchemaCache);
      break;
    default:
      LoadAString(m_strResultText, IDSC_CANTXMLVALIDATE);
      goto exit;
  }

  if (!FAILED(hr)) {  // Create SchemaCache
    //  Initialize the SchemaCache object with the XSD filename
    CComVariant cvXSDFileName = strXSDFileName.c_str();
    hr = pSchemaCache->add(L"", cvXSDFileName);
    if (hr != S_OK) {
      LoadAString(m_strResultText, IDSC_INVALID_SCHEMA);
      return false;
    }
    hr = pSchemaCache->validate();
    if (hr != S_OK) {
      LoadAString(m_strResultText, IDSC_INVALID_SCHEMA);
      return false;
    }

    // Check that we can get the Schema version
    BSTR bst_schema, bst_schema_version;
    bst_schema = L"";
    ISchema *pischema;
    hr = pSchemaCache->getSchema(bst_schema, &pischema);
    if (hr != S_OK) {
      LoadAString(m_strResultText, IDSC_MISSING_SCHEMA_VER);
      return false;
    }
    hr = pischema->get_version(&bst_schema_version);
    if (hr != S_OK) {
      LoadAString(m_strResultText, IDSC_INVALID_SCHEMA_VER);
      return false;
    }

    pCH->SetSchemaVersion(&bst_schema_version);

    //  Set the SAXReader/Schema Cache features and properties
    {
      /* Documentation is unclear as to what is in which release.
      Try them all - if they don't get set, the world will not end!
      Common Error codes:
      S_OK          Operation successful         0x00000000
      E_NOTIMPL     Not implemented              0x80004001
      E_NOINTERFACE No such interface supported  0x80004002
      E_ABORT       Operation aborted            0x80004004
      E_FAIL        Unspecified failure          0x80004005
      E_INVALIDARG Invalid argument              0x80070057
      Normally not supported on a back level MSXMLn.DLL
      */

      // Want all validation errors
      hr = pSAX2Reader->putFeature(L"exhaustive-errors", VARIANT_TRUE);
      // Don't allow user to override validation by using DTDs
      hr = pSAX2Reader->putFeature(L"prohibit-dtd", VARIANT_TRUE);
      // Don't allow user to override validation by using DTDs (2 features)
      hr = pSAX2Reader->putFeature(L"http://xml.org/sax/features/external-general-entities", VARIANT_FALSE);
      hr = pSAX2Reader->putFeature(L"http://xml.org/sax/features/external-parameter-entities", VARIANT_FALSE);
      // Want to validate XML file
      hr = pSAX2Reader->putFeature(L"schema-validation", VARIANT_TRUE);
      // Ignore any schema specified in the XML file
      hr = pSAX2Reader->putFeature(L"use-schema-location", VARIANT_FALSE);
      // Ignore any schema in the XML file
      hr = pSAX2Reader->putFeature(L"use-inline-schema", VARIANT_FALSE);
      // Only use the XSD in PWSafe's installation directory!
      hr = pSAX2Reader->putProperty(L"schemas", _variant_t(pSchemaCache));
    }

    //  Let's begin the parsing now
    if (!strXMLFileName.empty()) {
      wchar_t wcURL[MAX_PATH]={0};
#ifdef _UNICODE
#if (_MSC_VER >= 1400)
      _tcscpy_s(wcURL, MAX_PATH, strXMLFileName.c_str());
#else
      _tcscpy(wcURL, strXMLFileName.c_str());
#endif
#else
      mbstowcs(wcURL, strXMLFileName.c_str(), strXMLFileName.length());
#endif
      hr = pSAX2Reader->parseURL(wcURL);
    } else {
      CComVariant cvXMLData = strXMLData.c_str();
      hr = pSAX2Reader->parse(cvXMLData);
    }

    if(!FAILED(hr)) {  // Check for parsing errors
      if(pEH->bErrorsFound == TRUE) {
        m_strResultText = pEH->m_strValidationResult;
      } else {
        b_ok = true;
      }
    } else {
      if(pEH->bErrorsFound == TRUE) {
        m_strResultText = pEH->m_strValidationResult;
      } else {
        Format(m_strResultText, IDSC_MSXMLPARSEERROR, m_MSXML_Version, hr,
               m_bValidation ? cs_validation.c_str() : cs_import.c_str());
      }
    }  // End Check for parsing errors

  } else {
    Format(m_strResultText, IDSC_MSXMLBADCREATESCHEMA, m_MSXML_Version, hr,
           m_bValidation ? cs_validation.c_str() : cs_import.c_str());
  }  // End Create Schema Cache

exit:
  if (pSchemaCache != NULL)
    pSchemaCache->Release();

  if (pSAX2Reader != NULL)
    pSAX2Reader->Release();

  return b_ok;
}

#endif /* USE_XML_LIBRARY == MSXML */
<commit_msg>Fix memory leak if XML import of filter fails verification<commit_after>/*
* Copyright (c) 2003-2009 Rony Shapiro <ronys@users.sourceforge.net>.
* All rights reserved. Use of the code is allowed under the
* Artistic License 2.0 terms, as specified in the LICENSE file
* distributed with this code, or available from
* http://www.opensource.org/licenses/artistic-license-2.0.php
*/

// MFilterXMLProcessor.cpp : implementation file
//

#include "../XMLDefs.h"

#if USE_XML_LIBRARY == MSXML

#include "MFilterXMLProcessor.h"
#include "MFilterSAX2Handlers.h"
#include <msxml6.h>

#include "../../corelib.h"

#include <sys/types.h>
#include <sys/stat.h>
#include <comutil.h>

#include <map>
#include <algorithm>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

MFilterXMLProcessor::MFilterXMLProcessor(PWSFilters &mapfilters, const FilterPool fpool,
                                         Asker *pAsker)
  : m_MSXML_Version(60), m_MapFilters(mapfilters), m_FPool(fpool), m_pAsker(pAsker)
{
}

MFilterXMLProcessor::~MFilterXMLProcessor()
{
}

bool MFilterXMLProcessor::Process(const bool &bvalidation,
                                  const StringX &strXMLData,
                                  const stringT &strXMLFileName,
                                  const stringT &strXSDFileName)
{
  HRESULT hr, hr0, hr60, hr40, hr30;
  bool b_ok(false);
  stringT cs_validation;
  LoadAString(cs_validation, IDSC_XMLVALIDATION);
  stringT cs_import;
  LoadAString(cs_import, IDSC_XMLIMPORT);

  m_strResultText = _T("");
  m_bValidation = bvalidation;  // Validate or Import

  //  Create SAXReader object
  ISAXXMLReader* pSAX2Reader = NULL;
  //  Get ready for XSD schema validation
  IXMLDOMSchemaCollection2* pSchemaCache = NULL;

  if (m_bValidation) { //XMLValidate
    // Try 60
    hr60 = CoCreateInstance(__uuidof(SAXXMLReader60), NULL, CLSCTX_ALL,
                            __uuidof(ISAXXMLReader), (void **)&pSAX2Reader);
    if (FAILED(hr60)) {
      // Try 40
      hr40 = CoCreateInstance(__uuidof(SAXXMLReader40), NULL, CLSCTX_ALL,
                              __uuidof(ISAXXMLReader), (void **)&pSAX2Reader);
      if (FAILED(hr40)) {
        // Try 30
        hr30 = CoCreateInstance(__uuidof(SAXXMLReader30), NULL, CLSCTX_ALL,
                                __uuidof(ISAXXMLReader), (void **)&pSAX2Reader);
        if (FAILED(hr30)) {
          LoadAString(m_strResultText, IDSC_NOMSXMLREADER);
          goto exit;
        } else {
          m_MSXML_Version = 30;
        }
      } else {
        m_MSXML_Version = 40;
      }
    } else {
      m_MSXML_Version = 60;
    }
  } else {  // XMLImport
    switch (m_MSXML_Version) {
      case 60:
        hr0 = CoCreateInstance(__uuidof(SAXXMLReader60), NULL, CLSCTX_ALL,
                               __uuidof(ISAXXMLReader), (void **)&pSAX2Reader);
        break;
      case 40:
        hr0 = CoCreateInstance(__uuidof(SAXXMLReader40), NULL, CLSCTX_ALL,
                               __uuidof(ISAXXMLReader), (void **)&pSAX2Reader);
        break;
      case 30:
        hr0 = CoCreateInstance(__uuidof(SAXXMLReader30), NULL, CLSCTX_ALL,
                               __uuidof(ISAXXMLReader), (void **)&pSAX2Reader);
        break;
      default:
        // Should never get here as validate would have sorted it and this doesn't get called if it fails
        ASSERT(0);
    }
  }

  //  Create ContentHandlerImpl object
  MFilterSAX2ContentHandler* pCH = new MFilterSAX2ContentHandler;
  //  Create ErrorHandlerImpl object
  MFilterSAX2ErrorHandler* pEH = new MFilterSAX2ErrorHandler;

  pCH->SetVariables(m_pAsker, &m_MapFilters, m_FPool, m_bValidation);

  //  Set Content Handler
  hr = pSAX2Reader->putContentHandler(pCH);

  //  Set Error Handler
  hr = pSAX2Reader->putErrorHandler(pEH);

  switch (m_MSXML_Version) {
    case 60:
      hr = CoCreateInstance(__uuidof(XMLSchemaCache60), NULL, CLSCTX_ALL,
                            __uuidof(IXMLDOMSchemaCollection2), (void **)&pSchemaCache);
      break;
    case 40:
      hr = CoCreateInstance(__uuidof(XMLSchemaCache40), NULL, CLSCTX_ALL,
                            __uuidof(IXMLDOMSchemaCollection2), (void **)&pSchemaCache);
      break;
    case 30:
      hr = CoCreateInstance(__uuidof(XMLSchemaCache30), NULL, CLSCTX_ALL,
                            __uuidof(IXMLDOMSchemaCollection2), (void **)&pSchemaCache);
      break;
    default:
      LoadAString(m_strResultText, IDSC_CANTXMLVALIDATE);
      goto exit;
  }

  if (!FAILED(hr)) {  // Create SchemaCache
    //  Initialize the SchemaCache object with the XSD filename
    CComVariant cvXSDFileName = strXSDFileName.c_str();
    hr = pSchemaCache->add(L"", cvXSDFileName);
    if (hr != S_OK) {
      LoadAString(m_strResultText, IDSC_INVALID_SCHEMA);
      goto exit;
    }
    hr = pSchemaCache->validate();
    if (hr != S_OK) {
      LoadAString(m_strResultText, IDSC_INVALID_SCHEMA);
      goto exit;
    }

    // Check that we can get the Schema version
    BSTR bst_schema, bst_schema_version;
    bst_schema = L"";
    ISchema *pischema;
    hr = pSchemaCache->getSchema(bst_schema, &pischema);
    if (hr != S_OK) {
      LoadAString(m_strResultText, IDSC_MISSING_SCHEMA_VER);
      goto exit;
    }
    hr = pischema->get_version(&bst_schema_version);
    if (hr != S_OK) {
      LoadAString(m_strResultText, IDSC_INVALID_SCHEMA_VER);
      goto exit;
    }

    pCH->SetSchemaVersion(&bst_schema_version);

    //  Set the SAXReader/Schema Cache features and properties
    {
      /* Documentation is unclear as to what is in which release.
      Try them all - if they don't get set, the world will not end!
      Common Error codes:
      S_OK          Operation successful         0x00000000
      E_NOTIMPL     Not implemented              0x80004001
      E_NOINTERFACE No such interface supported  0x80004002
      E_ABORT       Operation aborted            0x80004004
      E_FAIL        Unspecified failure          0x80004005
      E_INVALIDARG Invalid argument              0x80070057
      Normally not supported on a back level MSXMLn.DLL
      */

      // Want all validation errors
      hr = pSAX2Reader->putFeature(L"exhaustive-errors", VARIANT_TRUE);
      // Don't allow user to override validation by using DTDs
      hr = pSAX2Reader->putFeature(L"prohibit-dtd", VARIANT_TRUE);
      // Don't allow user to override validation by using DTDs (2 features)
      hr = pSAX2Reader->putFeature(L"http://xml.org/sax/features/external-general-entities", VARIANT_FALSE);
      hr = pSAX2Reader->putFeature(L"http://xml.org/sax/features/external-parameter-entities", VARIANT_FALSE);
      // Want to validate XML file
      hr = pSAX2Reader->putFeature(L"schema-validation", VARIANT_TRUE);
      // Ignore any schema specified in the XML file
      hr = pSAX2Reader->putFeature(L"use-schema-location", VARIANT_FALSE);
      // Ignore any schema in the XML file
      hr = pSAX2Reader->putFeature(L"use-inline-schema", VARIANT_FALSE);
      // Only use the XSD in PWSafe's installation directory!
      hr = pSAX2Reader->putProperty(L"schemas", _variant_t(pSchemaCache));
    }

    //  Let's begin the parsing now
    if (!strXMLFileName.empty()) {
      wchar_t wcURL[MAX_PATH]={0};
#ifdef _UNICODE
#if (_MSC_VER >= 1400)
      _tcscpy_s(wcURL, MAX_PATH, strXMLFileName.c_str());
#else
      _tcscpy(wcURL, strXMLFileName.c_str());
#endif
#else
      mbstowcs(wcURL, strXMLFileName.c_str(), strXMLFileName.length());
#endif
      hr = pSAX2Reader->parseURL(wcURL);
    } else {
      CComVariant cvXMLData = strXMLData.c_str();
      hr = pSAX2Reader->parse(cvXMLData);
    }

    if(!FAILED(hr)) {  // Check for parsing errors
      if(pEH->bErrorsFound == TRUE) {
        m_strResultText = pEH->m_strValidationResult;
      } else {
        b_ok = true;
      }
    } else {
      if(pEH->bErrorsFound == TRUE) {
        m_strResultText = pEH->m_strValidationResult;
      } else {
        Format(m_strResultText, IDSC_MSXMLPARSEERROR, m_MSXML_Version, hr,
               m_bValidation ? cs_validation.c_str() : cs_import.c_str());
      }
    }  // End Check for parsing errors

  } else {
    Format(m_strResultText, IDSC_MSXMLBADCREATESCHEMA, m_MSXML_Version, hr,
           m_bValidation ? cs_validation.c_str() : cs_import.c_str());
  }  // End Create Schema Cache

exit:
  if (pSchemaCache != NULL)
    pSchemaCache->Release();

  if (pSAX2Reader != NULL)
    pSAX2Reader->Release();

  return b_ok;
}

#endif /* USE_XML_LIBRARY == MSXML */
<|endoftext|>


<commit_before>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Language:  C++
Date:      $Date: 2009-04-18 12:03:52 +0200 (Sat, 18 Apr 2009) $
Version:   $Revision: 16883 $

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "mitkShaderRepository.h"
#include "mitkShaderEnumProperty.h"
#include "mitkProperties.h"

#include <vtkProperty.h>
#include <vtkXMLMaterial.h>
#include <vtkXMLShader.h>
#include <vtkXMLDataElement.h>

#include <itkDirectory.h>
#include <itksys/SystemTools.hxx>

#include "mitkStandardFileLocations.h"

mitk::ShaderRepository::ShaderRepository()
{
  LoadShaders();
}

mitk::ShaderRepository::~ShaderRepository()
{
}

mitk::ShaderRepository *mitk::ShaderRepository::GetGlobalShaderRepository()
{
  static mitk::ShaderRepository::Pointer i;

  if(i.IsNull())
  {
    i=mitk::ShaderRepository::New();
  }

  return i;
}

void mitk::ShaderRepository::LoadShaders()
{
  itk::Directory::Pointer dir = itk::Directory::New();

  std::string mitkLighting = mitk::StandardFileLocations::GetInstance()->FindFile("mitkShaderLighting.xml", "Core/Code/Rendering");

  std::string dirPath = "./vtk_shader";

  if(mitkLighting.size() > 0)
  {
    // we found the default shader
    dirPath = itksys::SystemTools::GetFilenamePath( mitkLighting );

    LOG_INFO << "shader repository found default mitk shader at '" << dirPath << "'";
  }

  if( dir->Load( dirPath.c_str() ) )
  {
    int n = dir->GetNumberOfFiles();
    for(int r=0;r<n;r++)
    {
      const char *filename = dir->GetFile( r );

      std::string extension = itksys::SystemTools::GetFilenameExtension(filename);

      if(extension.compare(".xml")==0)
      {
        Shader::Pointer element=Shader::New();

        element->name = itksys::SystemTools::GetFilenameWithoutExtension(filename);
        element->path = dirPath + std::string("/") + element->name + std::string(".xml");

        LOG_INFO << "found shader '" << element->name << "'";

        element->LoadPropertiesFromPath();

        shaders.push_back(element);
      }
    }
  }
}

mitk::ShaderRepository::Shader::Shader()
{
}

mitk::ShaderRepository::Shader::~Shader()
{
}

void mitk::ShaderRepository::Shader::LoadPropertiesFromPath()
{
  vtkProperty *p;

  p = vtkProperty::New();

  p->LoadMaterial(path.c_str());

  vtkXMLMaterial *m=p->GetMaterial();

  // Vertexshader uniforms
  {
    vtkXMLShader *s=m->GetVertexShader();
    vtkXMLDataElement *x=s->GetRootElement();
    int n=x->GetNumberOfNestedElements();
    for(int r=0;r<n;r++)
    {
      vtkXMLDataElement *y=x->GetNestedElement(r);
      if(!strcmp(y->GetName(),"ApplicationUniform"))
      {
          Uniform::Pointer element=Uniform::New();
          element->LoadFromXML(y);
          uniforms.push_back(element);
      }
    }
  }

  // Fragmentshader uniforms
  {
    vtkXMLShader *s=m->GetFragmentShader();
    vtkXMLDataElement *x=s->GetRootElement();
    int n=x->GetNumberOfNestedElements();
    for(int r=0;r<n;r++)
    {
      vtkXMLDataElement *y=x->GetNestedElement(r);
      if(!strcmp(y->GetName(),"ApplicationUniform"))
      {
          Uniform::Pointer element=Uniform::New();
          element->LoadFromXML(y);
          uniforms.push_back(element);
      }
    }
  }

  p->Delete();
}

mitk::ShaderRepository::Shader::Uniform::Uniform()
{
}

mitk::ShaderRepository::Shader::Uniform::~Uniform()
{
}

mitk::ShaderRepository::Shader *mitk::ShaderRepository::GetShader(const char *id)
{
  std::list<Shader::Pointer>::const_iterator i = shaders.begin();

  while( i != shaders.end() )
  {
    if( (*i)->name.compare(id) == 0)
      return (*i);

    i++;
  }

  return 0;
}

void mitk::ShaderRepository::Shader::Uniform::LoadFromXML(vtkXMLDataElement *y)
{
  LOG_INFO << "found uniform '" << y->GetAttribute("name") << "' type=" << y->GetAttribute("type");// << " default=" << y->GetAttribute("value");

  name = y->GetAttribute("name");

  const char *sType=y->GetAttribute("type");

  if(!strcmp(sType,"float"))
    type=glsl_float;
  else if(!strcmp(sType,"vec2"))
    type=glsl_vec2;
  else if(!strcmp(sType,"vec3"))
    type=glsl_vec3;
  else if(!strcmp(sType,"vec4"))
    type=glsl_vec4;
  else if(!strcmp(sType,"int"))
    type=glsl_int;
  else if(!strcmp(sType,"ivec2"))
    type=glsl_ivec2;
  else if(!strcmp(sType,"ivec3"))
    type=glsl_ivec3;
  else if(!strcmp(sType,"ivec4"))
    type=glsl_ivec4;
  else
  {
    type=glsl_none;
    printf("shader repository: unknown type for uniform!!!\n");
  }

  defaultFloat[0]=defaultFloat[1]=defaultFloat[2]=defaultFloat[3]=0;

                                     /*
  const char *sDefault=y->GetAttribute("value");

  switch(type)
  {
    case glsl_float:
      sscanf(sDefault,"%f",&defaultFloat[0]);
      break;

    case glsl_vec2:
      sscanf(sDefault,"%f %f",&defaultFloat[0],&defaultFloat[1]);
      break;

    case glsl_vec3:
      sscanf(sDefault,"%f %f %f",&defaultFloat[0],&defaultFloat[1],&defaultFloat[2]);
      break;

    case glsl_vec4:
      sscanf(sDefault,"%f %f %f %f",&defaultFloat[0],&defaultFloat[1],&defaultFloat[2],&defaultFloat[3]);
      break;
  }           */
}

void mitk::ShaderRepository::AddDefaultProperties(mitk::DataTreeNode* node, mitk::BaseRenderer* renderer, bool overwrite)
{
  node->AddProperty( "shader", mitk::ShaderEnumProperty::New(), renderer, overwrite );

  std::list<Shader::Pointer>::const_iterator i = shaders.begin();

  while( i != shaders.end() )
  {
    std::list<Shader::Uniform::Pointer> *l = (*i)->GetUniforms();

    std::string shaderName = (*i)->name;

    std::list<Shader::Uniform::Pointer>::const_iterator j = l->begin();

    while( j != l->end() )
    {
      std::string propertyName = "shader." + shaderName + "." + (*j)->name;

      switch( (*j)->type )
      {
        case Shader::Uniform::glsl_float:
          node->AddProperty( propertyName.c_str(), mitk::FloatProperty::New( (*j)->defaultFloat[0] ), renderer, overwrite );
          break;

        case Shader::Uniform::glsl_vec2:
          node->AddProperty( (propertyName+".x").c_str(), mitk::FloatProperty::New( (*j)->defaultFloat[0] ), renderer, overwrite );
          node->AddProperty( (propertyName+".y").c_str(), mitk::FloatProperty::New( (*j)->defaultFloat[1] ), renderer, overwrite );
          break;

        case Shader::Uniform::glsl_vec3:
          node->AddProperty( (propertyName+".x").c_str(), mitk::FloatProperty::New( (*j)->defaultFloat[0] ), renderer, overwrite );
          node->AddProperty( (propertyName+".y").c_str(), mitk::FloatProperty::New( (*j)->defaultFloat[1] ), renderer, overwrite );
          node->AddProperty( (propertyName+".z").c_str(), mitk::FloatProperty::New( (*j)->defaultFloat[2] ), renderer, overwrite );
          break;

       case Shader::Uniform::glsl_vec4:
          node->AddProperty( (propertyName+".x").c_str(), mitk::FloatProperty::New( (*j)->defaultFloat[0] ), renderer, overwrite );
          node->AddProperty( (propertyName+".y").c_str(), mitk::FloatProperty::New( (*j)->defaultFloat[1] ), renderer, overwrite );
          node->AddProperty( (propertyName+".z").c_str(), mitk::FloatProperty::New( (*j)->defaultFloat[2] ), renderer, overwrite );
          node->AddProperty( (propertyName+".w").c_str(), mitk::FloatProperty::New( (*j)->defaultFloat[3] ), renderer, overwrite );
          break;

      }

      j++;

    }

    i++;
  }

}

void mitk::ShaderRepository::ApplyProperties(mitk::DataTreeNode* node, vtkActor *actor, mitk::BaseRenderer* renderer,itk::TimeStamp &MTime)
{
  bool setMTime = false;

  vtkProperty* property = actor->GetProperty();

  unsigned long ts = MTime.GetMTime();

  mitk::ShaderEnumProperty *sep=(mitk::ShaderEnumProperty *)node->GetProperty("shader",renderer);

  std::string shader=sep->GetValueAsString();

  // Need update pipeline mode
  if(sep->GetMTime() > ts)
  {
    if(shader.compare("fixed")==0)
    {
      //LOG_INFO << "disabling shader";
      property->ShadingOff();
    }
    else
    {
      Shader *s=GetShader(shader.c_str());
      if(s)
      {
        //LOG_INFO << "enabling shader";
        property->ShadingOn();
        property->LoadMaterial(s->path.c_str());
      }
    }
    setMTime = true;
  }

   if(shader.compare("fixed")!=0)
  {
    Shader *s=GetShader(shader.c_str());

    if(!s)
      return;

    std::list<Shader::Uniform::Pointer>::const_iterator j = s->uniforms.begin();

    while( j != s->uniforms.end() )
    {
      std::string propertyName = "shader." + s->name + "." + (*j)->name;

    //  LOG_INFO << "querying property: " << propertyName;

    //  mitk::BaseProperty *p = node->GetProperty( propertyName.c_str(), renderer );

    //  if( p && p->GetMTime() > MTime.GetMTime() )
      {
        float fval[4];

       // LOG_INFO << "copying property " << propertyName << " ->->- " << (*j)->name << " type=" << (*j)->type ;

        switch( (*j)->type )
        {
          case Shader::Uniform::glsl_float:
            node->GetFloatProperty( propertyName.c_str(), fval[0], renderer );
            property->AddShaderVariable( (*j)->name.c_str(), 1 , fval );
            break;

          case Shader::Uniform::glsl_vec2:
            node->GetFloatProperty( (propertyName+".x").c_str(), fval[0], renderer );
            node->GetFloatProperty( (propertyName+".y").c_str(), fval[1], renderer );
            property->AddShaderVariable( (*j)->name.c_str(), 2 , fval );
            break;

          case Shader::Uniform::glsl_vec3:
            node->GetFloatProperty( (propertyName+".x").c_str(), fval[0], renderer );
            node->GetFloatProperty( (propertyName+".y").c_str(), fval[1], renderer );
            node->GetFloatProperty( (propertyName+".z").c_str(), fval[2], renderer );

            property->AddShaderVariable( (*j)->name.c_str(), 3 , fval );
            break;

         case Shader::Uniform::glsl_vec4:
            node->GetFloatProperty( (propertyName+".x").c_str(), fval[0], renderer );
            node->GetFloatProperty( (propertyName+".y").c_str(), fval[1], renderer );
            node->GetFloatProperty( (propertyName+".z").c_str(), fval[2], renderer );
            node->GetFloatProperty( (propertyName+".w").c_str(), fval[3], renderer );
            property->AddShaderVariable( (*j)->name.c_str(), 4 , fval );
            break;

        }

        //setMTime=true;
      }

      j++;
    }
  }

  if(setMTime)
    MTime.Modified();
}

<commit_msg>FIX (#2292): fixed material editor exception, when no surface is available<commit_after>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Language:  C++
Date:      $Date: 2009-04-18 12:03:52 +0200 (Sat, 18 Apr 2009) $
Version:   $Revision: 16883 $

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "mitkShaderRepository.h"
#include "mitkShaderEnumProperty.h"
#include "mitkProperties.h"

#include <vtkProperty.h>
#include <vtkXMLMaterial.h>
#include <vtkXMLShader.h>
#include <vtkXMLDataElement.h>

#include <itkDirectory.h>
#include <itksys/SystemTools.hxx>

#include "mitkStandardFileLocations.h"

mitk::ShaderRepository::ShaderRepository()
{
  LoadShaders();
}

mitk::ShaderRepository::~ShaderRepository()
{
}

mitk::ShaderRepository *mitk::ShaderRepository::GetGlobalShaderRepository()
{
  static mitk::ShaderRepository::Pointer i;

  if(i.IsNull())
  {
    i=mitk::ShaderRepository::New();
  }

  return i;
}

void mitk::ShaderRepository::LoadShaders()
{
  itk::Directory::Pointer dir = itk::Directory::New();

  std::string mitkLighting = mitk::StandardFileLocations::GetInstance()->FindFile("mitkShaderLighting.xml", "Core/Code/Rendering");

  std::string dirPath = "./vtk_shader";

  if(mitkLighting.size() > 0)
  {
    // we found the default shader
    dirPath = itksys::SystemTools::GetFilenamePath( mitkLighting );

    LOG_INFO << "shader repository found default mitk shader at '" << dirPath << "'";
  }

  if( dir->Load( dirPath.c_str() ) )
  {
    int n = dir->GetNumberOfFiles();
    for(int r=0;r<n;r++)
    {
      const char *filename = dir->GetFile( r );

      std::string extension = itksys::SystemTools::GetFilenameExtension(filename);

      if(extension.compare(".xml")==0)
      {
        Shader::Pointer element=Shader::New();

        element->name = itksys::SystemTools::GetFilenameWithoutExtension(filename);
        element->path = dirPath + std::string("/") + element->name + std::string(".xml");

        LOG_INFO << "found shader '" << element->name << "'";

        element->LoadPropertiesFromPath();

        shaders.push_back(element);
      }
    }
  }
}

mitk::ShaderRepository::Shader::Shader()
{
}

mitk::ShaderRepository::Shader::~Shader()
{
}

void mitk::ShaderRepository::Shader::LoadPropertiesFromPath()
{
  vtkProperty *p;

  p = vtkProperty::New();

  p->LoadMaterial(path.c_str());

  vtkXMLMaterial *m=p->GetMaterial();

  // Vertexshader uniforms
  {
    vtkXMLShader *s=m->GetVertexShader();
    vtkXMLDataElement *x=s->GetRootElement();
    int n=x->GetNumberOfNestedElements();
    for(int r=0;r<n;r++)
    {
      vtkXMLDataElement *y=x->GetNestedElement(r);
      if(!strcmp(y->GetName(),"ApplicationUniform"))
      {
          Uniform::Pointer element=Uniform::New();
          element->LoadFromXML(y);
          uniforms.push_back(element);
      }
    }
  }

  // Fragmentshader uniforms
  {
    vtkXMLShader *s=m->GetFragmentShader();
    vtkXMLDataElement *x=s->GetRootElement();
    int n=x->GetNumberOfNestedElements();
    for(int r=0;r<n;r++)
    {
      vtkXMLDataElement *y=x->GetNestedElement(r);
      if(!strcmp(y->GetName(),"ApplicationUniform"))
      {
          Uniform::Pointer element=Uniform::New();
          element->LoadFromXML(y);
          uniforms.push_back(element);
      }
    }
  }

  p->Delete();
}

mitk::ShaderRepository::Shader::Uniform::Uniform()
{
}

mitk::ShaderRepository::Shader::Uniform::~Uniform()
{
}

mitk::ShaderRepository::Shader *mitk::ShaderRepository::GetShader(const char *id)
{
  std::list<Shader::Pointer>::const_iterator i = shaders.begin();

  while( i != shaders.end() )
  {
    if( (*i)->name.compare(id) == 0)
      return (*i);

    i++;
  }

  return 0;
}

void mitk::ShaderRepository::Shader::Uniform::LoadFromXML(vtkXMLDataElement *y)
{
  LOG_INFO << "found uniform '" << y->GetAttribute("name") << "' type=" << y->GetAttribute("type");// << " default=" << y->GetAttribute("value");

  name = y->GetAttribute("name");

  const char *sType=y->GetAttribute("type");

  if(!strcmp(sType,"float"))
    type=glsl_float;
  else if(!strcmp(sType,"vec2"))
    type=glsl_vec2;
  else if(!strcmp(sType,"vec3"))
    type=glsl_vec3;
  else if(!strcmp(sType,"vec4"))
    type=glsl_vec4;
  else if(!strcmp(sType,"int"))
    type=glsl_int;
  else if(!strcmp(sType,"ivec2"))
    type=glsl_ivec2;
  else if(!strcmp(sType,"ivec3"))
    type=glsl_ivec3;
  else if(!strcmp(sType,"ivec4"))
    type=glsl_ivec4;
  else
  {
    type=glsl_none;
    printf("shader repository: unknown type for uniform!!!\n");
  }

  defaultFloat[0]=defaultFloat[1]=defaultFloat[2]=defaultFloat[3]=0;

                                     /*
  const char *sDefault=y->GetAttribute("value");

  switch(type)
  {
    case glsl_float:
      sscanf(sDefault,"%f",&defaultFloat[0]);
      break;

    case glsl_vec2:
      sscanf(sDefault,"%f %f",&defaultFloat[0],&defaultFloat[1]);
      break;

    case glsl_vec3:
      sscanf(sDefault,"%f %f %f",&defaultFloat[0],&defaultFloat[1],&defaultFloat[2]);
      break;

    case glsl_vec4:
      sscanf(sDefault,"%f %f %f %f",&defaultFloat[0],&defaultFloat[1],&defaultFloat[2],&defaultFloat[3]);
      break;
  }           */
}

void mitk::ShaderRepository::AddDefaultProperties(mitk::DataTreeNode* node, mitk::BaseRenderer* renderer, bool overwrite)
{
  node->AddProperty( "shader", mitk::ShaderEnumProperty::New(), renderer, overwrite );

  std::list<Shader::Pointer>::const_iterator i = shaders.begin();

  while( i != shaders.end() )
  {
    std::list<Shader::Uniform::Pointer> *l = (*i)->GetUniforms();

    std::string shaderName = (*i)->name;

    std::list<Shader::Uniform::Pointer>::const_iterator j = l->begin();

    while( j != l->end() )
    {
      std::string propertyName = "shader." + shaderName + "." + (*j)->name;

      switch( (*j)->type )
      {
        case Shader::Uniform::glsl_float:
          node->AddProperty( propertyName.c_str(), mitk::FloatProperty::New( (*j)->defaultFloat[0] ), renderer, overwrite );
          break;

        case Shader::Uniform::glsl_vec2:
          node->AddProperty( (propertyName+".x").c_str(), mitk::FloatProperty::New( (*j)->defaultFloat[0] ), renderer, overwrite );
          node->AddProperty( (propertyName+".y").c_str(), mitk::FloatProperty::New( (*j)->defaultFloat[1] ), renderer, overwrite );
          break;

        case Shader::Uniform::glsl_vec3:
          node->AddProperty( (propertyName+".x").c_str(), mitk::FloatProperty::New( (*j)->defaultFloat[0] ), renderer, overwrite );
          node->AddProperty( (propertyName+".y").c_str(), mitk::FloatProperty::New( (*j)->defaultFloat[1] ), renderer, overwrite );
          node->AddProperty( (propertyName+".z").c_str(), mitk::FloatProperty::New( (*j)->defaultFloat[2] ), renderer, overwrite );
          break;

       case Shader::Uniform::glsl_vec4:
          node->AddProperty( (propertyName+".x").c_str(), mitk::FloatProperty::New( (*j)->defaultFloat[0] ), renderer, overwrite );
          node->AddProperty( (propertyName+".y").c_str(), mitk::FloatProperty::New( (*j)->defaultFloat[1] ), renderer, overwrite );
          node->AddProperty( (propertyName+".z").c_str(), mitk::FloatProperty::New( (*j)->defaultFloat[2] ), renderer, overwrite );
          node->AddProperty( (propertyName+".w").c_str(), mitk::FloatProperty::New( (*j)->defaultFloat[3] ), renderer, overwrite );
          break;

      }

      j++;

    }

    i++;
  }

}

void mitk::ShaderRepository::ApplyProperties(mitk::DataTreeNode* node, vtkActor *actor, mitk::BaseRenderer* renderer,itk::TimeStamp &MTime)
{
  bool setMTime = false;

  vtkProperty* property = actor->GetProperty();

  unsigned long ts = MTime.GetMTime();

  mitk::ShaderEnumProperty *sep=(mitk::ShaderEnumProperty *)node->GetProperty("shader",renderer);

  if(!sep)
  {
    property->ShadingOff();
    return;
  }

  std::string shader=sep->GetValueAsString();

  // Need update pipeline mode
  if(sep->GetMTime() > ts)
  {
    if(shader.compare("fixed")==0)
    {
      //LOG_INFO << "disabling shader";
      property->ShadingOff();
    }
    else
    {
      Shader *s=GetShader(shader.c_str());
      if(s)
      {
        //LOG_INFO << "enabling shader";
        property->ShadingOn();
        property->LoadMaterial(s->path.c_str());
      }
    }
    setMTime = true;
  }

   if(shader.compare("fixed")!=0)
  {
    Shader *s=GetShader(shader.c_str());

    if(!s)
      return;

    std::list<Shader::Uniform::Pointer>::const_iterator j = s->uniforms.begin();

    while( j != s->uniforms.end() )
    {
      std::string propertyName = "shader." + s->name + "." + (*j)->name;

    //  LOG_INFO << "querying property: " << propertyName;

    //  mitk::BaseProperty *p = node->GetProperty( propertyName.c_str(), renderer );

    //  if( p && p->GetMTime() > MTime.GetMTime() )
      {
        float fval[4];

       // LOG_INFO << "copying property " << propertyName << " ->->- " << (*j)->name << " type=" << (*j)->type ;

        switch( (*j)->type )
        {
          case Shader::Uniform::glsl_float:
            node->GetFloatProperty( propertyName.c_str(), fval[0], renderer );
            property->AddShaderVariable( (*j)->name.c_str(), 1 , fval );
            break;

          case Shader::Uniform::glsl_vec2:
            node->GetFloatProperty( (propertyName+".x").c_str(), fval[0], renderer );
            node->GetFloatProperty( (propertyName+".y").c_str(), fval[1], renderer );
            property->AddShaderVariable( (*j)->name.c_str(), 2 , fval );
            break;

          case Shader::Uniform::glsl_vec3:
            node->GetFloatProperty( (propertyName+".x").c_str(), fval[0], renderer );
            node->GetFloatProperty( (propertyName+".y").c_str(), fval[1], renderer );
            node->GetFloatProperty( (propertyName+".z").c_str(), fval[2], renderer );

            property->AddShaderVariable( (*j)->name.c_str(), 3 , fval );
            break;

         case Shader::Uniform::glsl_vec4:
            node->GetFloatProperty( (propertyName+".x").c_str(), fval[0], renderer );
            node->GetFloatProperty( (propertyName+".y").c_str(), fval[1], renderer );
            node->GetFloatProperty( (propertyName+".z").c_str(), fval[2], renderer );
            node->GetFloatProperty( (propertyName+".w").c_str(), fval[3], renderer );
            property->AddShaderVariable( (*j)->name.c_str(), 4 , fval );
            break;

        }

        //setMTime=true;
      }

      j++;
    }
  }

  if(setMTime)
    MTime.Modified();
}

<|endoftext|>