void CzBitmapSprite::setColour(int index, const CzColour& colour)
{
	if (Geometry == NULL)
		Prim->Colours[index] = colour.get();
	else
	{
		if (Geometry->Colours == NULL)
			Prim->Colours[index] = colour.get();
		else
		{
			Prim->Colours[index].r = (uint8)(((int)Geometry->Colours[index].r * colour.r) / 255);
			Prim->Colours[index].g = (uint8)(((int)Geometry->Colours[index].g * colour.g) / 255);
			Prim->Colours[index].b = (uint8)(((int)Geometry->Colours[index].b * colour.b) / 255);
			Prim->Colours[index].a = (uint8)(((int)Geometry->Colours[index].a * colour.a) / 255);
		}
	}
}
// BatchDrawPrims - Currently only supports batching of Quad lists
void CzPlatformRender::BatchDrawPrims(bool filter)
{
	if (NextMaterial == 0)
		return;

	// Allocate memory from data cache for verts, UV's and colours
	for (int t = 0; t < NextMaterial; t++)
	{
		int prim_count = MaterialUsedCounts[t] * 4;
		BatchVerts[t] = IW_GX_ALLOC(CzVec2, prim_count);
		BatchUVs[t] = IW_GX_ALLOC(CzVec2, prim_count);
		BatchColours[t] = IW_GX_ALLOC(CzColour, prim_count);
		BatchIndices[t] = IW_GX_ALLOC(uint16, prim_count);
	}

	// Populate the data cache
	CzRenderPrim** prims = Primitives;
	for (int t = 0; t < NextPrimitive; t++)
	{
		CzRenderPrim *prim = *prims;
		int mat_id = prim->MaterialID;
		int idx = MaterialIndices[mat_id];
		CzVec2* v = BatchVerts[mat_id] + idx;
		CzVec2* uv = BatchUVs[mat_id] + idx;
		CzColour* c = BatchColours[mat_id] + idx;
		uint16* i = BatchIndices[mat_id] + idx;
		for (int t2 = 0; t2 < 4; t2++)
		{
			v->x = (prim->Verts + t2)->x;
			v->y = (prim->Verts + t2)->y;
			uv->x = (prim->UVs + t2)->x;
			uv->y = (prim->UVs + t2)->y;
			c->set(*(prim->Colours + t2));
			v++; uv++; c++;
		}
// TODO: ERROR - Does not work with batched ngon
		*i++ = idx;
		*i++ = idx + 3;
		*i++ = idx + 2;
		*i++ = idx + 1;
		MaterialIndices[mat_id] += 4;
		prims++;
	}

	// Render batched streams
	CzRenderMaterial** mats = Materials;
	for (int t = 0; t < NextMaterial; t++)
	{
		int count = MaterialUsedCounts[t] * 4;
		IwGxSetUVStream((CIwFVec2*)BatchUVs[t], 0);
		IwGxSetVertStreamScreenSpace((CIwFVec2*)BatchVerts[t], count);
		IwGxSetColStream((CIwColour*)(BatchColours[t]), count);
		IwGxSetNormStream(NULL);
		CIwMaterial* mat = IW_GX_ALLOC_MATERIAL();
		CIwTexture* texture = static_cast<CIwTexture*>((*mats)->Image->getTexture());
		mat->SetTexture(texture);
		mat->SetDepthWriteMode(CIwMaterial::DEPTH_WRITE_DISABLED);
		mat->SetClamping(false);
		mat->SetFiltering(filter);
		mat->SetAlphaMode(CIwMaterial::ALPHA_BLEND);
		mat->SetCullMode(CIwMaterial::CULL_BACK);
//		mat->SetCullMode(CIwMaterial::CULL_NONE);
		IwGxSetMaterial(mat);
		IwGxDrawPrims(IW_GX_QUAD_LIST, BatchIndices[t], count);
		mats++;
	}

	// Reset batch pointers
	for (int t = 0; t < NextMaterial; t++)
		MaterialUsedCounts[t] = 0;
	for (int t = 0; t < NextMaterial; t++)
		MaterialIndices[t] = 0;
	NextPrimitive = 0;
	NextMaterial = 0;
}
void CzPlatformRender::DrawText(CzFontPreparedText prepared_text, CzFont* font, CzMatrix3* transform, const CzColour& colour, CzVec4& skew, bool filter, eCzAlphaMode alpha_mode)
{
	CIwMaterial::AlphaMode am = (CIwMaterial::AlphaMode)alpha_mode; // TODO Add proper method map Marmalade Alpha mode to Marmalade

	// Cache the transform
	float m00 = transform->m[0][0];
	float m01 = transform->m[0][1];
	float m10 = transform->m[1][0];
	float m11 = transform->m[1][1];
	float tx = transform->getX();
	float ty = transform->getY();
	float sx1 = (float)skew.x;
	float sx2 = (float)skew.y;
	float sy1 = (float)skew.z;
	float sy2 = (float)skew.w;
/*	CzIRect clip = ScreenClipRect;
	clip.x <<= 3;
	clip.y <<= 3;
	clip.w = clip.x + (clip.w << 3);
	clip.h = clip.y + (clip.h << 3);*/

	IwGxLightingOn();
	IwGxSetColStream(NULL);
	IwGxSetNormStream(NULL);

	CIwGxFont* mfont = static_cast<CIwGxFont*>(font->getFontHandle());
	CIwGxFontPreparedData* prep_text = static_cast<CIwGxFontPreparedData*>(prepared_text);

	// A font can consist of multiple materials so we need to process all of them
	for (int t = 0; t < mfont->GetNumberMaterials(); t++)
	{
		// Set UV stream
		uint32* char_ids;
		int num_chars = IwGxFontSetUVs(*prep_text, -1, t, &char_ids);

		// Generate transformed vertices from glyphs
		int nv = num_chars << 2;
		CzVec2* pVerts = IW_GX_ALLOC(CzVec2, nv);
		CzVec2* pVert = pVerts;
		if (m01 == 0 && m10 == 0)
		{
			// No rotation optimisation
			for (int t2 = 0; t2 < num_chars; t2++)
			{
				CIwRect rc = prep_text->GetCharacterArea(char_ids[t2]);
				float x1 = (float)rc.x;
				float y1 = (float)rc.y;
				float x2 = x1 + (float)rc.w;
				float y2 = y1 + (float)rc.h;
				float ax = (m00 * x1) + tx;
				float ay = (m11 * y1) + ty;
				float bx = (m00 * x2) + tx;
				float by = (m11 * y2) + ty;

//				if ((ax < clip.w && bx >= clip.x) && (ay < clip.h && by >= clip.y))
//				{
					pVert->x = ax + sx1;
					pVert->y = ay + sy1;
					pVert++;
					pVert->x = ax - sx1;
					pVert->y = by + sy2;
					pVert++;
					pVert->x = bx - sx2;
					pVert->y = by - sy2;
					pVert++;
					pVert->x = bx + sx2;
					pVert->y = ay - sy1;
					pVert++;
//				}
			}
		}
		else
		{
			for (int t2 = 0; t2 < num_chars; t2++)
			{
				CIwRect rc = prep_text->GetCharacterArea(char_ids[t2]);
				float x1 = (float)rc.x;
				float y1 = (float)rc.y;
				float x2 = x1 + (float)rc.w;
				float y2 = y1 + (float)rc.h;
				pVert->x = (m00 * x1 + m10 * y1 + tx + sx1);
				pVert->y = (m01 * x1 + m11 * y1 + ty + sy1);
				pVert++;
				pVert->x = (m00 * x1 + m10 * y2 + tx - sx1);
				pVert->y = (m01 * x1 + m11 * y2 + ty + sy2);
				pVert++;
				pVert->x = (m00 * x2 + m10 * y2 + tx - sx2);
				pVert->y = (m01 * x2 + m11 * y2 + ty - sy2);
				pVert++;
				pVert->x = (m00 * x2 + m10 * y1 + tx + sx2);
				pVert->y = (m01 * x2 + m11 * y1 + ty - sy1);
				pVert++;
			}
		}

		if (nv > 0)
		{
			// Set vertex stream
			IwGxSetVertStreamScreenSpace((CIwFVec2*)pVerts, nv);

			// Create a material
			CIwMaterial* mat = IW_GX_ALLOC_MATERIAL();
			mat->Copy(*IwGxFontGetFont()->GetMaterial(t));
			mat->SetDepthWriteMode(CIwMaterial::DEPTH_WRITE_DISABLED);
			mat->SetColEmissive(colour.get());
			mat->SetClamping(true);
			mat->SetFiltering(filter);
			mat->SetAlphaMode(am);
			mat->SetCullMode(CIwMaterial::CULL_BACK);
//			mat->SetCullMode(CIwMaterial::CULL_NONE);
			IwGxSetMaterial(mat);

			// Finally draw the glyphs
			IwGxDrawPrims(IW_GX_QUAD_LIST, NULL, nv);

			CurrentAlphaMode = alpha_mode;
		}
	}
	IwGxLightingOff();
	CurrentTexture = NULL;
}