void TileDownloader::downloadPicture(unsigned int index)
{
	const PictureInfo& info = mPictures[index];
	
	//Downloading all tiles in parallel
	{
		boost::threadpool::pool tp(info.tiles.size());
		for (unsigned int i=0; i<info.tiles.size(); ++i)
			tp.schedule(boost::bind(&TileDownloader::downloadPictureTile, this, index, i));
	}
	//compose all tiles on the canvas
	unsigned int width  = info.width;
	unsigned int height = info.height;
	Ogre::Canvas::Context* ctx = new Ogre::Canvas::Context(width, height, false);
	for (unsigned int i=0; i<info.tiles.size(); ++i)
	{
		const TileInfo& tileInfo = info.tiles[i];
		Ogre::Image img;
		std::stringstream filename;
		filename << tileInfo.j << "_" << tileInfo.i << ".jpg";
		img.load(filename.str(), Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);		
		float x = (tileInfo.i == 0) ? 0 : 509.0f + (tileInfo.i-1)*510.0f;
		float y = (tileInfo.j == 0) ? 0 : 509.0f + (tileInfo.j-1)*510.0f;
		ctx->drawImage(img, x, y);
	}
	
	//save canvas to jpeg
	ctx->saveToFile(info.filePath);

	delete ctx;
}
void OgreAppLogic::emptyCanvas()
{
	Ogre::Canvas::Context* ctx = mContext;
	ctx->save();
	ctx->fillStyle(Ogre::ColourValue::White);
	ctx->fillRect(0, 0, 150, 200);
	ctx->fillStyle(Ogre::ColourValue::Black);
	ctx->restore();
	mTexture->uploadTexture();
}
//Adapted from BetaCairo demo : http://www.ogre3d.org/forums/viewtopic.php?t=26987 (created by betajaen)
void OgreAppLogic::updateClock2Canvas()
{
	Chrono chrono(true);

	time_t now = time(NULL);
	struct tm * timeinfo;
	timeinfo = localtime(&now);
	float sec  = (float) timeinfo->tm_sec;
	float min  = (float) timeinfo->tm_min;
	float hour = (float) timeinfo->tm_hour;

	float clockSize = 150.0f;
	float clockUpdate = 0.125f;

	Ogre::Canvas::Context* ctx = mCanvasTextureClock2->getContext();
	Ogre::ColourValue tomato     = Ogre::Canvas::ColourConverter::fromHexa("#ff6347");
	Ogre::ColourValue whitesmoke = Ogre::Canvas::ColourConverter::fromHexa("#f5f5f5");

	// Basic bits:

		// Paint the Drawing with a tomatoes, this pretty much wipes over the previous drawing.
		ctx->fillStyle(tomato);
		ctx->fillRect(0, 0, clockSize, clockSize);

		// Draw a outline around the texture, using the whitesmoke colour and a line thickness of 1 pixel
		ctx->strokeStyle(whitesmoke);
		ctx->lineWidth(1.0f);
		ctx->strokeRect(0, 0, clockSize, clockSize);

		// Path out an arc (semi or full circle)
		ctx->fillStyle(whitesmoke);
		ctx->arc(clockSize / 2.0f, clockSize / 2.0f, clockSize / 4.0f, 0.0f, 360.0f, false);
		ctx->fill();

	// The Hour hand:

		ctx->lineCap(Ogre::Canvas::LineCap_Round);
		ctx->strokeStyle(tomato);
		ctx->lineWidth(3.0f);
		ctx->moveTo(clockSize / 2.0f, clockSize / 2.0f); // Move to the center of the image

		// Using a simple bit of trig. path the hour hand from the center to the correct hour, using a length of 1/5th of the imagesize.
		ctx->lineTo((clockSize / 2.0f) + (Ogre::Math::Sin(hour * Ogre::Math::PI / 6.0f) * (clockSize / 5.0f)), (clockSize / 2.0f) + (-Ogre::Math::Cos(hour * Ogre::Math::PI / 6.0f) * (clockSize / 5.0f)));
		ctx->stroke();


	// The Minute hand:
		
		ctx->beginPath();
		ctx->moveTo(clockSize / 2.0f, clockSize / 2.0f); // Move to the center of the image

		// Now draw the hour hand, using a length of 1/6th of the imagesize.
		ctx->lineTo((clockSize / 2) + (Ogre::Math::Sin((min + (sec / 60.0f)) * Ogre::Math::PI / 30.0f) * (clockSize / 6.0f)), (clockSize / 2) + (-Ogre::Math::Cos((min + (sec / 60.0f)) * Ogre::Math::PI / 30.0f) * (clockSize / 6.0f)));
		ctx->stroke();
		ctx->lineWidth(2.0f);
		ctx->strokeStyle(whitesmoke);
		ctx->stroke();

		// The second hand, and previous seconds:

			ctx->lineWidth(1.5f);		
			Ogre::ColourValue c = whitesmoke;

			int lastSecond = (int) Ogre::Math::Ceil(sec);
			float a = 1.0f / sec;

			// For each previous second, draw it out, with a subtle fade (alpha). The alpha decreases based how close it is to the current second.
			for (int i=0; i<lastSecond; i++) 
			{
				ctx->strokeStyle(Ogre::ColourValue(c.r, c.g, c.b, a*i));
				ctx->moveTo((clockSize / 2)  + (Ogre::Math::Sin(i * Ogre::Math::PI / 30.0f) * (clockSize / 4.0f) ),  (clockSize / 2.0f)  + (-Ogre::Math::Cos(i * Ogre::Math::PI / 30.0f) * (clockSize / 4.0f)));
				ctx->lineTo((clockSize / 2)  + (Ogre::Math::Sin(i * Ogre::Math::PI / 30.0f) * (clockSize / 3.5f) ) , (clockSize / 2.0f)  + (-Ogre::Math::Cos(i * Ogre::Math::PI / 30.0f) * (clockSize / 3.5f)));
				ctx->stroke();
			}

		// Draw the main second.

			ctx->strokeStyle(whitesmoke);
			ctx->moveTo((clockSize / 2.0f)  + (Ogre::Math::Sin(sec * Ogre::Math::PI / 30.0f) * (clockSize / 4.0f) ),  (clockSize / 2.0f)  + (-Ogre::Math::Cos(sec * Ogre::Math::PI / 30.0f) * (clockSize / 4.0f)));
			ctx->lineTo((clockSize / 2.0f)  + (Ogre::Math::Sin(sec * Ogre::Math::PI / 30.0f) * (clockSize / 3.5f) ) , (clockSize / 2.0f)  + (-Ogre::Math::Cos(sec * Ogre::Math::PI / 30.0f) * (clockSize / 3.5f)));
			ctx->stroke();

		// Outer ring:

			ctx->strokeStyle(whitesmoke);		
			ctx->arc((clockSize / 2.0f),(clockSize / 2.0f), (clockSize / 3.5f), 0.0f, 360.0f, false); // Path out an arc, from the center, for a radius of 1/3.5th of the image
			ctx->stroke();

		// The 12:

			// Path and Stroke "12"
			ctx->fillText("12", (clockSize / 2.0f)-8, (clockSize / 5.0f));

	double renderTime = chrono.getTimeElapsed();
	mCanvasTextureClock2->uploadTexture();
	double uploadTime = chrono.getTimeElapsed()-renderTime;
	std::cout << "clock2 render: " << renderTime << "ms, upload: " << uploadTime << "ms" <<std::endl;
}
void OgreAppLogic::updateSunCanvas()
{
	Ogre::Canvas::Context* ctx = mCanvasTextureSun->getContext();

	//ctx->globalCompositeOperation(Ogre::Canvas::DrawingOperator_DestOver);
	ctx->clearRect(0, 0, 300, 300); // clear canvas  
	ctx->fillStyle(Ogre::ColourValue::Black);
	ctx->fillRect(0, 0, 300, 300);
	ctx->fillStyle(Ogre::ColourValue(0.0f, 0.0f, 0.0f, 0.4f));
	ctx->strokeStyle(Ogre::Canvas::ColourConverter::fromRGBA(0, 153, 255, 102));
	ctx->save();  
	ctx->translate(150, 150);  

	// Earth  
	time_t now = time(NULL);
	struct tm * timeinfo;
	timeinfo = localtime(&now);
	int sec = timeinfo->tm_sec;
	int min = timeinfo->tm_min;
	int hr = timeinfo->tm_hour;

	ctx->rotate( ((2*Ogre::Math::PI)/60)*sec);// + ((2*Math.PI)/60000)*time.getMilliseconds() );  
	ctx->translate(105,0);  
	ctx->fillRect(0,-12,50,24); // Shadow  
	ctx->drawImage(mEarth, -12.0f, -12.0f);  

	// Moon  
	ctx->save();  
	ctx->rotate( ((2*Ogre::Math::PI)/6)*sec);// + ((2*Math.PI)/6000)*time.getMilliseconds() );  
	ctx->translate(0.0f, 28.5f);  
	ctx->drawImage(mMoon, -3.5f, -3.5f);  
	ctx->restore();  

	ctx->restore();  

	ctx->beginPath();  
	ctx->arc(150, 150, 105, 0, Ogre::Math::PI*2, false); // Earth orbit  
	ctx->stroke();  

	ctx->drawImage(mSun, 0.0f, 0.0f, 300.0f, 300.0f); 

	mCanvasTextureSun->uploadTexture();
}
void OgreAppLogic::updateClock1Canvas()
{
	Chrono chrono(true);
	Ogre::Canvas::Context* ctx = mCanvasTextureClock1->getContext();

	ctx->save();		
	ctx->clearRect(0, 0, 150, 150);
	ctx->strokeStyle(Ogre::ColourValue::Black);
	ctx->fillStyle(Ogre::ColourValue::White);
	ctx->fillRect(0, 0, 150, 150);
	ctx->translate(75, 75);
	ctx->scale(0.4f, 0.4f);
	ctx->rotate(-Ogre::Math::PI/2.0f);
	ctx->lineWidth(8);
	ctx->lineCap(Ogre::Canvas::LineCap_Round);

	// Hour marks
	ctx->save();
	for (float i=0; i<12; i++)
	{
		ctx->beginPath();
		ctx->rotate(Ogre::Math::PI/6.0f);
		ctx->moveTo(100, 0);
		ctx->lineTo(120, 0);
		ctx->stroke();
	}
	ctx->restore();

	// Minute marks
	ctx->save();
	ctx->lineWidth(5);
	for (int i=0; i<60; i++)
	{
		if (i%5!=0) 
		{
			ctx->beginPath();
			ctx->moveTo(117, 0);
			ctx->lineTo(120, 0);
			ctx->stroke();
		}
		ctx->rotate(Ogre::Math::PI/30);
	}
	ctx->restore();

	time_t now = time(NULL);
	struct tm * timeinfo;
	timeinfo = localtime(&now);
	int sec = timeinfo->tm_sec;
	int min = timeinfo->tm_min;
	int hr = timeinfo->tm_hour;
	hr = hr>=12 ? hr-12 : hr;

	ctx->fillStyle(Ogre::ColourValue::Black);

	// write Hours
	ctx->save();
	ctx->rotate( hr*(Ogre::Math::PI/6) + (Ogre::Math::PI/360)*min + (Ogre::Math::PI/21600)*sec );
	ctx->lineWidth(14);
	ctx->beginPath();
	ctx->moveTo(-20, 0);
	ctx->lineTo(80, 0);
	ctx->stroke();
	ctx->restore();

	// write Minutes
	ctx->save();
	ctx->rotate( (Ogre::Math::PI/30)*min + (Ogre::Math::PI/1800)*sec );
	ctx->lineWidth(10);
	ctx->beginPath();
	ctx->moveTo(-28, 0);
	ctx->lineTo(112, 0);
	ctx->stroke();
	ctx->restore();

	// Write seconds
	ctx->save();
	ctx->rotate(sec * Ogre::Math::PI/30);
	ctx->strokeStyle(Ogre::Canvas::ColourConverter::fromHexa("#D40000")); //red
	ctx->fillStyle(Ogre::Canvas::ColourConverter::fromHexa("#D40000")); //red
	ctx->lineWidth(6);
	ctx->beginPath();
	ctx->moveTo(-30, 0);
	ctx->lineTo(83, 0);
	ctx->stroke();
	ctx->beginPath();
	ctx->arc(0, 0, 10, 0, Ogre::Math::PI*2, true);
	ctx->fill();
	ctx->beginPath();
	ctx->arc(95, 0, 10, 0, Ogre::Math::PI*2, true);
	ctx->stroke();
	ctx->fillStyle(Ogre::Canvas::ColourConverter::fromHexa("#555")); //grey dark
	ctx->arc(0, 0, 3, 0, Ogre::Math::PI*2, true);
	ctx->fill();
	ctx->restore();

	ctx->beginPath();
	ctx->lineWidth(14);
	ctx->strokeStyle(Ogre::Canvas::ColourConverter::fromHexa("#325FA2")); //blue dark
	ctx->arc(0, 0, 142, 0, Ogre::Math::PI*2, true);
	ctx->stroke();

	ctx->restore();
	double renderTime = chrono.getTimeElapsed();
	mCanvasTextureClock1->uploadTexture();
	double uploadTime = chrono.getTimeElapsed()-renderTime;
	std::cout << "clock1 render: " << renderTime << "ms, upload: " << uploadTime << "ms" <<std::endl;
}