<commit_before>#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

internal ImTextureID LoadAndBindImage(char* Path)
{
	uint8* Image;
	int32 ImageWidth, ImageHeight, ComponentsPerPixel;
	Image = stbi_load(Path, &ImageWidth, &ImageHeight, &ComponentsPerPixel, 0);

	// Create texture
	GLuint Id_GLuint;
	glGenTextures(1, &Id_GLuint);
	glBindTexture(GL_TEXTURE_2D, Id_GLuint);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ImageWidth, ImageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, Image);

	// Store our identifier
	free(Image);
	return (void *)(intptr_t)Id_GLuint;
}

internal void LoadImageIntoDocument(char* Path, PapayaDocument* Document)
{
	Document->Texture = stbi_load(Path, &Document->Width, &Document->Height, &Document->ComponentsPerPixel, 0);

	// Create texture
	glGenTextures(1, &Document->TextureID);
	glBindTexture(GL_TEXTURE_2D, Document->TextureID);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, Document->Width, Document->Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, Document->Texture);
}

void Papaya_Initialize(PapayaMemory* Memory)
{
	// Texture IDs
	Memory->InterfaceTextureIDs[PapayaInterfaceTexture_TitleBarButtons] = (uint32)LoadAndBindImage("../../img/win32_titlebar_buttons.png");
	Memory->InterfaceTextureIDs[PapayaInterfaceTexture_TitleBarIcon] = (uint32)LoadAndBindImage("../../img/win32_titlebar_icon.png");
	Memory->InterfaceTextureIDs[PapayaInterfaceTexture_InterfaceIcons] = (uint32)LoadAndBindImage("../../img/interface_icons.png");

	// Colors
#if 1
	Memory->InterfaceColors[PapayaInterfaceColor_Clear]			= Color(45,45,48); // Dark grey
#else
	Memory->InterfaceColors[PapayaInterfaceColor_Clear]			= Color(114,144,154); // Light blue
#endif
	Memory->InterfaceColors[PapayaInterfaceColor_Transparent]	= Color(0,0,0,0);
	Memory->InterfaceColors[PapayaInterfaceColor_ButtonHover]	= Color(64,64,64);
	Memory->InterfaceColors[PapayaInterfaceColor_ButtonActive]	= Color(0,122,204);

	Memory->Documents = (PapayaDocument*)malloc(sizeof(PapayaDocument));
	LoadImageIntoDocument("C:\\Users\\Apoorva\\Pictures\\ImageTest\\Fruits.png", Memory->Documents);
	Memory->Documents[0].CanvasPosition = Vec2((Memory->Window.Width - 512.0f)/2.0f, (Memory->Window.Height - 512.0f)/2.0f);
	Memory->Documents[0].CanvasZoom = 1.0f;
}

void Papaya_Shutdown(PapayaMemory* Memory)
{
	//TODO: Free document texture
	free(Memory->Documents);
}

void Papaya_UpdateAndRender(PapayaMemory* Memory, PapayaDebugMemory* DebugMemory)
{
	#pragma region Current mouse info
	{
		Memory->Mouse.Pos = ImGui::GetMousePos();
		Memory->Mouse.IsDown[0] = ImGui::IsMouseDown(0);
		Memory->Mouse.IsDown[1] = ImGui::IsMouseDown(1);
		Memory->Mouse.IsDown[2] = ImGui::IsMouseDown(2);
	}
	#pragma endregion

	//local_persist float TimeX;
	//TimeX += 0.1f;
	//for (int32 i = 0; i < Memory->Documents[0].Width * Memory->Documents[0].Width; i++)
	//{
	//	*((uint8*)(Memory->Documents[0].Texture + i*4)) = 128 + (uint8)(128.0f * sin(TimeX));
	//}
	//glBindTexture(GL_TEXTURE_2D, Memory->Documents[0].TextureID);

	//int32 XOffset = 128, YOffset = 128;
	//int32 UpdateWidth = 256, UpdateHeight = 256;

	//glPixelStorei(GL_UNPACK_ROW_LENGTH, Memory->Documents[0].Width);
	//glPixelStorei(GL_UNPACK_SKIP_PIXELS, XOffset);
	//glPixelStorei(GL_UNPACK_SKIP_ROWS, YOffset);
	//glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, Memory->Documents[0].Width, Memory->Documents[0].Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, Memory->Documents[0].Texture);
	//glTexSubImage2D(GL_TEXTURE_2D, 0, XOffset, YOffset, UpdateWidth, UpdateHeight, GL_RGBA, GL_UNSIGNED_BYTE, Memory->Documents[0].Texture);

	// Brush
	{
		if (ImGui::IsMouseDown(0))
		{
			Vec2 MCurr = (Memory->Mouse.Pos - Memory->Documents[0].CanvasPosition) * (1.0f / Memory->Documents[0].CanvasZoom);
			Vec2 MLast = (Memory->Mouse.LastPos - Memory->Documents[0].CanvasPosition) * (1.0f / Memory->Documents[0].CanvasZoom);

			// TODO: Optimize and clean
			// Bresenham's line
			{
				int32 x = (int32)MCurr.x;	int32 y = (int32)MCurr.y;
				int32 x2 = (int32)MLast.x;	int32 y2 = (int32)MLast.y;
				int32 w = x2 - x;
				int32 h = y2 - y;
				int32 dx1 = 0, dy1 = 0, dx2 = 0, dy2 = 0 ;
				if		(w<0) { dx1 = -1; }
				else if (w>0) { dx1 =  1; }
				if		(h<0) { dy1 = -1; }
				else if (h>0) { dy1 =  1; }
				if		(w<0) { dx2 = -1; }
				else if (w>0) { dx2 =  1; }

				int32 longest = Math::Abs(w);
				int32 shortest = Math::Abs(h);
				if (longest <= shortest)
				{
					longest = Math::Abs(h);
					shortest = Math::Abs(w);
					if		(h<0) { dy2 = -1; }
					else if (h>0) { dy2 =  1; }
					dx2 = 0;            
				}
				int32 numerator = longest >> 1;

				for (int32 i=0; i<=longest; i++) 
				{
					if (x >= 0 && x < Memory->Documents[0].Width &&
						y >= 0 && y < Memory->Documents[0].Height)
					{
						*((uint32*)(Memory->Documents[0].Texture + (Memory->Documents[0].Width * y * sizeof(uint32)) + x * sizeof(uint32))) = 0xffff0000; // 0xAABBGGRR
						glBindTexture(GL_TEXTURE_2D, Memory->Documents[0].TextureID);
						glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, Memory->Documents[0].Width, Memory->Documents[0].Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, Memory->Documents[0].Texture);
					}

					numerator += shortest;
					if (numerator >= longest) 
					{
						numerator -= longest;
						x += dx1;
						y += dy1;
					} 
					else 
					{
						x += dx2;
						y += dy2;
					}
				}
			}
		}
	}


	// Panning
	Memory->Documents[0].CanvasPosition += ImGui::GetMouseDragDelta(2);
	ImGui::ResetMouseDragDelta(2);

	// Zooming
	if (!ImGui::IsMouseDown(2) && ImGui::GetIO().MouseWheel)
	{
		float MinZoom = 0.01f, MaxZoom = 32.0f;
		float ZoomSpeed = 0.2f * Memory->Documents[0].CanvasZoom;
		float ScaleDelta = min(MaxZoom - Memory->Documents[0].CanvasZoom, ImGui::GetIO().MouseWheel * ZoomSpeed);
		Vec2 OldCanvasZoom = Vec2((float)Memory->Documents[0].Width, (float)Memory->Documents[0].Height) * Memory->Documents[0].CanvasZoom;<commit_msg>Extracted the texture upload from the loop<commit_after>#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

internal ImTextureID LoadAndBindImage(char* Path)
{
	uint8* Image;
	int32 ImageWidth, ImageHeight, ComponentsPerPixel;
	Image = stbi_load(Path, &ImageWidth, &ImageHeight, &ComponentsPerPixel, 0);

	// Create texture
	GLuint Id_GLuint;
	glGenTextures(1, &Id_GLuint);
	glBindTexture(GL_TEXTURE_2D, Id_GLuint);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ImageWidth, ImageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, Image);

	// Store our identifier
	free(Image);
	return (void *)(intptr_t)Id_GLuint;
}

internal void LoadImageIntoDocument(char* Path, PapayaDocument* Document)
{
	Document->Texture = stbi_load(Path, &Document->Width, &Document->Height, &Document->ComponentsPerPixel, 0);

	// Create texture
	glGenTextures(1, &Document->TextureID);
	glBindTexture(GL_TEXTURE_2D, Document->TextureID);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, Document->Width, Document->Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, Document->Texture);
}

void Papaya_Initialize(PapayaMemory* Memory)
{
	// Texture IDs
	Memory->InterfaceTextureIDs[PapayaInterfaceTexture_TitleBarButtons] = (uint32)LoadAndBindImage("../../img/win32_titlebar_buttons.png");
	Memory->InterfaceTextureIDs[PapayaInterfaceTexture_TitleBarIcon] = (uint32)LoadAndBindImage("../../img/win32_titlebar_icon.png");
	Memory->InterfaceTextureIDs[PapayaInterfaceTexture_InterfaceIcons] = (uint32)LoadAndBindImage("../../img/interface_icons.png");

	// Colors
#if 1
	Memory->InterfaceColors[PapayaInterfaceColor_Clear]			= Color(45,45,48); // Dark grey
#else
	Memory->InterfaceColors[PapayaInterfaceColor_Clear]			= Color(114,144,154); // Light blue
#endif
	Memory->InterfaceColors[PapayaInterfaceColor_Transparent]	= Color(0,0,0,0);
	Memory->InterfaceColors[PapayaInterfaceColor_ButtonHover]	= Color(64,64,64);
	Memory->InterfaceColors[PapayaInterfaceColor_ButtonActive]	= Color(0,122,204);

	Memory->Documents = (PapayaDocument*)malloc(sizeof(PapayaDocument));
	LoadImageIntoDocument("C:\\Users\\Apoorva\\Pictures\\ImageTest\\Fruits.png", Memory->Documents);
	Memory->Documents[0].CanvasPosition = Vec2((Memory->Window.Width - 512.0f)/2.0f, (Memory->Window.Height - 512.0f)/2.0f);
	Memory->Documents[0].CanvasZoom = 1.0f;
}

void Papaya_Shutdown(PapayaMemory* Memory)
{
	//TODO: Free document texture
	free(Memory->Documents);
}

void Papaya_UpdateAndRender(PapayaMemory* Memory, PapayaDebugMemory* DebugMemory)
{
	#pragma region Current mouse info
	{
		Memory->Mouse.Pos = ImGui::GetMousePos();
		Memory->Mouse.IsDown[0] = ImGui::IsMouseDown(0);
		Memory->Mouse.IsDown[1] = ImGui::IsMouseDown(1);
		Memory->Mouse.IsDown[2] = ImGui::IsMouseDown(2);
	}
	#pragma endregion

	//local_persist float TimeX;
	//TimeX += 0.1f;
	//for (int32 i = 0; i < Memory->Documents[0].Width * Memory->Documents[0].Width; i++)
	//{
	//	*((uint8*)(Memory->Documents[0].Texture + i*4)) = 128 + (uint8)(128.0f * sin(TimeX));
	//}
	//glBindTexture(GL_TEXTURE_2D, Memory->Documents[0].TextureID);

	//int32 XOffset = 128, YOffset = 128;
	//int32 UpdateWidth = 256, UpdateHeight = 256;

	//glPixelStorei(GL_UNPACK_ROW_LENGTH, Memory->Documents[0].Width);
	//glPixelStorei(GL_UNPACK_SKIP_PIXELS, XOffset);
	//glPixelStorei(GL_UNPACK_SKIP_ROWS, YOffset);
	//glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, Memory->Documents[0].Width, Memory->Documents[0].Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, Memory->Documents[0].Texture);
	//glTexSubImage2D(GL_TEXTURE_2D, 0, XOffset, YOffset, UpdateWidth, UpdateHeight, GL_RGBA, GL_UNSIGNED_BYTE, Memory->Documents[0].Texture);

	// Brush
	{
		if (ImGui::IsMouseDown(0))
		{
			Vec2 MCurr = (Memory->Mouse.Pos - Memory->Documents[0].CanvasPosition) * (1.0f / Memory->Documents[0].CanvasZoom);
			Vec2 MLast = (Memory->Mouse.LastPos - Memory->Documents[0].CanvasPosition) * (1.0f / Memory->Documents[0].CanvasZoom);

			// TODO: Optimize and clean
			// Bresenham's line
			{
				int32 x = (int32)MCurr.x;	int32 y = (int32)MCurr.y;
				int32 x2 = (int32)MLast.x;	int32 y2 = (int32)MLast.y;
				int32 w = x2 - x;
				int32 h = y2 - y;
				int32 dx1 = 0, dy1 = 0, dx2 = 0, dy2 = 0 ;
				if		(w<0) { dx1 = -1; }
				else if (w>0) { dx1 =  1; }
				if		(h<0) { dy1 = -1; }
				else if (h>0) { dy1 =  1; }
				if		(w<0) { dx2 = -1; }
				else if (w>0) { dx2 =  1; }

				int32 longest = Math::Abs(w);
				int32 shortest = Math::Abs(h);
				if (longest <= shortest)
				{
					longest = Math::Abs(h);
					shortest = Math::Abs(w);
					if		(h<0) { dy2 = -1; }
					else if (h>0) { dy2 =  1; }
					dx2 = 0;            
				}
				int32 numerator = longest >> 1;

				for (int32 i=0; i<=longest; i++) 
				{
					if (x >= 0 && x < Memory->Documents[0].Width &&
						y >= 0 && y < Memory->Documents[0].Height)
					{
						*((uint32*)(Memory->Documents[0].Texture + (Memory->Documents[0].Width * y * sizeof(uint32)) + x * sizeof(uint32))) = 0xffff0000; // 0xAABBGGRR
					}

					numerator += shortest;
					if (numerator >= longest) 
					{
						numerator -= longest;
						x += dx1;
						y += dy1;
					} 
					else 
					{
						x += dx2;
						y += dy2;
					}
				}

				glBindTexture(GL_TEXTURE_2D, Memory->Documents[0].TextureID);
				glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, Memory->Documents[0].Width, Memory->Documents[0].Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, Memory->Documents[0].Texture);
			}
		}
	}


	// Panning
	Memory->Documents[0].CanvasPosition += ImGui::GetMouseDragDelta(2);
	ImGui::ResetMouseDragDelta(2);

	// Zooming
	if (!ImGui::IsMouseDown(2) && ImGui::GetIO().MouseWheel)
	{
		float MinZoom = 0.01f, MaxZoom = 32.0f;
		float ZoomSpeed = 0.2f * Memory->Documents[0].CanvasZoom;
		float ScaleDelta = min(MaxZoom - Memory->Documents[0].CanvasZoom, ImGui::GetIO().MouseWheel * ZoomSpeed);
		Vec2 OldCanvasZoom = Vec2((float)Memory->Documents[0].Width, (float)Memory->Documents[0].Height) * Memory->Documents[0].CanvasZoom;
{'fraction_non_alphanumeric': 0.15890589384565287, 'fraction_numerical': 0.04395962227287528, 'mean_word_length': 4.440655447298494, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 135, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1403508', 'n_tokens_mistral': 5319, 'n_tokens_neox': 4624, 'n_words': 781}