bool VisualTextureContainer::initWithARGBPixelData(PixelColor* argbPixels, size_t imageWidth, size_t imageHeight, bool debug) {
	
	bool success = true;
	
	this->imageRect.width = imageWidth;
	this->imageRect.height = imageHeight;
	
	VisualGraphics* theVisualGraphics = VisualGraphics::getInstance();
	this->useRectExtension = theVisualGraphics->canUseTextureRectExtension();
	if (this->useRectExtension == false) {
		this->textureRect.width = theVisualGraphics->power2Ceiling(this->imageRect.width);
		this->textureRect.height = theVisualGraphics->power2Ceiling(this->imageRect.height);
	} else {
		this->textureRect.width = this->imageRect.width;
		this->textureRect.height = this->imageRect.height;
	}
	
	this->textureName = theVisualGraphics->getNextFreeTextureName();
	this->aTextureIsSet = true;
	VisualTextureContainer::textureRefCountMap[this->textureName] = 1;
	
	success = theVisualGraphics->copyARGBBitmapDataToTexture(this->textureName, this->imageRect.width, this->imageRect.height, this->useRectExtension, const_cast<const uint32**>(&(argbPixels)), debug);
	
	if (this->useRectExtension == false) {
		this->logicalSize.width = (double)this->imageRect.width / (double)this->textureRect.width;
		this->logicalSize.height = (double)this->imageRect.height / (double)this->textureRect.height;
	} else {
		this->logicalSize.width = (double)this->textureRect.width;
		this->logicalSize.height = (double)this->textureRect.height;
	}
	
	return success;
}
VisualTextureContainer::VisualTextureContainer(UInt32 anImageWidth, UInt32 anImageHeight, bool useRectExtensionBool) {
	textureIsSet = false;
	textureName = 0;
	imageWidth = anImageWidth;
	imageHeight = anImageHeight;
	useRectExtension = useRectExtensionBool;
	if (useRectExtensionBool == false) {
		VisualGraphics* theVisualGraphics = VisualGraphics::getInstance();
		textureWidth = theVisualGraphics->power2Ceiling(imageWidth);
		textureHeight = theVisualGraphics->power2Ceiling(imageHeight);
		textureLogicalWidth = (double)imageWidth / (double)textureWidth;
		textureLogicalHeight = (double)imageHeight / (double)textureHeight;
	} else {
		textureWidth = imageWidth;
		textureHeight = imageHeight;
		textureLogicalWidth = (double)textureWidth;
		textureLogicalHeight = (double)textureHeight;
	}
	pixelFormat = kGL_BGRA;
#if __BIG_ENDIAN__
	dataType = kGL_UNSIGNED_INT_8_8_8_8_REV;
#else
#if TARGET_OS_WIN
	dataType = kGL_UNSIGNED_BYTE;
#else
	dataType = kGL_UNSIGNED_INT_8_8_8_8;
#endif
#endif
	pixelBuffer = NULL;
}
OSStatus VisualTextureContainer::initWithURL(VisualString& anURL) {

	this->releaseTextureData();
	if (this->pixelBuffer != NULL) {
		free(this->pixelBuffer);
		this->pixelBuffer = NULL;
	}

	OSStatus osStatus = noErr;
	
	CFURLRef imageURL = CFURLCreateWithString(kCFAllocatorDefault, anURL.getCharactersPointer(), NULL);
	CGImageSourceRef imageSource = CGImageSourceCreateWithURL(imageURL, NULL);
	CGImageRef imageRef = CGImageSourceCreateImageAtIndex(imageSource, 0, NULL);
	this->imageWidth = CGImageGetWidth(imageRef);
	this->imageHeight = CGImageGetHeight(imageRef);
	VisualGraphics* theVisualGraphics = VisualGraphics::getInstance();
	this->useRectExtension = theVisualGraphics->canUseTextureRectExtension();
	if (this->useRectExtension == false) {
		this->textureWidth = theVisualGraphics->power2Ceiling(this->imageWidth);
		this->textureHeight = theVisualGraphics->power2Ceiling(this->imageHeight);
	} else {
		this->textureWidth = this->imageWidth;
		this->textureHeight = this->imageHeight;
	}
	CGContextRef context = theVisualGraphics->createBitmapContext(this->textureWidth, this->textureHeight);

	CGContextTranslateCTM(context, 0.0, (float)this->textureHeight + (float)(this->textureHeight - this->imageHeight));
	CGContextScaleCTM(context, 1.0, -1.0);

	CGRect rect = CGRectMake(0, (this->textureHeight - this->imageHeight), this->imageWidth, this->imageHeight);
	CGContextDrawImage(context, rect, imageRef);

	this->pixelBuffer = static_cast<UInt32*>(CGBitmapContextGetData(context));

	this->textureName = theVisualGraphics->getNextFreeTextureName();
	this->textureIsSet = true;
	VisualTextureContainer::textureRefCountMap[this->textureName] = 1;
	theVisualGraphics->copyARGBBitmapDataToTexture(this->textureName, this->textureWidth, this->textureHeight, this->useRectExtension, this->pixelFormat, this->dataType, const_cast<const UInt32**>(&(this->pixelBuffer)));

	CGContextRelease(context);
	if (this->pixelBuffer) {
		free(this->pixelBuffer);
		this->pixelBuffer = NULL;
	}
	CGImageRelease(imageRef);

	if (this->useRectExtension == false) {
		this->textureLogicalWidth = (double)this->imageWidth / (double)this->textureWidth;
		this->textureLogicalHeight = (double)this->imageHeight / (double)this->textureHeight;
	} else {
		this->textureLogicalWidth = (double)this->textureWidth;
		this->textureLogicalHeight = (double)this->textureHeight;
	}

	return osStatus;

}
bool VisualTextureContainer::initWithFramebuffer(const BottomLeftPositionedPixelRect& clipRect) {
	
	bool success = true;

	uint16 dataType;
	uint16 pixelFormat = kGL_BGRA;
	// BGRA on intel machines and ARGB on ppc
#if TARGET_OS_WIN
	dataType = kGL_UNSIGNED_BYTE;
#else
#if __BIG_ENDIAN__
	dataType = kGL_UNSIGNED_INT_8_8_8_8_REV;
#else
	dataType = kGL_UNSIGNED_INT_8_8_8_8;
#endif
#endif
	
	VisualGraphics* theVisualGraphics = VisualGraphics::getInstance();
	
	this->releaseTextureData();
	
	this->textureName = theVisualGraphics->getNextFreeTextureName();
	this->aTextureIsSet = true;
	VisualTextureContainer::textureRefCountMap[this->textureName] = 1;
	this->useRectExtension = theVisualGraphics->canUseTextureRectExtension();
	
	int prevReadBuffer = theVisualGraphics->getCurrentColorBufferForPixelReadingOperations();
	theVisualGraphics->setColorBufferForPixelReadingOperations(kGL_BACK_COLOR_BUFFER);
	
	int prevDrawBuffer = theVisualGraphics->getCurrentColorBufferForPixelDrawingOperations();
	theVisualGraphics->setColorBufferForPixelDrawingOperations(kGL_BACK_COLOR_BUFFER);
	
	theVisualGraphics->enableTexturing(this->useRectExtension);
	theVisualGraphics->copyFramebufferToTexture(this->textureName, this->useRectExtension, clipRect, pixelFormat, dataType);
	theVisualGraphics->disableTexturing(this->useRectExtension);
	
	theVisualGraphics->setColorBufferForPixelDrawingOperations(prevDrawBuffer);
	theVisualGraphics->setColorBufferForPixelReadingOperations(prevReadBuffer);
	
	this->imageRect.width = clipRect.pixelRect.width;
	this->imageRect.height = clipRect.pixelRect.height;
	
	this->useRectExtension = theVisualGraphics->canUseTextureRectExtension();
	if (this->useRectExtension == false) {
		this->textureRect.width = theVisualGraphics->power2Ceiling(this->imageRect.width);
		this->textureRect.height = theVisualGraphics->power2Ceiling(this->imageRect.height);
	} else {
		this->textureRect.width = this->imageRect.width;
		this->textureRect.height = this->imageRect.height;
	}
	
	return success;
}
bool VisualTextureContainer::initWithStyledString(VisualStyledString& styledString) {
	
	this->releaseTextureData();
	
    bool success = true;
	
	const VisualString* aVisualString = &(styledString);
	VisualStringStyle& stringStyle = styledString.getStyle();
	if (aVisualString->getNumberOfCharacters() == 0) {
		return false;
	}
	
	VisualGraphics* theVisualGraphics = VisualGraphics::getInstance();
	uint32 maxPixelWidth = theVisualGraphics->getCanvasPixelWidth();
	uint32 maxPixelHeight = theVisualGraphics->getCanvasPixelHeight();
	
	this->textureName = theVisualGraphics->getNextFreeTextureName();
	this->aTextureIsSet = true;
	VisualTextureContainer::textureRefCountMap[this->textureName] = 1;
	this->useRectExtension = theVisualGraphics->canUseTextureRectExtension();
	
#if TARGET_OS_MAC
	char alignmentStr[32];	
	switch (stringStyle.horizontalAlignment) {
		case (kLeftAligned):
			strcpy(alignmentStr, "left");
			break;
		case(kCenterAligned):
			strcpy(alignmentStr, "center");
			break;
		case(kRightAligned):
			strcpy(alignmentStr, "right");
			break;
		default:
			break;
	}
	
	success = getDimensionsOfCocoaStringBitmap((void*)aVisualString, (void*)&stringStyle, &(this->imageRect.width), &(this->imageRect.height), maxPixelWidth, maxPixelHeight, alignmentStr);
	if (!success) {
		return success;
	}
	
	if (this->useRectExtension == false) {
		this->textureRect.width = theVisualGraphics->power2Ceiling(this->imageRect.width);
		this->textureRect.height = theVisualGraphics->power2Ceiling(this->imageRect.height);
	} else {
		this->textureRect.width = this->imageRect.width;
		this->textureRect.height = this->imageRect.height;
	}
	
	PixelColor* pixelBuffer = (uint32*)calloc(this->textureRect.width * this->textureRect.height, sizeof(uint32));
	
	success = getCocoaStringBitmapData((void*)&styledString, this->textureRect.width, this->textureRect.height, alignmentStr, &(pixelBuffer));
	
	success = theVisualGraphics->copyARGBBitmapDataToTexture(this->textureName, this->textureRect.width, this->textureRect.height, this->useRectExtension, const_cast<const uint32**>(&(pixelBuffer)));
	
#endif
	
#if TARGET_OS_WIN
	
	wchar_t* stringValueRef = (wchar_t*)(styledString.getCharactersPointer());
	uint8 red = (uint8)(stringStyle.fontColor.r * 255.0f);
	uint8 green = (uint8)(stringStyle.fontColor.g * 255.0f);
	uint8 blue = (uint8)(stringStyle.fontColor.b * 255.0f);

	if (!stringValueRef) {
		success = false;
		return success;
	}
	
	success = theVisualGraphics->makeTextureOfStringWin(stringValueRef, styledString.getNumberOfCharacters(), this->textureName, this->textureRect.width, this->textureRect.height, this->imageRect.width, this->imageRect.height, stringStyle.fontNameStr, (uint16)stringStyle.fontSize, red, green, blue, stringStyle.horizontalAlignment, maxPixelWidth, maxPixelHeight);
	
#endif
	
	if (this->useRectExtension == false) {
		this->logicalSize.width = (double)this->imageRect.width / (double)this->textureRect.width;
		this->logicalSize.height = (double)this->imageRect.height / (double)this->textureRect.height;
	} else {
		this->logicalSize.width = (double)this->textureRect.width;
		this->logicalSize.height = (double)this->textureRect.height;
	}
	
	return success;
}
bool VisualTextureContainer::initWithEncodedData(const char* const bufferData, size_t size) {
	
	bool success = true;
	bool debug = false;
	
	this->releaseTextureData();
	
	uint32* aPixelBuffer = NULL;
	
#if TARGET_OS_WIN
	
	HGLOBAL hGlobal = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD, (SIZE_T)size);
	if (!hGlobal)
		return false;
	
	BYTE* pDest = (BYTE*)::GlobalLock(hGlobal);
	
	memcpy(pDest, bufferData, size);
	
	::GlobalUnlock(hGlobal);
	
	IStream* pStream = NULL;
	if (::CreateStreamOnHGlobal(hGlobal, FALSE, &pStream) != S_OK)
		return false;
	
	Gdiplus::Bitmap* bitmap = Gdiplus::Bitmap::FromStream(pStream);
	bitmap->RotateFlip(Gdiplus::RotateNoneFlipY);
	
	this->imageRect.width = bitmap->GetWidth();
	this->imageRect.height = bitmap->GetHeight();
	
	VisualGraphics* theVisualGraphics = VisualGraphics::getInstance();
	this->useRectExtension = theVisualGraphics->canUseTextureRectExtension();
	if (this->useRectExtension == false) {
		this->textureRect.width = theVisualGraphics->power2Ceiling(this->imageRect.width);
		this->textureRect.height = theVisualGraphics->power2Ceiling(this->imageRect.height);
	} else {
		this->textureRect.width = this->imageRect.width;
		this->textureRect.height = this->imageRect.height;
	}
	
	aPixelBuffer = (uint32*)malloc(this->imageRect.width * this->imageRect.height * sizeof(uint32));
	Gdiplus::Rect rect(0, 0, this->imageRect.width, this->imageRect.height);
	Gdiplus::BitmapData* bitmapData = new Gdiplus::BitmapData;
	
	bitmapData->Width = this->imageRect.width;
	bitmapData->Height = this->imageRect.height;
	bitmapData->Stride = sizeof(uint32) * bitmapData->Width;
	bitmapData->PixelFormat = PixelFormat32bppARGB;
	bitmapData->Scan0 = (VOID*)aPixelBuffer;
	
	Gdiplus::Status status = Gdiplus::Ok;
	status = bitmap->LockBits(&rect, Gdiplus::ImageLockModeRead | Gdiplus::ImageLockModeUserInputBuf, PixelFormat32bppPARGB, bitmapData);
	
#endif
	
#if TARGET_OS_MAC
	
	CFDataRef dataRef = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (UInt8*)bufferData, (CFIndex)size, kCFAllocatorDefault);
	
	CFDictionaryRef options = NULL;
	CGImageSourceRef imageSourceRef = CGImageSourceCreateWithData(dataRef, options);
	
	CGImageRef imageRef = CGImageSourceCreateImageAtIndex(imageSourceRef, 0, options);
	
	this->imageRect.width = CGImageGetWidth(imageRef);
	this->imageRect.height = CGImageGetHeight(imageRef);
	
	VisualGraphics* theVisualGraphics = VisualGraphics::getInstance();
	this->useRectExtension = theVisualGraphics->canUseTextureRectExtension();
	if (this->useRectExtension == false) {
		this->textureRect.width = theVisualGraphics->power2Ceiling(this->imageRect.width);
		this->textureRect.height = theVisualGraphics->power2Ceiling(this->imageRect.height);
	} else {
		this->textureRect.width = this->imageRect.width;
		this->textureRect.height = this->imageRect.height;
	}
	
	CGContextRef contextPtr = theVisualGraphics->createBitmapContext(this->imageRect.width, this->imageRect.height);
	
	CGContextTranslateCTM(contextPtr, 0, this->imageRect.height);
	CGContextScaleCTM(contextPtr, 1.0f, -1.0f);
	
	CGRect rect = CGRectMake(0, 0, this->imageRect.width, this->imageRect.height);
	CGContextDrawImage(contextPtr, rect, imageRef);
	
	aPixelBuffer = static_cast<uint32*>(CGBitmapContextGetData(contextPtr));
#endif
	
	PixelColor* interleavedARGBColorPixelBuffer = NULL;
	
	if (debug == true) {
		interleavedARGBColorPixelBuffer = VisualColorTools::createARGBCheckPixels(this->textureRect.width, this->textureRect.height);
	} else {
		interleavedARGBColorPixelBuffer = static_cast<PixelColor*>(aPixelBuffer);
	}
	success = this->initWithARGBPixelData(interleavedARGBColorPixelBuffer, this->imageRect.width, this->imageRect.height);
	
#if TARGET_OS_MAC
	CGContextRelease(contextPtr);
	CGImageRelease(imageRef);
#endif
	
#if TARGET_OS_WIN
	bitmap->UnlockBits(bitmapData);
#endif
	
	return success;
	
}
OSStatus VisualTextureContainer::initWithString(const VisualString& stringValue, VisualStringStyle& stringStyle) {
	
	this->releaseTextureData();
	if (this->pixelBuffer != NULL) {
		free(this->pixelBuffer);
		this->pixelBuffer = NULL;
	}

    OSStatus status = noErr;

	VisualGraphics* theVisualGraphics = VisualGraphics::getInstance();
	UInt16 maxPixelWidth = theVisualGraphics->getCanvasPixelWidth();
	UInt16 maxPixelHeight = theVisualGraphics->getCanvasPixelHeight();
	
	this->textureName = theVisualGraphics->getNextFreeTextureName();
	this->textureIsSet = true;
	VisualTextureContainer::textureRefCountMap[this->textureName] = 1;
	this->useRectExtension = theVisualGraphics->canUseTextureRectExtension();

#if TARGET_OS_MAC
	char alignmentStr[32];	
	switch (stringStyle.horizontalAlignment) {
		case (kLeftAligned):
			strcpy(alignmentStr, "left");
			break;
		case(kCenterAligned):
			strcpy(alignmentStr, "center");
			break;
		case(kRightAligned):
			strcpy(alignmentStr, "right");
			break;
		default:
			break;
	}
	
	status = getDimensionsOfCocoaStringBitmap((void*)&stringValue, &(this->imageWidth), &(this->imageHeight), const_cast<char*>(stringStyle.fontNameStr), &(stringStyle.fontSize), stringStyle.fontColor.r, stringStyle.fontColor.g, stringStyle.fontColor.b, maxPixelWidth, maxPixelHeight, alignmentStr);
	
	if (this->useRectExtension == false) {
		this->textureWidth = theVisualGraphics->power2Ceiling(this->imageWidth);
		this->textureHeight = theVisualGraphics->power2Ceiling(this->imageHeight);
	} else {
		this->textureWidth = this->imageWidth;
		this->textureHeight = this->imageHeight;
	}
	
	this->pixelBuffer = (UInt32*)calloc(this->textureWidth * this->textureHeight, sizeof(UInt32));

	status = getCocoaStringBitmapData((void*)&stringValue, this->textureWidth, this->textureHeight, const_cast<char*>(stringStyle.fontNameStr), stringStyle.fontSize, stringStyle.fontColor.r, stringStyle.fontColor.g, stringStyle.fontColor.b, alignmentStr, &(this->pixelBuffer));
	
	theVisualGraphics->copyARGBBitmapDataToTexture(this->textureName, this->textureWidth, this->textureHeight, this->useRectExtension, this->pixelFormat, this->dataType, const_cast<const UInt32**>(&(this->pixelBuffer)));

#endif

#if TARGET_OS_WIN

	wchar_t* stringValueRef = (wchar_t*)stringValue.getCharactersPointer();
	UInt8 red = (UInt8)(stringStyle.fontColor.r * 255.0f);
	UInt8 green = (UInt8)(stringStyle.fontColor.g * 255.0f);
	UInt8 blue = (UInt8)(stringStyle.fontColor.b * 255.0f);
	
	status = theVisualGraphics->makeTextureOfStringWin(stringValueRef, stringValue.getNumberOfCharacters(), this->textureName, this->textureWidth, this->textureHeight, this->imageWidth, this->imageHeight, stringStyle.fontNameStr, (UInt16)stringStyle.fontSize, red, green, blue, stringStyle.horizontalAlignment, maxPixelWidth, maxPixelHeight);

#endif

	if (this->useRectExtension == false) {
		this->textureLogicalWidth = (double)this->imageWidth / (double)this->textureWidth;
		this->textureLogicalHeight = (double)this->imageHeight / (double)this->textureHeight;
	} else {
		this->textureLogicalWidth = (double)this->textureWidth;
		this->textureLogicalHeight = (double)this->textureHeight;
	}

	return status;
}
OSStatus VisualTextureContainer::initWithFile(const VisualFile& aFile, OSType fileType) {
	
	this->releaseTextureData();
	if (this->pixelBuffer != NULL) {
		free(this->pixelBuffer);
		this->pixelBuffer = NULL;
	}

	OSStatus status = noErr;
	char errLog[128];
	GraphicsImportComponent gi = 0;
	
	status = VisualQuickTime::getGraphicsImporterForFile(aFile, gi, fileType);
	if (status != noErr) {
		sprintf(errLog, "err %ld: after getGraphicsImporterForFile() in file: %s (line: %d) [%s])", status, __FILE__, __LINE__, __FUNCTION__);
		writeLog(errLog);
		return status;
	}
	
	status = VisualQuickTime::setMaxQuality(gi);
	if (status != noErr) {
		sprintf(errLog, "err %ld: after setMaxQuality() in file: %s (line: %d) [%s])", status, __FILE__, __LINE__, __FUNCTION__);
		writeLog(errLog);
		return status;
	}

	VisualQuickTime::getImageDimensions(gi, this->imageWidth, this->imageHeight);

	VisualGraphics* theVisualGraphics = VisualGraphics::getInstance();
	this->useRectExtension = theVisualGraphics->canUseTextureRectExtension();
	if (this->useRectExtension == false) {
		this->textureWidth = theVisualGraphics->power2Ceiling(this->imageWidth);
		this->textureHeight = theVisualGraphics->power2Ceiling(this->imageHeight);
	} else {
		this->textureWidth = this->imageWidth;
		this->textureHeight = this->imageHeight;
	}

	status = VisualQuickTime::flipImportMatrix(gi, this->imageWidth, this->imageHeight);
	if (status != noErr) {
		sprintf(errLog, "err %ld: flipImportMatrix", status);
		writeLog(errLog);
		return status;
	}

#if TARGET_OS_MAC	
	CGImageRef imageRef = VisualQuickTime::createCGImageRef(gi);
	if (imageRef == NULL) {
		char errStr[256];
		sprintf(errStr, "imageRef is NULL in file: %s (line: %d) [%s])", __FILE__, __LINE__, __FUNCTION__);
		writeLog(errStr);
		return NULL;
	}
	
	CGContextRef contextPtr = theVisualGraphics->createBitmapContext(this->textureWidth, this->textureHeight);

	CGRect rect = CGRectMake(0, (this->textureHeight - this->imageHeight), this->imageWidth, this->imageHeight);
	CGContextDrawImage(contextPtr, rect, imageRef);

	this->pixelBuffer = static_cast<UInt32*>(CGBitmapContextGetData(contextPtr));
#endif

#if TARGET_OS_WIN
	this->pixelBuffer = VisualQuickTime::getBitmapOfDrawing(gi, this->textureWidth, this->textureHeight);
#endif

	CloseComponent(gi);

	this->textureName = theVisualGraphics->getNextFreeTextureName();
	this->textureIsSet = true;
	VisualTextureContainer::textureRefCountMap[this->textureName] = 1;
#if TARGET_OS_WIN
	theVisualGraphics->copyARGBBitmapDataToTexture(this->textureName, this->textureWidth, this->textureHeight, this->useRectExtension, this->pixelFormat, kGL_UNSIGNED_BYTE, const_cast<const UInt32**>(&(this->pixelBuffer)));
#endif
#if TARGET_OS_MAC
	theVisualGraphics->copyARGBBitmapDataToTexture(this->textureName, this->textureWidth, this->textureHeight, this->useRectExtension, this->pixelFormat, this->dataType, const_cast<const UInt32**>(&(this->pixelBuffer)));
#endif

#if TARGET_OS_WIN
	if (this->pixelBuffer != NULL) {
		free(this->pixelBuffer);
		this->pixelBuffer = NULL;
	}
#endif

#if TARGET_OS_MAC
	CGContextRelease(contextPtr);
	if (this->pixelBuffer != NULL) {
		free(this->pixelBuffer);
		this->pixelBuffer = NULL;
	}
	CGImageRelease(imageRef);	
#endif

	if (this->useRectExtension == false) {
		this->textureLogicalWidth = (double)this->imageWidth / (double)this->textureWidth;
		this->textureLogicalHeight = (double)this->imageHeight / (double)this->textureHeight;
	} else {
		this->textureLogicalWidth = (double)this->textureWidth;
		this->textureLogicalHeight = (double)this->textureHeight;
	}

	return status;
}