#include "stdafx.h"
#include "DeviceCairo.h"
#include "App.h"
#include "Window.h"
#include "RenderMgr.h"
#include "Exception.h"
#include "Gui/2D/Cairo/TextMgr.h"
#include "Gui/2D/Cairo/Surface.h"

#ifdef GUI_GTK

namespace gui {

	// Get the draw widget for a window:
	static GtkWidget *drawWidget(Engine &e, Handle handle) {
		Window *w = app(e)->findWindow(handle);
		if (!w)
			return handle.widget();
		else
			return w->drawWidget();
	}

	CairoDevice::CairoDevice(Engine &e) : GLDevice(e), myId(0) {}

	TextMgr *CairoDevice::createTextMgr() {
		return new CairoText();
	}

	Nat CairoDevice::id() {
		if (myId == 0)
			myId = renderMgr(e)->allocId();
		return myId;
	}

	Surface *CairoDevice::createSurface(Handle window, SurfaceType type) {
		if (type == surface2D) {
			return createCairoSurface(window);
		} else {
			return GLDevice::createSurface(window, type);
		}
	}

	Surface2D *CairoDevice::createSurface2D(GtkWidget *widget, Context *context) {
		// We should have intercepted the call earlier.
		throw new (e) GuiError(S("Should not be called."));
	}

	CairoSwDevice::CairoSwDevice(Engine &e) : CairoDevice(e) {}

	Surface *CairoSwDevice::createCairoSurface(Handle window) {
		int scale = gtk_widget_get_scale_factor(window.widget());
		Size size(gtk_widget_get_allocated_width(window.widget()) * scale,
				gtk_widget_get_allocated_height(window.widget()) * scale);
		cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, size.w, size.h);

		return new CairoBlitSurface(id(), size, scale, surface);
	}


	CairoGtkDevice::CairoGtkDevice(Engine &e) : CairoDevice(e) {}

	Surface *CairoGtkDevice::createCairoSurface(Handle window) {
		GdkWindow *win = gtk_widget_get_window(drawWidget(e, window));
		if (!win)
			return null;

		int scale = gtk_widget_get_scale_factor(window.widget());
		Size size(gtk_widget_get_allocated_width(window.widget()) * scale,
				gtk_widget_get_allocated_height(window.widget()) * scale);

		return new CairoBlitSurface(id(), size, scale,
									gdk_window_create_similar_surface(win, CAIRO_CONTENT_COLOR, int(size.w), int(size.h)));
	}

}

#endif
