⛏️ index : haiku.git

#include <Application.h>
#include <Bitmap.h>
#include <View.h>
#include <Window.h>
#include <malloc.h>
#include <stdio.h>


#if 0
{
	// usage example for simple rects
	port_id port = find_port("drawing_debugger_port");
	if (port >= 0) {
		write_port_etc(port, 'RECT', &interestingRect, sizeof(BRect),
			B_RELATIVE_TIMEOUT, 0);
	}


	// usage example for regions
	port_id port = find_port("drawing_debugger_port");
	if (port >= 0) {
		int32 rectCount = region->CountRects();
		for (int32 i = 0; i < rectCount; i++) {
			BRect interestingRect = region->RectAt(i);
			write_port_etc(port, 'RECT', &interestingRect, sizeof(BRect),
				B_RELATIVE_TIMEOUT, 0);
		}
	}
}
#endif


class DrawingDebuggerView : public BView {
public:
								DrawingDebuggerView(BRect frame);
virtual							~DrawingDebuggerView();

virtual	void					Draw(BRect updateRect);

private:
static	int32					_PortListener(void *data);

		BBitmap *				fBitmap;
		BView *					fOffscreenView;
		thread_id				fListenerThread;
		bool					fStopListener;
};


class DrawingDebuggerWindow : public BWindow {
public:
								DrawingDebuggerWindow(BRect frame);

private:
		DrawingDebuggerView *	fView;
};


class DrawingDebuggerApp : public BApplication {
public:
								DrawingDebuggerApp();

private:
		DrawingDebuggerWindow *	fWindow;
};


rgb_color
random_color()
{
	rgb_color result;
	result.red = system_time() % 256;
	result.green = (system_time() >> 8) % 256;
	result.blue = (system_time() >> 16) % 256;
	return result;
}


DrawingDebuggerApp::DrawingDebuggerApp()
	:	BApplication("application/x.vnd-Haiku.DrawingDebugger")
{
	fWindow = new DrawingDebuggerWindow(BRect(200, 200, 999, 799));
	fWindow->Show();
}


DrawingDebuggerWindow::DrawingDebuggerWindow(BRect frame)
	:	BWindow(frame, "DrawingDebugger", B_TITLED_WINDOW,
			B_QUIT_ON_WINDOW_CLOSE)
{
	fView = new DrawingDebuggerView(frame.OffsetToSelf(0, 0));
	AddChild(fView);
}


DrawingDebuggerView::DrawingDebuggerView(BRect frame)
	:	BView(frame, "DrawingDebuggerView", B_FOLLOW_ALL, B_WILL_DRAW)
{
	fBitmap = new BBitmap(frame, B_RGB32, true);
	fOffscreenView= new BView(frame, "OffscreenView", B_FOLLOW_NONE, 0);
	fOffscreenView->SetViewColor(B_TRANSPARENT_32_BIT);
	fBitmap->AddChild(fOffscreenView);

	fStopListener = false;
	fListenerThread = spawn_thread(_PortListener, "port_listener",
		B_NORMAL_PRIORITY, this);
	resume_thread(fListenerThread);
}


DrawingDebuggerView::~DrawingDebuggerView()
{
	fStopListener = true;
	int32 returnCode = B_OK;
	wait_for_thread(fListenerThread, &returnCode);
	delete fBitmap;
}


void
DrawingDebuggerView::Draw(BRect updateRect)
{
	DrawBitmap(fBitmap, updateRect, updateRect);
}


int32
DrawingDebuggerView::_PortListener(void *data)
{
	DrawingDebuggerView *view = (DrawingDebuggerView *)data;
	port_id port = create_port(1000, "drawing_debugger_port");
	if (port < 0) {
		printf("failed to create port\n");
		return port;
	}

	size_t bufferSize = 1024;
	uint8 *buffer = (uint8 *)malloc(bufferSize);
	if (buffer == NULL)
		return B_NO_MEMORY;

	while (!view->fStopListener) {
		int32 code = 0;
		status_t result = read_port_etc(port, &code, buffer, bufferSize,
			B_RELATIVE_TIMEOUT, 100000);
		if (result == B_INTERRUPTED || result == B_TIMED_OUT)
			continue;
		if (result < B_OK) {
			printf("failed to read from port\n");
			return result;
		}

		switch (code) {
			case 'RECT':
			{
				BRect *rect = (BRect *)buffer;
				view->fBitmap->Lock();
				view->fOffscreenView->SetHighColor(random_color());
				view->fOffscreenView->FillRect(*rect, B_SOLID_HIGH);
				view->fOffscreenView->Sync();
				view->fBitmap->Unlock();

				view->LockLooper();
				view->Invalidate(*rect);
				view->UnlockLooper();
				break;
			}

			default:
				printf("unsupported code '%.4s'\n", (char *)&code);
				break;
		}
	}

	free(buffer);
	delete_port(port);
	return 0;
}


int
main(int argc, const char *argv[])
{
	DrawingDebuggerApp *app = new DrawingDebuggerApp();
	app->Run();
	delete app;
	return 0;
}