#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //#define USE_OPENGL 1 //#define USE_CONTEXTPLUS 1 #ifdef USE_OPENGL #include #include #endif #if _MSC_VER < 1800 /* vc12 (2013) */ #define DEFINE_ROUND #endif #ifdef DEFINE_ROUND double round(double x) { return (int)(x>0? x+0.5: x-0.5); } #endif /********************************** Images *****************************************/ static Ihandle* load_image_PaintLine(void) { unsigned char imgdata[] = { 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 12, 0, 0, 0, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 239, 0, 0, 0, 60, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 239, 0, 0, 0, 60, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 84, 0, 0, 0, 239, 0, 0, 0, 60, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 84, 0, 0, 0, 239, 0, 0, 0, 60, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 84, 0, 0, 0, 239, 0, 0, 0, 60, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 84, 0, 0, 0, 239, 0, 0, 0, 60, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 84, 0, 0, 0, 239, 0, 0, 0, 60, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 84, 0, 0, 0, 239, 0, 0, 0, 60, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 84, 0, 0, 0, 239, 0, 0, 0, 60, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 84, 0, 0, 0, 239, 0, 0, 0, 60, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 84, 0, 0, 0, 239, 0, 0, 0, 60, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 84, 0, 0, 0, 227, 0, 0, 0, 8, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 16, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0 }; Ihandle* image = IupImageRGBA(16, 16, imgdata); return image; } static Ihandle* load_image_Pointer(void) { unsigned char imgdata[] = { 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 162, 180, 203, 255, 162, 180, 203, 84, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 162, 180, 203, 255, 162, 180, 203, 255, 162, 180, 203, 84, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 162, 180, 203, 255, 240, 243, 246, 255, 162, 180, 203, 255, 162, 180, 203, 69, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 162, 180, 203, 255, 255, 255, 255, 255, 241, 244, 247, 255, 161, 179, 202, 255, 161, 179, 202, 57, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 158, 176, 200, 255, 255, 255, 255, 255, 255, 255, 255, 255, 240, 242, 246, 255, 147, 165, 189, 255, 134, 152, 176, 57, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 153, 172, 195, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 227, 231, 236, 255, 129, 147, 171, 255, 115, 134, 158, 48, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 148, 166, 189, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 254, 255, 213, 218, 226, 255, 111, 130, 154, 255, 96, 115, 140, 57, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 141, 159, 183, 255, 254, 255, 255, 255, 252, 253, 254, 255, 250, 251, 253, 255, 247, 248, 251, 255, 243, 246, 250, 255, 206, 213, 223, 255, 91, 110, 136, 255, 73, 92, 118, 48, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 134, 152, 176, 255, 249, 250, 252, 255, 246, 247, 251, 255, 242, 245, 249, 255, 238, 242, 247, 255, 92, 111, 137, 255, 56, 76, 102, 255, 60, 80, 106, 255, 73, 92, 118, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 127, 145, 170, 255, 241, 244, 249, 255, 205, 212, 221, 255, 88, 108, 133, 255, 229, 234, 243, 255, 105, 124, 148, 255, 105, 124, 148, 83, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 119, 138, 163, 255, 203, 209, 220, 255, 63, 83, 109, 255, 102, 121, 145, 255, 197, 206, 221, 255, 187, 197, 214, 255, 89, 108, 133, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 112, 131, 156, 255, 82, 101, 127, 255, 55, 75, 101, 81, 102, 121, 145, 123, 102, 121, 145, 255, 206, 215, 233, 255, 79, 99, 124, 255, 79, 99, 124, 45, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 105, 124, 150, 255, 255, 255, 255, 0, 255, 255, 255, 0, 102, 121, 145, 18, 95, 115, 140, 255, 190, 202, 223, 255, 152, 167, 189, 255, 67, 87, 112, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 95, 115, 140, 150, 84, 104, 129, 255, 164, 178, 202, 255, 58, 78, 104, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 95, 115, 140, 6, 70, 90, 116, 255, 59, 79, 105, 255, 55, 75, 101, 87, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0 }; Ihandle* image = IupImageRGBA(16, 16, imgdata); return image; } static Ihandle* load_image_PaintPencil(void) { unsigned char imgdata[] = { 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 194, 126, 104, 73, 173, 108, 94, 255, 173, 108, 94, 255, 188, 121, 101, 48, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 175, 158, 120, 66, 173, 108, 94, 255, 235, 159, 129, 255, 208, 118, 94, 255, 173, 108, 94, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 175, 158, 120, 66, 187, 176, 125, 255, 172, 184, 202, 255, 209, 133, 115, 255, 173, 108, 94, 255, 144, 53, 53, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 175, 158, 120, 66, 185, 172, 115, 255, 238, 224, 140, 255, 217, 196, 108, 255, 134, 134, 125, 255, 144, 53, 53, 255, 131, 57, 47, 78, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 175, 158, 120, 66, 183, 166, 101, 255, 238, 224, 140, 255, 215, 191, 98, 255, 178, 154, 73, 255, 22, 18, 14, 255, 102, 85, 40, 48, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 175, 158, 120, 66, 185, 172, 115, 255, 238, 224, 140, 255, 215, 191, 98, 255, 178, 154, 73, 255, 22, 18, 14, 255, 117, 98, 45, 59, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 175, 158, 120, 66, 183, 166, 101, 255, 238, 224, 140, 255, 215, 191, 98, 255, 178, 154, 73, 255, 22, 18, 14, 255, 117, 98, 45, 59, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 175, 158, 120, 66, 181, 160, 87, 255, 238, 224, 140, 255, 215, 191, 98, 255, 178, 154, 73, 255, 22, 18, 14, 255, 117, 98, 45, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 175, 158, 120, 66, 179, 156, 77, 255, 238, 224, 140, 255, 215, 191, 98, 255, 178, 154, 73, 255, 22, 18, 14, 255, 117, 98, 45, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 152, 157, 163, 255, 199, 183, 136, 255, 226, 206, 116, 255, 178, 154, 73, 255, 22, 18, 14, 255, 82, 68, 37, 40, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 152, 157, 163, 118, 152, 157, 163, 255, 254, 254, 253, 255, 169, 147, 81, 255, 22, 18, 14, 255, 117, 98, 45, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 118, 110, 113, 117, 255, 81, 84, 87, 255, 0, 0, 0, 255, 82, 68, 37, 40, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 224, 0, 0, 0, 118, 81, 84, 87, 104, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0 }; Ihandle* image = IupImageRGBA(16, 16, imgdata); return image; } static Ihandle* load_image_PaintColorPicker(void) { unsigned char imgdata[] = { 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 1, 1, 1, 85, 0, 0, 1, 192, 0, 0, 0, 192, 0, 0, 0, 85, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 7, 11, 15, 37, 8, 12, 16, 70, 79, 81, 83, 224, 205, 205, 205, 255, 136, 138, 142, 255, 11, 13, 15, 203, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 9, 15, 21, 119, 18, 26, 37, 255, 68, 70, 72, 255, 88, 93, 99, 255, 117, 120, 126, 255, 84, 86, 91, 255, 2, 2, 2, 194, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 15, 21, 30, 31, 23, 34, 49, 235, 49, 56, 65, 255, 70, 72, 72, 255, 54, 56, 58, 255, 21, 22, 22, 199, 0, 0, 0, 85, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 152, 166, 185, 255, 20, 30, 42, 42, 21, 32, 45, 237, 49, 56, 65, 255, 7, 9, 13, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 152, 166, 185, 255, 255, 255, 255, 255, 202, 208, 222, 255, 173, 183, 202, 255, 6, 10, 15, 236, 2, 4, 5, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 152, 166, 185, 255, 255, 255, 255, 255, 202, 208, 222, 255, 143, 156, 181, 255, 68, 88, 114, 255, 1, 1, 3, 33, 0, 0, 0, 111, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 152, 166, 185, 255, 255, 255, 255, 255, 214, 220, 230, 255, 143, 156, 181, 255, 68, 88, 114, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 152, 166, 185, 255, 255, 255, 255, 255, 215, 221, 231, 255, 143, 156, 181, 255, 65, 85, 112, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 152, 166, 185, 255, 255, 255, 255, 255, 216, 220, 231, 255, 143, 156, 181, 255, 65, 85, 112, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 152, 166, 185, 255, 216, 220, 231, 218, 143, 156, 181, 255, 66, 86, 113, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 43, 134, 240, 46, 43, 134, 240, 107, 152, 166, 185, 255, 255, 255, 255, 255, 69, 89, 114, 255, 51, 72, 99, 255, 43, 134, 240, 236, 43, 134, 240, 204, 43, 133, 240, 161, 43, 132, 239, 107, 43, 130, 239, 46, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 43, 133, 239, 170, 43, 133, 240, 255, 87, 105, 130, 255, 79, 97, 123, 255, 43, 134, 240, 255, 43, 134, 240, 255, 43, 135, 240, 255, 43, 134, 240, 255, 43, 134, 240, 255, 43, 134, 240, 255, 43, 133, 239, 170, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 42, 120, 237, 46, 42, 124, 238, 107, 42, 125, 238, 161, 42, 126, 238, 204, 42, 128, 238, 236, 43, 130, 239, 253, 43, 131, 239, 236, 43, 131, 239, 204, 43, 131, 239, 161, 43, 129, 239, 107, 42, 127, 238, 46, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0 }; Ihandle* image = IupImageRGBA(16, 16, imgdata); return image; } static Ihandle* load_image_PaintEllipse(void) { unsigned char imgdata[] = { 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 20, 0, 0, 0, 84, 0, 0, 0, 128, 0, 0, 0, 128, 0, 0, 0, 84, 0, 0, 0, 20, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 16, 0, 0, 0, 155, 0, 0, 0, 239, 0, 0, 0, 175, 0, 0, 0, 131, 0, 0, 0, 131, 0, 0, 0, 175, 0, 0, 0, 239, 0, 0, 0, 155, 0, 0, 0, 16, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 24, 0, 0, 0, 215, 0, 0, 0, 143, 0, 0, 0, 16, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 16, 0, 0, 0, 143, 0, 0, 0, 215, 0, 0, 0, 24, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 199, 0, 0, 0, 120, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 120, 0, 0, 0, 199, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 60, 0, 0, 0, 211, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 211, 0, 0, 0, 60, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 120, 0, 0, 0, 139, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 139, 0, 0, 0, 120, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 120, 0, 0, 0, 135, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 135, 0, 0, 0, 120, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 68, 0, 0, 0, 211, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 211, 0, 0, 0, 68, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 199, 0, 0, 0, 120, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 120, 0, 0, 0, 199, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 36, 0, 0, 0, 231, 0, 0, 0, 135, 0, 0, 0, 12, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 12, 0, 0, 0, 135, 0, 0, 0, 231, 0, 0, 0, 36, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 20, 0, 0, 0, 163, 0, 0, 0, 239, 0, 0, 0, 171, 0, 0, 0, 131, 0, 0, 0, 131, 0, 0, 0, 171, 0, 0, 0, 239, 0, 0, 0, 163, 0, 0, 0, 20, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 24, 0, 0, 0, 88, 0, 0, 0, 128, 0, 0, 0, 128, 0, 0, 0, 88, 0, 0, 0, 24, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0 }; Ihandle* image = IupImageRGBA(16, 16, imgdata); return image; } static Ihandle* load_image_PaintRect(void) { unsigned char imgdata[] = { 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 254, 0, 0, 0, 247, 0, 0, 0, 239, 0, 0, 0, 247, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0 }; Ihandle* image = IupImageRGBA(16, 16, imgdata); return image; } static Ihandle* load_image_PaintOval(void) { unsigned char imgdata[] = { 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 24, 0, 0, 0, 135, 0, 0, 0, 211, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 211, 0, 0, 0, 135, 0, 0, 0, 24, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 80, 0, 0, 0, 239, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 239, 0, 0, 0, 80, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 48, 0, 0, 0, 251, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 251, 0, 0, 0, 48, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 183, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 183, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 247, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 247, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 247, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 247, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 183, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 183, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 56, 0, 0, 0, 251, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 251, 0, 0, 0, 56, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 84, 0, 0, 0, 243, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 243, 0, 0, 0, 84, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 24, 0, 0, 0, 139, 0, 0, 0, 211, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 211, 0, 0, 0, 139, 0, 0, 0, 24, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0 }; Ihandle* image = IupImageRGBA(16, 16, imgdata); return image; } static Ihandle* load_image_PaintBox(void) { unsigned char imgdata[] = { 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 254, 0, 0, 0, 247, 0, 0, 0, 239, 0, 0, 0, 247, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0 }; Ihandle* image = IupImageRGBA(16, 16, imgdata); return image; } static Ihandle* load_image_PaintZoomGrid(void) { unsigned char imgdata[] = { 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 110, 155, 223, 255, 255, 255, 255, 0, 255, 255, 255, 0, 106, 151, 219, 255, 255, 255, 255, 0, 255, 255, 255, 0, 95, 142, 210, 255, 255, 255, 255, 0, 255, 255, 255, 0, 84, 129, 201, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 110, 155, 223, 255, 255, 255, 255, 0, 255, 255, 255, 0, 102, 147, 217, 255, 255, 255, 255, 0, 255, 255, 255, 0, 92, 137, 207, 255, 255, 255, 255, 0, 255, 255, 255, 0, 80, 125, 197, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 110, 155, 223, 255, 110, 155, 223, 255, 107, 152, 222, 255, 104, 151, 219, 255, 103, 148, 216, 255, 100, 145, 213, 255, 97, 142, 210, 255, 93, 138, 206, 255, 88, 133, 203, 255, 84, 129, 201, 255, 80, 125, 197, 255, 76, 121, 193, 255, 72, 117, 189, 255, 68, 113, 183, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 106, 149, 219, 255, 255, 255, 255, 0, 255, 255, 255, 0, 97, 142, 210, 255, 255, 255, 255, 0, 255, 255, 255, 0, 84, 131, 199, 255, 255, 255, 255, 0, 255, 255, 255, 0, 72, 117, 187, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 103, 148, 216, 255, 255, 255, 255, 0, 255, 255, 255, 0, 92, 137, 207, 255, 255, 255, 255, 0, 255, 255, 255, 0, 81, 125, 196, 255, 255, 255, 255, 0, 255, 255, 255, 0, 68, 113, 185, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 104, 151, 219, 255, 104, 148, 216, 255, 100, 145, 213, 255, 97, 142, 210, 255, 92, 137, 207, 255, 88, 135, 203, 255, 84, 129, 199, 255, 80, 125, 195, 255, 76, 121, 193, 255, 70, 117, 189, 255, 68, 112, 183, 255, 62, 109, 181, 255, 60, 105, 177, 255, 57, 102, 174, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 97, 142, 210, 255, 255, 255, 255, 0, 255, 255, 255, 0, 84, 129, 199, 255, 255, 255, 255, 0, 255, 255, 255, 0, 72, 117, 187, 255, 255, 255, 255, 0, 255, 255, 255, 0, 60, 105, 177, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 93, 138, 206, 255, 255, 255, 255, 0, 255, 255, 255, 0, 80, 125, 195, 255, 255, 255, 255, 0, 255, 255, 255, 0, 66, 113, 185, 255, 255, 255, 255, 0, 255, 255, 255, 0, 56, 103, 173, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 95, 140, 212, 255, 92, 137, 207, 255, 88, 133, 203, 255, 84, 129, 199, 255, 80, 125, 195, 255, 76, 121, 193, 255, 72, 117, 187, 255, 68, 113, 185, 255, 64, 107, 181, 255, 59, 105, 178, 255, 55, 101, 174, 255, 53, 98, 170, 255, 49, 95, 168, 255, 48, 91, 165, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 84, 131, 199, 255, 255, 255, 255, 0, 255, 255, 255, 0, 70, 117, 189, 255, 255, 255, 255, 0, 255, 255, 255, 0, 60, 105, 177, 255, 255, 255, 255, 0, 255, 255, 255, 0, 49, 95, 168, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 82, 125, 195, 255, 255, 255, 255, 0, 255, 255, 255, 0, 68, 113, 185, 255, 255, 255, 255, 0, 255, 255, 255, 0, 57, 102, 174, 255, 255, 255, 255, 0, 255, 255, 255, 0, 46, 92, 165, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 84, 129, 199, 255, 80, 125, 195, 255, 76, 121, 191, 255, 72, 117, 189, 255, 66, 113, 185, 255, 64, 109, 181, 255, 60, 105, 177, 255, 55, 102, 174, 255, 52, 98, 171, 255, 49, 95, 168, 255, 46, 91, 166, 255, 44, 90, 163, 255, 42, 88, 161, 255, 42, 88, 161, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 72, 117, 187, 255, 255, 255, 255, 0, 255, 255, 255, 0, 60, 107, 177, 255, 255, 255, 255, 0, 255, 255, 255, 0, 50, 95, 167, 255, 255, 255, 255, 0, 255, 255, 255, 0, 42, 88, 161, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 68, 113, 185, 255, 255, 255, 255, 0, 255, 255, 255, 0, 56, 101, 173, 255, 255, 255, 255, 0, 255, 255, 255, 0, 46, 92, 165, 255, 255, 255, 255, 0, 255, 255, 255, 0, 42, 88, 161, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0 }; Ihandle* image = IupImageRGBA(16, 16, imgdata); return image; } static Ihandle* load_image_PaintFill(void) { unsigned char imgdata[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 53, 53, 86, 59, 59, 59, 111, 108, 108, 108, 82, 127, 127, 127, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 54, 54, 122, 72, 72, 72, 7, 119, 122, 124, 117, 124, 124, 130, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 77, 76, 154, 144, 166, 188, 23, 158, 169, 181, 191, 144, 151, 159, 194, 134, 147, 174, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 126, 129, 197, 141, 160, 183, 179, 212, 219, 225, 254, 157, 162, 166, 254, 163, 180, 200, 168, 159, 175, 191, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, 141, 158, 45, 130, 143, 155, 245, 218, 225, 232, 250, 222, 232, 239, 255, 136, 139, 142, 255, 205, 217, 227, 252, 148, 167, 189, 163, 155, 155, 184, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 148, 170, 24, 134, 155, 174, 172, 213, 220, 227, 254, 218, 233, 243, 255, 197, 207, 217, 255, 149, 149, 150, 255, 232, 241, 245, 255, 179, 196, 213, 252, 129, 147, 172, 164, 75, 103, 144, 37, 17, 51, 102, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 147, 174, 19, 122, 146, 168, 179, 216, 223, 228, 252, 217, 231, 242, 255, 213, 227, 238, 255, 159, 162, 164, 255, 128, 129, 128, 255, 228, 235, 239, 255, 171, 197, 218, 255, 136, 162, 190, 253, 87, 116, 156, 227, 37, 75, 150, 183, 0, 31, 107, 57, 0, 0, 0, 0, 0, 0, 0, 0, 120, 134, 161, 19, 126, 147, 168, 157, 209, 217, 225, 245, 217, 231, 241, 255, 203, 217, 232, 255, 242, 244, 245, 255, 192, 192, 191, 255, 164, 166, 169, 255, 202, 213, 223, 255, 158, 176, 194, 255, 126, 154, 184, 255, 103, 134, 168, 255, 76, 110, 169, 255, 49, 93, 175, 201, 37, 66, 132, 27, 122, 132, 160, 27, 102, 124, 149, 172, 194, 209, 220, 241, 213, 228, 239, 246, 204, 218, 232, 249, 241, 242, 244, 255, 247, 245, 245, 255, 243, 244, 243, 255, 222, 228, 234, 255, 192, 203, 214, 255, 159, 172, 185, 255, 138, 152, 168, 255, 84, 116, 151, 248, 74, 104, 158, 246, 83, 129, 213, 243, 77, 108, 169, 92, 125, 134, 152, 55, 111, 131, 154, 211, 189, 201, 214, 255, 214, 223, 234, 254, 238, 240, 243, 236, 248, 246, 245, 241, 242, 243, 243, 254, 221, 228, 234, 255, 192, 203, 214, 255, 165, 178, 192, 255, 142, 155, 169, 255, 98, 117, 137, 243, 77, 94, 120, 121, 46, 82, 158, 171, 87, 131, 209, 247, 85, 114, 171, 122, 0, 255, 255, 1, 134, 140, 167, 38, 137, 155, 179, 206, 218, 223, 230, 254, 244, 242, 243, 252, 242, 244, 243, 239, 220, 228, 234, 252, 192, 202, 214, 255, 164, 176, 190, 255, 140, 154, 168, 255, 92, 112, 132, 243, 75, 91, 114, 111, 102, 102, 153, 5, 29, 61, 136, 140, 68, 109, 192, 244, 84, 113, 170, 94, 0, 0, 0, 0, 0, 0, 255, 1, 157, 173, 195, 47, 148, 166, 191, 205, 204, 210, 220, 248, 227, 231, 235, 253, 193, 204, 216, 255, 163, 175, 189, 255, 138, 151, 166, 255, 95, 113, 134, 242, 74, 88, 113, 110, 95, 127, 127, 8, 0, 0, 0, 0, 35, 66, 135, 145, 72, 109, 182, 239, 91, 120, 178, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 142, 165, 34, 103, 124, 151, 197, 158, 172, 187, 252, 164, 176, 189, 255, 134, 148, 162, 254, 96, 113, 133, 245, 75, 87, 110, 122, 102, 102, 102, 5, 0, 0, 0, 0, 0, 0, 0, 0, 60, 91, 151, 173, 84, 115, 173, 195, 98, 117, 176, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 110, 119, 30, 73, 96, 120, 204, 107, 126, 144, 255, 106, 123, 141, 255, 102, 115, 135, 152, 139, 150, 162, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 92, 154, 173, 85, 115, 173, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 82, 115, 31, 49, 79, 109, 212, 92, 110, 134, 169, 143, 159, 175, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 93, 154, 163, 63, 89, 153, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 118, 140, 58, 85, 106, 148, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 92, 154, 33, 0, 0, 0, 0, 0, 0, 0, 0 }; Ihandle* image = IupImageRGBA(16, 16, imgdata); return image; } static Ihandle* load_image_PaintText(void) { unsigned char imgdata[] = { 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 36, 0, 0, 0, 96, 0, 0, 0, 96, 0, 0, 0, 96, 0, 0, 0, 96, 0, 0, 0, 96, 0, 0, 0, 96, 0, 0, 0, 96, 0, 0, 0, 96, 0, 0, 0, 96, 0, 0, 0, 96, 0, 0, 0, 72, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 96, 0, 0, 0, 255, 0, 0, 0, 203, 0, 0, 0, 124, 0, 0, 0, 135, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 215, 0, 0, 0, 96, 0, 0, 0, 131, 0, 0, 0, 243, 0, 0, 0, 191, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 96, 0, 0, 0, 163, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 64, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 191, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 44, 0, 0, 0, 191, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 96, 0, 0, 0, 48, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 64, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 191, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 116, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 64, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 191, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 64, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 191, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 64, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 191, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 64, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 191, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 64, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 191, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 64, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 191, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 64, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 191, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 64, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 191, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 96, 0, 0, 0, 187, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 243, 0, 0, 0, 116, 0, 0, 0, 48, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0 }; Ihandle* image = IupImageRGBA(16, 16, imgdata); return image; } /********************************** Utilities *****************************************/ static const char* str_filetitle(const char *filename) { /* Start at the last character */ int len = (int)strlen(filename); int offset = len - 1; while (offset != 0) { if (filename[offset] == '\\' || filename[offset] == '/') { offset++; break; } offset--; } return filename + offset; } static const char* str_fileext(const char *filename) { /* Start at the last character */ int len = (int)strlen(filename); int offset = len - 1; while (offset != 0) { if (filename[offset] == '\\' || filename[offset] == '/') break; if (filename[offset] == '.') { offset++; return filename + offset; } offset--; } return NULL; } static int str_compare(const char *l, const char *r, int casesensitive) { if (!l || !r) return 0; while (*l && *r) { int diff; char l_char = *l, r_char = *r; /* compute the difference of both characters */ if (casesensitive) diff = l_char - r_char; else diff = tolower((int)l_char) - tolower((int)r_char); /* if they differ we have a result */ if (diff != 0) return 0; /* otherwise process the next characters */ ++l; ++r; } /* check also for terminator */ if (*l == *r) return 1; if (*r == 0) return 1; /* if second string is at terminator, then it is partially equal */ return 0; } static void show_error(const char* message, int is_error) { Ihandle* dlg = IupMessageDlg(); IupSetStrAttribute(dlg, "PARENTDIALOG", IupGetGlobal("PARENTDIALOG")); IupSetAttribute(dlg, "DIALOGTYPE", is_error ? "ERROR" : "WARNING"); IupSetAttribute(dlg, "BUTTONS", "OK"); IupSetStrAttribute(dlg, "TITLE", is_error ? "Error" : "Warning"); IupSetStrAttribute(dlg, "VALUE", message); IupPopup(dlg, IUP_CENTERPARENT, IUP_CENTERPARENT); IupDestroy(dlg); } static void show_file_error(int error) { switch (error) { case IM_ERR_OPEN: show_error("Error Opening File.", 1); break; case IM_ERR_MEM: show_error("Insufficient memory.", 1); break; case IM_ERR_ACCESS: show_error("Error Accessing File.", 1); break; case IM_ERR_DATA: show_error("Image type not Supported.", 1); break; case IM_ERR_FORMAT: show_error("Invalid Format.", 1); break; case IM_ERR_COMPRESS: show_error("Invalid or unsupported compression.", 1); break; default: show_error("Unknown Error.", 1); } } static imImage* read_file(const char* filename) { int error; imImage* image = imFileImageLoadBitmap(filename, 0, &error); if (error) show_file_error(error); return image; } static int write_file(const char* filename, const imImage* image) { const char* format = imImageGetAttribString(image, "FileFormat"); int error = imFileImageSave(filename, format, image); if (error) { show_file_error(error); return 0; } return 1; } /* extracted from the SCROLLBAR attribute documentation */ static void scroll_update(Ihandle* ih, int view_width, int view_height) { /* view_width and view_height is the virtual space size */ /* here we assume XMIN=0, XMAX=1, YMIN=0, YMAX=1 */ int elem_width, elem_height; int canvas_width, canvas_height; int scrollbar_size = IupGetInt(NULL, "SCROLLBARSIZE"); int border = IupGetInt(ih, "BORDER"); IupGetIntInt(ih, "RASTERSIZE", &elem_width, &elem_height); /* if view is greater than canvas in one direction, then it has scrollbars, but this affects the opposite direction */ elem_width -= 2 * border; /* remove BORDER (always size=1) */ elem_height -= 2 * border; canvas_width = elem_width; canvas_height = elem_height; if (view_width > elem_width) /* check for horizontal scrollbar */ canvas_height -= scrollbar_size; /* affect vertical size */ if (view_height > elem_height) canvas_width -= scrollbar_size; if (view_width <= elem_width && view_width > canvas_width) /* check if still has horizontal scrollbar */ canvas_height -= scrollbar_size; if (view_height <= elem_height && view_height > canvas_height) canvas_width -= scrollbar_size; if (canvas_width < 0) canvas_width = 0; if (canvas_height < 0) canvas_height = 0; IupSetFloat(ih, "DX", (float)canvas_width / (float)view_width); IupSetFloat(ih, "DY", (float)canvas_height / (float)view_height); } static void scroll_calc_center(Ihandle* ih, float *x, float *y) { *x = IupGetFloat(ih, "POSX") + IupGetFloat(ih, "DX") / 2.0f; *y = IupGetFloat(ih, "POSY") + IupGetFloat(ih, "DY") / 2.0f; } static void scroll_center(Ihandle* ih, float old_center_x, float old_center_y) { /* always update the scroll position keeping it proportional to the old position relative to the center of the ih. */ float dx = IupGetFloat(ih, "DX"); float dy = IupGetFloat(ih, "DY"); float posx = old_center_x - dx / 2.0f; float posy = old_center_y - dy / 2.0f; if (posx < 0) posx = 0; if (posx > 1 - dx) posx = 1 - dx; if (posy < 0) posy = 0; if (posy > 1 - dy) posy = 1 - dy; IupSetFloat(ih, "POSX", posx); IupSetFloat(ih, "POSY", posy); } static void scroll_move(Ihandle* ih, int canvas_width, int canvas_height, int move_x, int move_y, int view_width, int view_height) { float posy = 0; float posx = 0; if (move_x == 0 && move_y == 0) return; if (canvas_height < view_height) { posy = IupGetFloat(ih, "POSY"); posy -= (float)move_y / (float)view_height; } if (canvas_width < view_width) { posx = IupGetFloat(ih, "POSX"); posx -= (float)move_x / (float)view_width; } if (posx != 0 || posy != 0) { IupSetFloat(ih, "POSX", posx); IupSetFloat(ih, "POSY", posy); IupRedraw(ih, 0); } } static void zoom_update(Ihandle* ih, double zoom_index) { Ihandle* zoom_lbl = IupGetDialogChild(ih, "ZOOMLABEL"); Ihandle* canvas = IupGetDialogChild(ih, "CANVAS"); imImage* image = (imImage*)IupGetAttribute(canvas, "IMAGE"); double zoom_factor = pow(2, zoom_index); IupSetStrf(zoom_lbl, "TITLE", "%.0f%%", floor(zoom_factor * 100)); if (image) { float old_center_x, old_center_y; int view_width = (int)(zoom_factor * image->width); int view_height = (int)(zoom_factor * image->height); scroll_calc_center(canvas, &old_center_x, &old_center_y); scroll_update(canvas, view_width, view_height); scroll_center(canvas, old_center_x, old_center_y); } IupUpdate(canvas); } static void image_flood_fill(imImage* image, int start_x, int start_y, long replace_color, double tol_percent) { #if IM_VERSION_NUMBER > 312000 double color[4]; double tol; #else float color[4]; float tol; #endif color[0] = cdRed(replace_color); color[1] = cdGreen(replace_color); color[2] = cdBlue(replace_color); color[3] = cdAlpha(replace_color); /* max value = 255*255*3 = 195075 */ /* sqrt(195075) = 441 */ tol = (441 * tol_percent) / 100; /* still too high */ tol = tol / 5; /* empirical reduce. TODO: What is the best formula? */ imProcessRenderFloodFill(image, start_x, start_y, color, tol); } static void image_fill_white(imImage* image) { double color[4]; color[0] = 255; color[1] = 255; color[2] = 255; color[3] = 255; imProcessRenderConstant(image, color); } static void update_image(Ihandle* canvas, imImage* image, int update_size) { imImage* old_image = (imImage*)IupGetAttribute(canvas, "IMAGE"); IupSetAttribute(canvas, "DIRTY", "Yes"); IupSetAttribute(canvas, "IMAGE", (char*)image); if (old_image) imImageDestroy(old_image); if (update_size) { Ihandle* size_lbl = IupGetDialogChild(canvas, "SIZELABEL"); Ihandle* zoom_val = IupGetDialogChild(canvas, "ZOOMVAL"); double zoom_index = IupGetDouble(zoom_val, "VALUE"); IupSetfAttribute(size_lbl, "TITLE", "%d x %d px", image->width, image->height); zoom_update(canvas, zoom_index); } else IupUpdate(canvas); } static void set_new_image(Ihandle* canvas, imImage* image, const char* filename, int dirty) { imImage* old_image = (imImage*)IupGetAttribute(canvas, "IMAGE"); Ihandle* size_lbl = IupGetDialogChild(canvas, "SIZELABEL"); Ihandle* zoom_val = IupGetDialogChild(canvas, "ZOOMVAL"); const char* format; if (filename) { IupSetStrAttribute(canvas, "FILENAME", filename); IupSetfAttribute(IupGetDialog(canvas), "TITLE", "%s - Simple Paint", str_filetitle(filename)); } else { IupSetAttribute(canvas, "FILENAME", NULL); IupSetAttribute(IupGetDialog(canvas), "TITLE", "Untitled - Simple Paint"); } /* we are going to support only RGB images */ if (image->color_space != IM_RGB) { imImage* new_image = imImageCreateBased(image, -1, -1, IM_RGB, -1); if (image->has_alpha) imImageAddAlpha(new_image); imConvertColorSpace(image, new_image); imImageDestroy(image); image = new_image; } /* default file format */ format = imImageGetAttribString(image, "FileFormat"); if (!format) imImageSetAttribString(image, "FileFormat", "JPEG"); IupSetAttribute(canvas, "DIRTY", dirty ? "Yes" : "No"); IupSetAttribute(canvas, "IMAGE", (char*)image); IupSetfAttribute(size_lbl, "TITLE", "%d x %d px", image->width, image->height); if (old_image) imImageDestroy(old_image); IupSetDouble(zoom_val, "VALUE", 0); zoom_update(canvas, 0); } static void check_new_file(Ihandle* dlg) { Ihandle* canvas = IupGetDialogChild(dlg, "CANVAS"); imImage* image = (imImage*)IupGetAttribute(canvas, "IMAGE"); if (!image) { Ihandle* config = (Ihandle*)IupGetAttribute(canvas, "CONFIG"); int width = IupConfigGetVariableIntDef(config, "NewImage", "Width", 640); int height = IupConfigGetVariableIntDef(config, "NewImage", "Height", 480); int has_alpha = IupConfigGetVariableIntDef(config, "NewImage", "HasAlpha", 0); image = imImageCreate(width, height, IM_RGB, IM_BYTE); if (!image) { show_file_error(IM_ERR_MEM); return; } if (has_alpha) imImageAddAlpha(image); image_fill_white(image); set_new_image(canvas, image, NULL, 0); } } static void open_file(Ihandle* ih, const char* filename) { imImage* image = read_file(filename); if (image) { Ihandle* canvas = IupGetDialogChild(ih, "CANVAS"); Ihandle* config = (Ihandle*)IupGetAttribute(canvas, "CONFIG"); set_new_image(canvas, image, filename, 0); IupConfigRecentUpdate(config, filename); } } static void save_file(Ihandle* canvas) { char* filename = IupGetAttribute(canvas, "FILENAME"); imImage* image = (imImage*)IupGetAttribute(canvas, "IMAGE"); if (write_file(filename, image)) IupSetAttribute(canvas, "DIRTY", "NO"); } static void set_file_format(imImage* image, const char* filename) { const char* ext = str_fileext(filename); const char* format = "JPEG"; if (str_compare(ext, "jpg", 0) || str_compare(ext, "jpeg", 0)) format = "JPEG"; else if (str_compare(ext, "bmp", 0)) format = "BMP"; else if (str_compare(ext, "png", 0)) format = "PNG"; else if (str_compare(ext, "tga", 0)) format = "TGA"; else if (str_compare(ext, "tif", 0) || str_compare(ext, "tiff", 0)) format = "TIFF"; imImageSetAttribString(image, "FileFormat", format); } static void saveas_file(Ihandle* canvas, const char* filename) { imImage* image = (imImage*)IupGetAttribute(canvas, "IMAGE"); set_file_format(image, filename); if (write_file(filename, image)) { Ihandle* config = (Ihandle*)IupGetAttribute(canvas, "CONFIG"); IupSetfAttribute(IupGetDialog(canvas), "TITLE", "%s - Simple Paint", str_filetitle(filename)); IupSetStrAttribute(canvas, "FILENAME", filename); IupSetAttribute(canvas, "DIRTY", "NO"); IupConfigRecentUpdate(config, filename); } } static int save_check(Ihandle* ih) { Ihandle* canvas = IupGetDialogChild(ih, "CANVAS"); if (IupGetInt(canvas, "DIRTY")) { switch (IupAlarm("Warning", "File not saved! Save it now?", "Yes", "No", "Cancel")) { case 1: /* save the changes and continue */ save_file(canvas); break; case 2: /* ignore the changes and continue */ break; case 3: /* cancel */ return 0; } } return 1; } static void toggle_bar_visibility(Ihandle* item, Ihandle* ih) { if (IupGetInt(item, "VALUE")) { IupSetAttribute(ih, "FLOATING", "YES"); IupSetAttribute(ih, "VISIBLE", "NO"); IupSetAttribute(item, "VALUE", "OFF"); } else { IupSetAttribute(ih, "FLOATING", "NO"); IupSetAttribute(ih, "VISIBLE", "YES"); IupSetAttribute(item, "VALUE", "ON"); } IupRefresh(ih); /* refresh the dialog layout */ } static int select_file(Ihandle* parent_dlg, int is_open) { Ihandle* config = (Ihandle*)IupGetAttribute(parent_dlg, "CONFIG"); Ihandle* canvas = IupGetDialogChild(parent_dlg, "CANVAS"); const char* dir = IupConfigGetVariableStr(config, "MainWindow", "LastDirectory"); Ihandle* filedlg = IupFileDlg(); if (is_open) IupSetAttribute(filedlg, "DIALOGTYPE", "OPEN"); else { IupSetAttribute(filedlg, "DIALOGTYPE", "SAVE"); IupSetStrAttribute(filedlg, "FILE", IupGetAttribute(canvas, "FILENAME")); } IupSetAttribute(filedlg, "EXTFILTER", "Image Files|*.bmp;*.jpg;*.png;*.tif;*.tga|All Files|*.*|"); IupSetStrAttribute(filedlg, "DIRECTORY", dir); IupSetAttributeHandle(filedlg, "PARENTDIALOG", parent_dlg); IupPopup(filedlg, IUP_CENTERPARENT, IUP_CENTERPARENT); if (IupGetInt(filedlg, "STATUS") != -1) { char* filename = IupGetAttribute(filedlg, "VALUE"); if (is_open) open_file(parent_dlg, filename); else saveas_file(canvas, filename); dir = IupGetAttribute(filedlg, "DIRECTORY"); IupConfigSetVariableStr(config, "MainWindow", "LastDirectory", dir); } IupDestroy(filedlg); return IUP_DEFAULT; } static void view_fit_rect(int canvas_width, int canvas_height, int image_width, int image_height, int *view_width, int *view_height) { *view_width = canvas_width; *view_height = (canvas_width * image_height) / image_width; if (*view_height > canvas_height) { *view_height = canvas_height; *view_width = (canvas_height * image_width) / image_height; } } static double view_zoom_rect(Ihandle* ih, int image_width, int image_height, int *_x, int *_y, int *_view_width, int *_view_height) { int x, y, canvas_width, canvas_height; int view_width, view_height; Ihandle* zoom_val = IupGetDialogChild(ih, "ZOOMVAL"); double zoom_index = IupGetDouble(zoom_val, "VALUE"); double zoom_factor = pow(2, zoom_index); float posy = IupGetFloat(ih, "POSY"); float posx = IupGetFloat(ih, "POSX"); IupGetIntInt(ih, "DRAWSIZE", &canvas_width, &canvas_height); view_width = (int)(zoom_factor * image_width); view_height = (int)(zoom_factor * image_height); if (canvas_width < view_width) x = (int)floor(-posx*view_width); else x = (canvas_width - view_width) / 2; if (canvas_height < view_height) { /* posy is top-bottom, CD is bottom-top. invert posy reference (YMAX-DY - POSY) */ float dy = IupGetFloat(ih, "DY"); posy = 1.0f - dy - posy; y = (int)floor(-posy*view_height); } else y = (canvas_height - view_height) / 2; *_x = x; *_y = y; *_view_width = view_width; *_view_height = view_height; return zoom_factor; } static void view_zoom_offset(int view_x, int view_y, int image_width, int image_height, double zoom_factor, int *x, int *y) { *x -= view_x; *y -= view_y; *x = (int)(*x / zoom_factor); *y = (int)(*y / zoom_factor); if (*x < 0) *x = 0; if (*y < 0) *y = 0; if (*x > image_width - 1) *x = image_width - 1; if (*y > image_height - 1) *y = image_height - 1; } static int tool_get_text_enter_cb(void) { return IUP_CLOSE; } static void tool_get_text(Ihandle* toolbox) { Ihandle *text, *dlg; char* value = IupGetAttribute(toolbox, "TOOLTEXT"); char* font = IupGetAttribute(toolbox, "TOOLFONT"); text = IupText(NULL); IupSetAttribute(text, "EXPAND", "YES"); IupSetStrAttribute(text, "VALUE", value); IupSetStrAttribute(text, "FONT", font); IupSetAttribute(text, "VISIBLECOLUMNS", "20"); dlg = IupDialog(text); IupSetStrAttribute(dlg, "TITLE", "Enter Text:"); IupSetAttribute(dlg, "MINBOX", "NO"); IupSetAttribute(dlg, "MAXBOX", "NO"); IupSetCallback(dlg, "K_CR", (Icallback)tool_get_text_enter_cb); IupSetAttributeHandle(dlg, "PARENTDIALOG", toolbox); IupPopup(dlg, IUP_MOUSEPOS, IUP_MOUSEPOS); value = IupGetAttribute(text, "VALUE"); IupSetStrAttribute(toolbox, "TOOLTEXT", value); IupDestroy(dlg); } static void tool_draw_pencil(Ihandle* toolbox, imImage* image, int start_x, int start_y, int end_x, int end_y) { double res = IupGetDouble(NULL, "SCREENDPI") / 25.4; unsigned char r, g, b, a; cdCanvas* rgb_canvas; int line_width = IupGetInt(toolbox, "TOOLWIDTH"); IupGetRGBA(toolbox, "TOOLCOLOR", &r, &g, &b, &a); /* do not use line style here */ rgb_canvas = cdCreateCanvas(CD_IMIMAGE, image); cdCanvasSetfAttribute(rgb_canvas, "RESOLUTION", "%g", res); cdCanvasForeground(rgb_canvas, cdEncodeColorAlpha(r, g, b, a)); cdCanvasLineWidth(rgb_canvas, line_width); cdCanvasLine(rgb_canvas, start_x, start_y, end_x, end_y); cdKillCanvas(rgb_canvas); } static void tool_draw_overlay(Ihandle* toolbox, cdCanvas* cd_canvas, int start_x, int start_y, int end_x, int end_y) { int tool_index = IupGetInt(toolbox, "TOOLINDEX"); int line_width = IupGetInt(toolbox, "TOOLWIDTH"); int line_style = IupGetInt(toolbox, "TOOLSTYLE") - 1; unsigned char r, g, b, a; IupGetRGBA(toolbox, "TOOLCOLOR", &r, &g, &b, &a); cdCanvasForeground(cd_canvas, cdEncodeColorAlpha(r, g, b, a)); cdCanvasLineWidth(cd_canvas, line_width); if (line_width == 1) cdCanvasLineStyle(cd_canvas, line_style); if (tool_index == 3) /* Line */ cdCanvasLine(cd_canvas, start_x, start_y, end_x, end_y); else if (tool_index == 4) /* Rect */ cdCanvasRect(cd_canvas, start_x, end_x, start_y, end_y); else if (tool_index == 5) /* Box */ cdCanvasBox(cd_canvas, start_x, end_x, start_y, end_y); else if (tool_index == 6) /* Ellipse */ cdCanvasArc(cd_canvas, (end_x + start_x) / 2, (end_y + start_y) / 2, abs(end_x - start_x), abs(end_y - start_y), 0, 360); else if (tool_index == 7) /* Oval */ cdCanvasSector(cd_canvas, (end_x + start_x) / 2, (end_y + start_y) / 2, abs(end_x - start_x), abs(end_y - start_y), 0, 360); else if (tool_index == 8) /* Text */ { cdCanvasTextAlignment(cd_canvas, CD_SOUTH_WEST); cdCanvasNativeFont(cd_canvas, IupGetAttribute(toolbox, "TOOLFONT")); cdCanvasText(cd_canvas, end_x, end_y, IupGetAttribute(toolbox, "TOOLTEXT")); } } /********************************** Callbacks *****************************************/ static int canvas_action_cb(Ihandle* canvas) { unsigned int ri, gi, bi; imImage* image; cdCanvas* cd_canvas = (cdCanvas*)IupGetAttribute(canvas, "cdCanvas"); Ihandle* config = (Ihandle*)IupGetAttribute(canvas, "CONFIG"); const char* background = IupConfigGetVariableStrDef(config, "Canvas", "Background", "208 208 208"); #ifdef USE_OPENGL IupGLMakeCurrent(canvas); #endif cdCanvasActivate(cd_canvas); /* draw the background */ sscanf(background, "%u %u %u", &ri, &gi, &bi); cdCanvasBackground(cd_canvas, cdEncodeColor((unsigned char)ri, (unsigned char)gi, (unsigned char)bi)); cdCanvasClear(cd_canvas); /* draw the image at the center of the canvas */ image = (imImage*)IupGetAttribute(canvas, "IMAGE"); if (image) { int x, y, view_width, view_height; view_zoom_rect(canvas, image->width, image->height, &x, &y, &view_width, &view_height); /* black line around the image cdCanvasForeground(cd_canvas, CD_BLACK); cdCanvasLineWidth(cd_canvas, 1); cdCanvasLineStyle(cd_canvas, CD_CONTINUOUS); cdCanvasRect(cd_canvas, x - 1, x + view_width, y - 1, y + view_height); */ /* Some CD drivers have interpolation options for image zoom */ /* we force NEAREST so we can see the pixel boundary in zoom in */ /* an alternative would be to set BILINEAR when zoom out */ cdCanvasSetAttribute(cd_canvas, "IMGINTERP", "NEAREST"); /* affects only drivers that have this attribute */ cdCanvasPutImImage(cd_canvas, image, x, y, view_width, view_height); if (IupConfigGetVariableInt(config, "Canvas", "ZoomGrid")) { Ihandle* zoom_val = IupGetDialogChild(canvas, "ZOOMVAL"); double zoom_index = IupGetDouble(zoom_val, "VALUE"); if (zoom_index > 1) { int ix, iy; double zoom_factor = pow(2, zoom_index); cdCanvasForeground(cd_canvas, CD_GRAY); for (ix = 0; ix <= image->width; ix++) { int gx = (int)(ix * zoom_factor); cdCanvasLine(cd_canvas, gx + x, y, gx + x, y + view_height); } for (iy = 0; iy <= image->height; iy++) { int gy = (int)(iy * zoom_factor); cdCanvasLine(cd_canvas, x, gy + y, x + view_width, gy + y); } } } if (IupGetAttribute(canvas, "OVERLAY")) { Ihandle* toolbox = (Ihandle*)IupGetAttribute(canvas, "TOOLBOX"); int start_x = IupGetInt(canvas, "START_X"); int start_y = IupGetInt(canvas, "START_Y"); int end_x = IupGetInt(canvas, "END_X"); int end_y = IupGetInt(canvas, "END_Y"); double scale_x = (double)view_width / (double)image->width; double scale_y = (double)view_height / (double)image->height; /* offset and scale drawing in screen to macth the image */ if (scale_x > 1 || scale_y > 1) { /* also draw at the center of the pixel when zoom in */ cdCanvasTransformTranslate(cd_canvas, x + scale_x / 2, y + scale_y / 2); } else cdCanvasTransformTranslate(cd_canvas, x, y); cdCanvasTransformScale(cd_canvas, scale_x, scale_y); tool_draw_overlay(toolbox, cd_canvas, start_x, start_y, end_x, end_y); cdCanvasTransform(cd_canvas, NULL); } } cdCanvasFlush(cd_canvas); #ifdef USE_OPENGL IupGLSwapBuffers(canvas); #endif return IUP_DEFAULT; } static int canvas_map_cb(Ihandle* canvas) { cdCanvas* cd_canvas; #ifdef USE_OPENGL double res = IupGetDouble(NULL, "SCREENDPI") / 25.4; IupGLMakeCurrent(canvas); cd_canvas = cdCreateCanvasf(CD_GL, "10x10 %g", res); #else #ifdef USE_CONTEXTPLUS cdUseContextPlus(1); #endif cd_canvas = cdCreateCanvas(CD_IUPDBUFFER, canvas); #ifdef USE_CONTEXTPLUS cdUseContextPlus(0); #endif #endif IupSetAttribute(canvas, "cdCanvas", (char*)cd_canvas); return IUP_DEFAULT; } static int canvas_unmap_cb(Ihandle* canvas) { cdCanvas* cd_canvas = (cdCanvas*)IupGetAttribute(canvas, "cdCanvas"); cdKillCanvas(cd_canvas); return IUP_DEFAULT; } static int zoomout_action_cb(Ihandle* ih) { Ihandle* zoom_val = IupGetDialogChild(ih, "ZOOMVAL"); double zoom_index = IupGetDouble(zoom_val, "VALUE"); zoom_index--; if (zoom_index < -6) zoom_index = -6; IupSetDouble(zoom_val, "VALUE", round(zoom_index)); /* fixed increments when using buttons */ zoom_update(ih, zoom_index); return IUP_DEFAULT; } static int zoomin_action_cb(Ihandle* ih) { Ihandle* zoom_val = IupGetDialogChild(ih, "ZOOMVAL"); double zoom_index = IupGetDouble(zoom_val, "VALUE"); zoom_index++; if (zoom_index > 6) zoom_index = 6; IupSetDouble(zoom_val, "VALUE", round(zoom_index)); /* fixed increments when using buttons */ zoom_update(ih, zoom_index); return IUP_DEFAULT; } static int actualsize_action_cb(Ihandle* ih) { Ihandle* zoom_val = IupGetDialogChild(ih, "ZOOMVAL"); IupSetDouble(zoom_val, "VALUE", 0); zoom_update(ih, 0); return IUP_DEFAULT; } static int canvas_resize_cb(Ihandle* canvas) { imImage* image = (imImage*)IupGetAttribute(canvas, "IMAGE"); if (image) { Ihandle* zoom_val = IupGetDialogChild(canvas, "ZOOMVAL"); double zoom_index = IupGetDouble(zoom_val, "VALUE"); double zoom_factor = pow(2, zoom_index); float old_center_x, old_center_y; int view_width = (int)(zoom_factor * image->width); int view_height = (int)(zoom_factor * image->height); scroll_calc_center(canvas, &old_center_x, &old_center_y); scroll_update(canvas, view_width, view_height); scroll_center(canvas, old_center_x, old_center_y); } #ifdef USE_OPENGL { int canvas_width, canvas_height; double res = IupGetDouble(NULL, "SCREENDPI") / 25.4; cdCanvas* cd_canvas = (cdCanvas*)IupGetAttribute(canvas, "cdCanvas"); IupGetIntInt(canvas, "DRAWSIZE", &canvas_width, &canvas_height); IupGLMakeCurrent(canvas); cdCanvasSetfAttribute(cd_canvas, "SIZE", "%dx%d %g", canvas_width, canvas_height, res); } #endif return IUP_DEFAULT; } static int canvas_wheel_cb(Ihandle* canvas, float delta) { if (IupGetInt(NULL, "CONTROLKEY")) { if (delta < 0) zoomout_action_cb(canvas); else zoomin_action_cb(canvas); } else { float posy = IupGetFloat(canvas, "POSY"); posy -= delta * IupGetFloat(canvas, "DY") / 10.0f; IupSetFloat(canvas, "POSY", posy); IupUpdate(canvas); } return IUP_DEFAULT; } static int canvas_button_cb(Ihandle* canvas, int button, int pressed, int x, int y) { imImage* image = (imImage*)IupGetAttribute(canvas, "IMAGE"); if (image) { int cursor_x = x, cursor_y = y; int view_x, view_y, view_width, view_height; double zoom_factor = view_zoom_rect(canvas, image->width, image->height, &view_x, &view_y, &view_width, &view_height); /* y is top-down in IUP */ int canvas_height = IupGetInt2(canvas, "DRAWSIZE"); y = canvas_height - y - 1; /* inside image area */ if (x > view_x && y > view_y && x < view_x + view_width && y < view_y + view_height) { view_zoom_offset(view_x, view_y, image->width, image->height, zoom_factor, &x, &y); if (button == IUP_BUTTON1) { Ihandle* toolbox = (Ihandle*)IupGetAttribute(canvas, "TOOLBOX"); int tool_index = IupGetInt(toolbox, "TOOLINDEX"); if (pressed) { IupSetInt(canvas, "START_X", x); IupSetInt(canvas, "START_Y", y); IupSetInt(canvas, "START_CURSOR_X", cursor_x); IupSetInt(canvas, "START_CURSOR_Y", cursor_y); if (tool_index == 8) /* Text */ { IupSetInt(canvas, "END_X", x); IupSetInt(canvas, "END_Y", y); IupSetAttribute(canvas, "OVERLAY", "Yes"); IupRedraw(canvas, 0); } } else { if (tool_index == 1) /* Color Picker */ { Ihandle* color = IupGetDialogChild(toolbox, "COLOR"); unsigned char** data = (unsigned char**)image->data; unsigned char r, g, b, a = 255; int offset; offset = y * image->width + x; r = data[0][offset]; g = data[1][offset]; b = data[2][offset]; if (image->has_alpha) a = data[3][offset]; IupSetRGB(color, "BGCOLOR", r, g, b); IupSetRGBA(toolbox, "TOOLCOLOR", r, g, b, a); } else if (tool_index == 2) /* Pencil */ { int start_x = IupGetInt(canvas, "START_X"); int start_y = IupGetInt(canvas, "START_Y"); tool_draw_pencil(toolbox, image, start_x, start_y, x, y); IupSetAttribute(canvas, "DIRTY", "Yes"); IupUpdate(canvas); IupSetInt(canvas, "START_X", x); IupSetInt(canvas, "START_Y", y); } else if (tool_index >= 3 && tool_index <= 8) /* Shapes */ { if (IupGetAttribute(canvas, "OVERLAY")) { int start_x = IupGetInt(canvas, "START_X"); int start_y = IupGetInt(canvas, "START_Y"); double res = IupGetDouble(NULL, "SCREENDPI") / 25.4; cdCanvas* rgb_canvas = cdCreateCanvas(CD_IMIMAGE, image); cdCanvasSetfAttribute(rgb_canvas, "RESOLUTION", "%g", res); tool_draw_overlay(toolbox, rgb_canvas, start_x, start_y, x, y); cdKillCanvas(rgb_canvas); IupSetAttribute(canvas, "OVERLAY", NULL); IupSetAttribute(canvas, "DIRTY", "Yes"); IupUpdate(canvas); } } else if (tool_index == 9) /* Fill Color */ { double tol_percent = IupGetDouble(toolbox, "TOOLFILLTOL"); unsigned char r, g, b, a; IupGetRGBA(toolbox, "TOOLCOLOR", &r, &g, &b, &a); image_flood_fill(image, x, y, cdEncodeColorAlpha(r, g, b, a), tol_percent); IupSetAttribute(canvas, "DIRTY", "Yes"); IupUpdate(canvas); } } } else if (button == IUP_BUTTON3) { if (!pressed) { Ihandle* toolbox = (Ihandle*)IupGetAttribute(canvas, "TOOLBOX"); int tool_index = IupGetInt(toolbox, "TOOLINDEX"); if (tool_index == 8) /* Text */ tool_get_text(toolbox); } } } } return IUP_DEFAULT; } static int canvas_motion_cb(Ihandle* canvas, int x, int y, char *status) { imImage* image = (imImage*)IupGetAttribute(canvas, "IMAGE"); if (image) { int cursor_x = x, cursor_y = y; int view_x, view_y, view_width, view_height; double zoom_factor = view_zoom_rect(canvas, image->width, image->height, &view_x, &view_y, &view_width, &view_height); /* y is top-down in IUP */ int canvas_height = IupGetInt2(canvas, "DRAWSIZE"); y = canvas_height - y - 1; /* inside image area */ if (x > view_x && y > view_y && x < view_x + view_width && y < view_y + view_height) { Ihandle* status_lbl = IupGetDialogChild(canvas, "STATUSLABEL"); unsigned char** data = (unsigned char**)image->data; unsigned char r, g, b; int offset; view_zoom_offset(view_x, view_y, image->width, image->height, zoom_factor, &x, &y); offset = y * image->width + x; r = data[0][offset]; g = data[1][offset]; b = data[2][offset]; if (image->has_alpha) { unsigned char a = data[3][offset]; IupSetStrf(status_lbl, "TITLE", "(%4d, %4d) = %3d %3d %3d %3d", x, y, (int)r, (int)g, (int)b, (int)a); } else IupSetStrf(status_lbl, "TITLE", "(%4d, %4d) = %3d %3d %3d", x, y, (int)r, (int)g, (int)b); if (iup_isbutton1(status)) /* button1 is pressed */ { Ihandle* toolbox = (Ihandle*)IupGetAttribute(canvas, "TOOLBOX"); int tool_index = IupGetInt(toolbox, "TOOLINDEX"); if (tool_index == 0) /* Pointer */ { int start_cursor_x = IupGetInt(canvas, "START_CURSOR_X"); int start_cursor_y = IupGetInt(canvas, "START_CURSOR_Y"); int canvas_width = IupGetInt(canvas, "DRAWSIZE"); scroll_move(canvas, canvas_width, canvas_height, cursor_x - start_cursor_x, cursor_y - start_cursor_y, view_width, view_height); IupSetInt(canvas, "START_CURSOR_X", cursor_x); IupSetInt(canvas, "START_CURSOR_Y", cursor_y); } else if (tool_index == 2) /* Pencil */ { int start_x = IupGetInt(canvas, "START_X"); int start_y = IupGetInt(canvas, "START_Y"); tool_draw_pencil(toolbox, image, start_x, start_y, x, y); IupSetAttribute(canvas, "DIRTY", "Yes"); IupRedraw(canvas, 0); IupSetInt(canvas, "START_X", x); IupSetInt(canvas, "START_Y", y); } else if (tool_index >= 3 && tool_index <= 8) /* Shapes */ { IupSetInt(canvas, "END_X", x); IupSetInt(canvas, "END_Y", y); IupSetAttribute(canvas, "OVERLAY", "Yes"); IupRedraw(canvas, 0); } } } } return IUP_DEFAULT; } static int zoom_valuechanged_cb(Ihandle* val) { double zoom_index = IupGetDouble(val, "VALUE"); zoom_update(val, zoom_index); return IUP_DEFAULT; } static int dropfiles_cb(Ihandle* ih, const char* filename) { if (save_check(ih)) open_file(ih, filename); return IUP_DEFAULT; } static int file_menu_open_cb(Ihandle* ih) { Ihandle* item_revert = IupGetDialogChild(ih, "ITEM_REVERT"); Ihandle* item_save = IupGetDialogChild(ih, "ITEM_SAVE"); Ihandle* canvas = IupGetDialogChild(ih, "CANVAS"); char* filename = IupGetAttribute(canvas, "FILENAME"); int dirty = IupGetInt(canvas, "DIRTY"); if (dirty) IupSetAttribute(item_save, "ACTIVE", "YES"); else IupSetAttribute(item_save, "ACTIVE", "NO"); if (dirty && filename) IupSetAttribute(item_revert, "ACTIVE", "YES"); else IupSetAttribute(item_revert, "ACTIVE", "NO"); return IUP_DEFAULT; } static int edit_menu_open_cb(Ihandle* ih) { Ihandle *clipboard = IupClipboard(); Ihandle *item_paste = IupGetDialogChild(ih, "ITEM_PASTE"); if (!IupGetInt(clipboard, "IMAGEAVAILABLE")) IupSetAttribute(item_paste, "ACTIVE", "NO"); else IupSetAttribute(item_paste, "ACTIVE", "YES"); IupDestroy(clipboard); return IUP_DEFAULT; } static int config_recent_cb(Ihandle* ih) { if (save_check(ih)) { char* filename = IupGetAttribute(ih, "RECENTFILENAME"); open_file(ih, filename); } return IUP_DEFAULT; } static int item_new_action_cb(Ihandle* item_new) { if (save_check(item_new)) { Ihandle* canvas = IupGetDialogChild(item_new, "CANVAS"); Ihandle* config = (Ihandle*)IupGetAttribute(canvas, "CONFIG"); int width = IupConfigGetVariableIntDef(config, "NewImage", "Width", 640); int height = IupConfigGetVariableIntDef(config, "NewImage", "Height", 480); int has_alpha = IupConfigGetVariableIntDef(config, "NewImage", "HasAlpha", 0); if (IupGetParam("New Image", NULL, NULL, "Width: %i[1,]\n" "Height: %i[1,]\n" "Has Alpha: %b\n", &width, &height, &has_alpha, NULL)) { imImage* image = imImageCreate(width, height, IM_RGB, IM_BYTE); if (!image) { show_file_error(IM_ERR_MEM); return IUP_DEFAULT; } if (has_alpha) imImageAddAlpha(image); image_fill_white(image); IupConfigSetVariableInt(config, "NewImage", "Width", width); IupConfigSetVariableInt(config, "NewImage", "Height", height); IupConfigSetVariableInt(config, "NewImage", "HasAlpha", has_alpha); set_new_image(canvas, image, NULL, 0); } } return IUP_DEFAULT; } static int item_open_action_cb(Ihandle* item_open) { if (!save_check(item_open)) return IUP_DEFAULT; return select_file(IupGetDialog(item_open), 1); } static int item_saveas_action_cb(Ihandle* item_saveas) { return select_file(IupGetDialog(item_saveas), 0); } static int item_save_action_cb(Ihandle* item_save) { Ihandle* canvas = IupGetDialogChild(item_save, "CANVAS"); char* filename = IupGetAttribute(canvas, "FILENAME"); if (!filename) item_saveas_action_cb(item_save); else { /* test again because in can be called using the hot key */ int dirty = IupGetInt(canvas, "DIRTY"); if (dirty) save_file(canvas); } return IUP_DEFAULT; } static int item_revert_action_cb(Ihandle* item_revert) { Ihandle* canvas = IupGetDialogChild(item_revert, "CANVAS"); char* filename = IupGetAttribute(canvas, "FILENAME"); open_file(item_revert, filename); return IUP_DEFAULT; } static int item_pagesetup_action_cb(Ihandle* item_pagesetup) { Ihandle* canvas = IupGetDialogChild(item_pagesetup, "CANVAS"); Ihandle* config = (Ihandle*)IupGetAttribute(canvas, "CONFIG"); int margin_width = IupConfigGetVariableIntDef(config, "Print", "MarginWidth", 20); int margin_height = IupConfigGetVariableIntDef(config, "Print", "MarginHeight", 20); if (IupGetParam("Page Setup", NULL, NULL, "Margin Width (mm): %i[1,]\nMargin Height (mm): %i[1,]\n", &margin_width, &margin_height, NULL)) { IupConfigSetVariableInt(config, "Print", "MarginWidth", margin_width); IupConfigSetVariableInt(config, "Print", "MarginHeight", margin_height); } return IUP_DEFAULT; } static int item_print_action_cb(Ihandle* item_print) { Ihandle* canvas = IupGetDialogChild(item_print, "CANVAS"); imImage* image; char* title = IupGetAttribute(IupGetDialog(item_print), "TITLE"); cdCanvas* print_canvas = cdCreateCanvasf(CD_PRINTER, "%s -d", title); if (!print_canvas) return IUP_DEFAULT; /* do NOT draw the background, use the paper color */ /* draw the image at the center of the canvas */ image = (imImage*)IupGetAttribute(canvas, "IMAGE"); if (image) { int x, y, canvas_width, canvas_height, view_width, view_height; double canvas_width_mm, canvas_height_mm; Ihandle* config = (Ihandle*)IupGetAttribute(canvas, "CONFIG"); int margin_width = IupConfigGetVariableIntDef(config, "Print", "MarginWidth", 20); int margin_height = IupConfigGetVariableIntDef(config, "Print", "MarginHeight", 20); cdCanvasGetSize(print_canvas, &canvas_width, &canvas_height, &canvas_width_mm, &canvas_height_mm); /* convert to pixels */ margin_width = (int)((margin_width * canvas_width) / canvas_width_mm); margin_height = (int)((margin_height * canvas_height) / canvas_height_mm); view_fit_rect(canvas_width - 2 * margin_width, canvas_height - 2 * margin_height, image->width, image->height, &view_width, &view_height); x = (canvas_width - view_width) / 2; y = (canvas_height - view_height) / 2; cdCanvasPutImImage(print_canvas, image, x, y, view_width, view_height); } cdKillCanvas(print_canvas); return IUP_DEFAULT; } static int item_exit_action_cb(Ihandle* item_exit) { Ihandle* dlg = IupGetDialog(item_exit); Ihandle* config = (Ihandle*)IupGetAttribute(dlg, "CONFIG"); Ihandle* canvas = IupGetDialogChild(dlg, "CANVAS"); imImage* image = (imImage*)IupGetAttribute(canvas, "IMAGE"); Ihandle* toolbox = (Ihandle*)IupGetAttribute(dlg, "TOOLBOX"); if (!save_check(item_exit)) return IUP_IGNORE; /* to abort the CLOSE_CB callback */ if (IupGetInt(toolbox, "VISIBLE")) { IupConfigDialogClosed(config, toolbox, "Toolbox"); IupHide(toolbox); } if (image) imImageDestroy(image); IupConfigDialogClosed(config, dlg, "MainWindow"); IupConfigSave(config); IupDestroy(config); return IUP_CLOSE; } static int item_copy_action_cb(Ihandle* item_copy) { Ihandle* canvas = IupGetDialogChild(item_copy, "CANVAS"); imImage* image = (imImage*)IupGetAttribute(canvas, "IMAGE"); Ihandle *clipboard = IupClipboard(); IupSetAttribute(clipboard, "NATIVEIMAGE", (char*)IupGetImageNativeHandle(image)); IupDestroy(clipboard); return IUP_DEFAULT; } static int item_paste_action_cb(Ihandle* item_paste) { if (save_check(item_paste)) { Ihandle* canvas = IupGetDialogChild(item_paste, "CANVAS"); Ihandle *clipboard = IupClipboard(); imImage* image = IupGetNativeHandleImage(IupGetAttribute(clipboard, "NATIVEIMAGE")); IupDestroy(clipboard); if (!image) { show_error("Invalid Clipboard Data", 1); return IUP_DEFAULT; } set_new_image(canvas, image, NULL, 1); /* set dirty */ } return IUP_DEFAULT; } static int item_background_action_cb(Ihandle* item_background) { Ihandle* canvas = IupGetDialogChild(item_background, "CANVAS"); Ihandle* config = (Ihandle*)IupGetAttribute(canvas, "CONFIG"); Ihandle* colordlg = IupColorDlg(); const char* background = IupConfigGetVariableStrDef(config, "Canvas", "Background", "208 208 208"); IupSetStrAttribute(colordlg, "VALUE", background); IupSetAttributeHandle(colordlg, "PARENTDIALOG", IupGetDialog(item_background)); IupPopup(colordlg, IUP_CENTERPARENT, IUP_CENTERPARENT); if (IupGetInt(colordlg, "STATUS") == 1) { background = IupGetAttribute(colordlg, "VALUE"); IupConfigSetVariableStr(config, "Canvas", "Background", background); IupUpdate(canvas); } IupDestroy(colordlg); return IUP_DEFAULT; } static int item_zoomgrid_action_cb(Ihandle* ih) { Ihandle* item_zoomgrid = IupGetDialogChild(ih, "ZOOMGRID"); Ihandle* canvas = IupGetDialogChild(ih, "CANVAS"); Ihandle* config = (Ihandle*)IupGetAttribute(ih, "CONFIG"); if (IupGetInt(item_zoomgrid, "VALUE")) IupSetAttribute(item_zoomgrid, "VALUE", "OFF"); else IupSetAttribute(item_zoomgrid, "VALUE", "ON"); IupConfigSetVariableStr(config, "Canvas", "ZoomGrid", IupGetAttribute(item_zoomgrid, "VALUE")); IupUpdate(canvas); return IUP_DEFAULT; } static int item_toolbar_action_cb(Ihandle* item_toolbar) { Ihandle* toolbar = IupGetDialogChild(item_toolbar, "TOOLBAR"); Ihandle* config = (Ihandle*)IupGetAttribute(item_toolbar, "CONFIG"); toggle_bar_visibility(item_toolbar, toolbar); IupConfigSetVariableStr(config, "MainWindow", "Toolbar", IupGetAttribute(item_toolbar, "VALUE")); return IUP_DEFAULT; } static int item_toolbox_action_cb(Ihandle* item_toolbox) { Ihandle* toolbox = (Ihandle*)IupGetAttribute(item_toolbox, "TOOLBOX"); Ihandle* config = (Ihandle*)IupGetAttribute(item_toolbox, "CONFIG"); if (IupGetInt(toolbox, "VISIBLE")) { IupSetAttribute(item_toolbox, "VALUE", "OFF"); IupConfigDialogClosed(config, toolbox, "Toolbox"); IupHide(toolbox); } else { IupSetAttribute(item_toolbox, "VALUE", "ON"); IupConfigDialogShow(config, toolbox, "Toolbox"); } IupConfigSetVariableStr(config, "MainWindow", "Toolbox", IupGetAttribute(item_toolbox, "VALUE")); return IUP_DEFAULT; } static int item_statusbar_action_cb(Ihandle* item_statusbar) { Ihandle* statusbar = IupGetDialogChild(item_statusbar, "STATUSBAR"); Ihandle* config = (Ihandle*)IupGetAttribute(item_statusbar, "CONFIG"); toggle_bar_visibility(item_statusbar, statusbar); IupConfigSetVariableStr(config, "MainWindow", "Statusbar", IupGetAttribute(item_statusbar, "VALUE")); return IUP_DEFAULT; } static int item_help_action_cb(void) { IupHelp("http://www.tecgraf.puc-rio.br/iup"); return IUP_DEFAULT; } static int item_about_action_cb(void) { IupMessage("About", " Simple Paint\n\nAuthors:\n Gustavo Lyrio\n Antonio Scuri"); return IUP_DEFAULT; } static int toolbox_close_cb(Ihandle* toolbox) { Ihandle* config = (Ihandle*)IupGetAttribute(toolbox, "CONFIG"); Ihandle* canvas = (Ihandle*)IupGetAttribute(toolbox, "CANVAS"); Ihandle* item_toolbox = IupGetDialogChild(canvas, "TOOLBOXMENU"); IupConfigDialogClosed(config, toolbox, "Toolbox"); IupSetAttribute(item_toolbox, "VALUE", "OFF"); IupConfigSetVariableStr(config, "MainWindow", "Toolbox", "OFF"); return IUP_DEFAULT; } static int tool_action_cb(Ihandle* ih, int state) { if (state == 1) { Ihandle* canvas = (Ihandle*)IupGetAttribute(ih, "CANVAS"); int tool_index = IupGetInt(ih, "TOOLINDEX"); IupSetInt(IupGetDialog(ih), "TOOLINDEX", tool_index); if (tool_index == 0) IupSetAttribute(canvas, "CURSOR", "ARROW"); else IupSetAttribute(canvas, "CURSOR", "CROSS"); if (tool_index == 8) tool_get_text(IupGetDialog(ih)); } return IUP_DEFAULT; } static int toolcolor_action_cb(Ihandle* ih) { Ihandle* toolbox = IupGetDialog(ih); Ihandle* colordlg = IupColorDlg(); Ihandle* canvas = (Ihandle*)IupGetAttribute(toolbox, "CANVAS"); imImage* image = (imImage*)IupGetAttribute(canvas, "IMAGE"); const char* color = IupGetAttribute(toolbox, "TOOLCOLOR"); IupSetStrAttribute(colordlg, "VALUE", color); IupSetAttributeHandle(colordlg, "PARENTDIALOG", toolbox); if (image->has_alpha) IupSetStrAttribute(colordlg, "SHOWALPHA", "Yes"); IupPopup(colordlg, IUP_CENTER, IUP_CENTER); if (IupGetInt(colordlg, "STATUS") == 1) { color = IupGetAttribute(colordlg, "VALUE"); IupSetStrAttribute(toolbox, "TOOLCOLOR", color); IupSetStrAttribute(ih, "BGCOLOR", color); } IupDestroy(colordlg); return IUP_DEFAULT; } static int toolwidth_valuechanged_cb(Ihandle* ih) { char* value = IupGetAttribute(ih, "VALUE"); IupSetStrAttribute(IupGetDialog(ih), "TOOLWIDTH", value); return IUP_DEFAULT; } static int toolstyle_valuechanged_cb(Ihandle* ih) { char* value = IupGetAttribute(ih, "VALUE"); IupSetStrAttribute(IupGetDialog(ih), "TOOLSTYLE", value); return IUP_DEFAULT; } static int toolfont_action_cb(Ihandle* ih) { Ihandle* font_dlg = IupFontDlg(); char* font = IupGetAttribute(ih, "TOOLFONT"); IupSetAttributeHandle(font_dlg, "PARENTDIALOG", IupGetDialog(ih)); IupSetStrAttribute(font_dlg, "VALUE", font); IupPopup(font_dlg, IUP_CENTER, IUP_CENTER); if (IupGetInt(font_dlg, "STATUS") == 1) { font = IupGetAttribute(font_dlg, "VALUE"); IupSetStrAttribute(IupGetDialog(ih), "TOOLFONT", font); } IupDestroy(font_dlg); return IUP_DEFAULT; } static int toolfilltol_valuechanged_cb(Ihandle* ih) { Ihandle* filltol_label = IupGetDialogChild(ih, "FILLTOLLABEL"); double value = IupGetDouble(ih, "VALUE"); IupSetStrf(filltol_label, "TITLE", "Tol.: %.0f%%", value); IupSetDouble(IupGetDialog(ih), "TOOLFILLTOL", value); return IUP_DEFAULT; } static int main_dlg_move_cb(Ihandle* dlg, int x, int y) { Ihandle* toolbox = (Ihandle*)IupGetAttribute(dlg, "TOOLBOX"); int old_x = IupGetInt(dlg, "_OLD_X"); int old_y = IupGetInt(dlg, "_OLD_Y"); if (old_x == x && old_y == y) return IUP_DEFAULT; if (IupGetInt(toolbox, "VISIBLE")) { int tb_x = IupGetInt(toolbox, "X"); int tb_y = IupGetInt(toolbox, "Y"); tb_x += x - old_x; tb_y += y - old_y; IupShowXY(toolbox, tb_x, tb_y); } IupSetInt(dlg, "_OLD_X", x); IupSetInt(dlg, "_OLD_Y", y); return IUP_DEFAULT; } static int item_resize_action_cb(Ihandle* ih) { Ihandle* config = (Ihandle*)IupGetAttribute(ih, "CONFIG"); Ihandle* canvas = IupGetDialogChild(ih, "CANVAS"); imImage* image = (imImage*)IupGetAttribute(canvas, "IMAGE"); imImage* new_image; int height = image->height, width = image->width; int quality = IupConfigGetVariableIntDef(config, "Image", "ResizeQuality", 1); /* medium default */ if (!IupGetParam("Resize", NULL, NULL, "Width: %i[1,]\n" "Height: %i[1,]\n" "Quality: %l|low|medium|high|\n", &width, &height, &quality, NULL)) return IUP_DEFAULT; IupConfigSetVariableInt(config, "Image", "ResizeQuality", quality); new_image = imImageCreateBased(image, width, height, -1, -1); if (!new_image) { show_file_error(IM_ERR_MEM); return IUP_DEFAULT; } if (quality == 2) quality = 3; /* interpolation order can be 0, 1, and 3 */ imProcessResize(image, new_image, quality); update_image(canvas, new_image, 1); /* update size */ return IUP_DEFAULT; } static int item_mirror_action_cb(Ihandle* ih) { Ihandle* canvas = IupGetDialogChild(ih, "CANVAS"); imImage* image = (imImage*)IupGetAttribute(canvas, "IMAGE"); imImage* new_image = imImageClone(image); if (!new_image) { show_file_error(IM_ERR_MEM); return IUP_DEFAULT; } imProcessMirror(image, new_image); update_image(canvas, new_image, 0); return IUP_DEFAULT; } static int item_flip_action_cb(Ihandle* ih) { Ihandle* canvas = IupGetDialogChild(ih, "CANVAS"); imImage* image = (imImage*)IupGetAttribute(canvas, "IMAGE"); imImage* new_image = imImageClone(image); if (!new_image) { show_file_error(IM_ERR_MEM); return IUP_DEFAULT; } imProcessFlip(image, new_image); update_image(canvas, new_image, 0); return IUP_DEFAULT; } static int item_rotate180_action_cb(Ihandle* ih) { Ihandle* canvas = IupGetDialogChild(ih, "CANVAS"); imImage* image = (imImage*)IupGetAttribute(canvas, "IMAGE"); imImage* new_image = imImageClone(image); if (!new_image) { show_file_error(IM_ERR_MEM); return IUP_DEFAULT; } imProcessRotate180(image, new_image); update_image(canvas, new_image, 0); return IUP_DEFAULT; } static int item_rotate90cw_action_cb(Ihandle* ih) { Ihandle* canvas = IupGetDialogChild(ih, "CANVAS"); imImage* image = (imImage*)IupGetAttribute(canvas, "IMAGE"); imImage* new_image = imImageCreateBased(image, image->height, image->width, -1, -1); if (!new_image) { show_file_error(IM_ERR_MEM); return IUP_DEFAULT; } imProcessRotate90(image, new_image, 1); update_image(canvas, new_image, 1); /* update size */ return IUP_DEFAULT; } static int item_rotate90ccw_action_cb(Ihandle* ih) { Ihandle* canvas = IupGetDialogChild(ih, "CANVAS"); imImage* image = (imImage*)IupGetAttribute(canvas, "IMAGE"); imImage* new_image = imImageCreateBased(image, image->height, image->width, -1, -1); if (!new_image) { show_file_error(IM_ERR_MEM); return IUP_DEFAULT; } imProcessRotate90(image, new_image, -1); update_image(canvas, new_image, 1); /* update size */ return IUP_DEFAULT; } static int item_negative_action_cb(Ihandle* ih) { Ihandle* canvas = IupGetDialogChild(ih, "CANVAS"); imImage* image = (imImage*)IupGetAttribute(canvas, "IMAGE"); imImage* new_image = imImageClone(image); if (!new_image) { show_file_error(IM_ERR_MEM); return IUP_DEFAULT; } imProcessNegative(image, new_image); update_image(canvas, new_image, 0); return IUP_DEFAULT; } static int brightcont_param_cb(Ihandle* dialog, int param_index, void* user_data) { Ihandle* canvas = (Ihandle*)user_data; if (param_index == 0 || param_index == 1) { double param[2] = { 0, 0 }; imImage* image = (imImage*)IupGetAttribute(canvas, "ORIGINAL_IMAGE"); imImage* new_image = (imImage*)IupGetAttribute(canvas, "NEW_IMAGE"); Ihandle* brightness_shift_param = (Ihandle*)IupGetAttribute(dialog, "PARAM0"); Ihandle* contrast_factor_param = (Ihandle*)IupGetAttribute(dialog, "PARAM1"); param[0] = IupGetDouble(brightness_shift_param, "VALUE"); param[1] = IupGetDouble(contrast_factor_param, "VALUE"); imProcessToneGamut(image, new_image, IM_GAMUT_BRIGHTCONT, param); IupSetAttribute(canvas, "IMAGE", (char*)new_image); IupRedraw(canvas, 0); } else if (param_index != IUP_GETPARAM_INIT && param_index != IUP_GETPARAM_MAP) { /* restore original configuration */ imImage* image = (imImage*)IupGetAttribute(canvas, "ORIGINAL_IMAGE"); IupSetAttribute(canvas, "IMAGE", (char*)image); IupSetAttribute(canvas, "ORIGINAL_IMAGE", NULL); IupSetAttribute(canvas, "NEW_IMAGE", NULL); if (param_index == IUP_GETPARAM_BUTTON2) /* cancel */ IupUpdate(canvas); } return 1; } static int item_brightcont_action_cb(Ihandle* ih) { double param[2] = { 0, 0 }; Ihandle* canvas = IupGetDialogChild(ih, "CANVAS"); imImage* image = (imImage*)IupGetAttribute(canvas, "IMAGE"); imImage* new_image = imImageClone(image); if (!new_image) { show_file_error(IM_ERR_MEM); return IUP_DEFAULT; } IupSetAttribute(canvas, "ORIGINAL_IMAGE", (char*)image); IupSetAttribute(canvas, "NEW_IMAGE", (char*)new_image); if (!IupGetParam("Brightness and Contrast", brightcont_param_cb, canvas, "Brightness Shift: %R[-100,100]\n" "Contrast Factor: %R[-100,100]\n", ¶m[0], ¶m[1], NULL)) { imImageDestroy(new_image); return IUP_DEFAULT; } imProcessToneGamut(image, new_image, IM_GAMUT_BRIGHTCONT, param); update_image(canvas, new_image, 0); return IUP_DEFAULT; } /********************************** Main *****************************************/ static Ihandle* create_main_menu(Ihandle *config) { Ihandle *menu, *sub_menu_file; Ihandle *file_menu, *item_exit, *item_new, *item_open, *item_save, *item_saveas, *item_revert; Ihandle *sub_menu_edit, *edit_menu, *item_copy, *item_paste, *item_print, *item_pagesetup; Ihandle *sub_menu_help, *help_menu, *item_help, *item_about; Ihandle *sub_menu_view, *view_menu, *item_toolbar, *item_statusbar; Ihandle *item_zoomin, *item_zoomout, *item_actualsize; Ihandle *recent_menu, *item_background, *item_toolbox, *item_zoomgrid; Ihandle *sub_menu_image, *image_menu; item_new = IupItem("&New\tCtrl+N", NULL); IupSetAttribute(item_new, "IMAGE", "IUP_FileNew"); IupSetCallback(item_new, "ACTION", (Icallback)item_new_action_cb); item_open = IupItem("&Open...\tCtrl+O", NULL); IupSetAttribute(item_open, "IMAGE", "IUP_FileOpen"); IupSetCallback(item_open, "ACTION", (Icallback)item_open_action_cb); item_save = IupItem("&Save\tCtrl+S", NULL); IupSetAttribute(item_save, "NAME", "ITEM_SAVE"); IupSetAttribute(item_save, "IMAGE", "IUP_FileSave"); IupSetCallback(item_save, "ACTION", (Icallback)item_save_action_cb); item_saveas = IupItem("Save &As...", NULL); IupSetAttribute(item_saveas, "NAME", "ITEM_SAVEAS"); IupSetCallback(item_saveas, "ACTION", (Icallback)item_saveas_action_cb); item_revert = IupItem("&Revert", NULL); IupSetAttribute(item_revert, "NAME", "ITEM_REVERT"); IupSetCallback(item_revert, "ACTION", (Icallback)item_revert_action_cb); item_pagesetup = IupItem("Page Set&up...", NULL); IupSetCallback(item_pagesetup, "ACTION", (Icallback)item_pagesetup_action_cb); item_print = IupItem("&Print...\tCtrl+P", NULL); IupSetCallback(item_print, "ACTION", (Icallback)item_print_action_cb); item_exit = IupItem("E&xit", NULL); IupSetCallback(item_exit, "ACTION", (Icallback)item_exit_action_cb); item_copy = IupItem("&Copy\tCtrl+C", NULL); IupSetAttribute(item_copy, "NAME", "ITEM_COPY"); IupSetAttribute(item_copy, "IMAGE", "IUP_EditCopy"); IupSetCallback(item_copy, "ACTION", (Icallback)item_copy_action_cb); item_paste = IupItem("&Paste\tCtrl+V", NULL); IupSetAttribute(item_paste, "NAME", "ITEM_PASTE"); IupSetAttribute(item_paste, "IMAGE", "IUP_EditPaste"); IupSetCallback(item_paste, "ACTION", (Icallback)item_paste_action_cb); item_zoomin = IupItem("Zoom &In\tCtrl++", NULL); IupSetAttribute(item_zoomin, "IMAGE", "IUP_ZoomIn"); IupSetCallback(item_zoomin, "ACTION", (Icallback)zoomin_action_cb); item_zoomout = IupItem("Zoom &Out\tCtrl+-", NULL); IupSetAttribute(item_zoomout, "IMAGE", "IUP_ZoomOut"); IupSetCallback(item_zoomout, "ACTION", (Icallback)zoomout_action_cb); item_actualsize = IupItem("&Actual Size\tCtrl+0", NULL); IupSetAttribute(item_actualsize, "IMAGE", "IUP_ZoomActualSize"); IupSetCallback(item_actualsize, "ACTION", (Icallback)actualsize_action_cb); item_zoomgrid = IupItem("&Zoom Grid", NULL); IupSetCallback(item_zoomgrid, "ACTION", (Icallback)item_zoomgrid_action_cb); IupSetAttribute(item_zoomgrid, "NAME", "ZOOMGRID"); IupSetAttribute(item_zoomgrid, "VALUE", "ON"); /* default is ON */ item_background = IupItem("&Background...", NULL); IupSetCallback(item_background, "ACTION", (Icallback)item_background_action_cb); item_toolbar = IupItem("&Toobar", NULL); IupSetCallback(item_toolbar, "ACTION", (Icallback)item_toolbar_action_cb); IupSetAttribute(item_toolbar, "VALUE", "ON"); /* default is ON */ item_toolbox = IupItem("&Toobox", NULL); IupSetCallback(item_toolbox, "ACTION", (Icallback)item_toolbox_action_cb); IupSetAttribute(item_toolbox, "NAME", "TOOLBOXMENU"); IupSetAttribute(item_toolbox, "VALUE", "ON"); /* default is ON */ item_statusbar = IupItem("&Statusbar", NULL); IupSetCallback(item_statusbar, "ACTION", (Icallback)item_statusbar_action_cb); IupSetAttribute(item_statusbar, "VALUE", "ON"); /* default is ON */ item_help = IupItem("&Help...", NULL); IupSetCallback(item_help, "ACTION", (Icallback)item_help_action_cb); item_about = IupItem("&About...", NULL); IupSetCallback(item_about, "ACTION", (Icallback)item_about_action_cb); recent_menu = IupMenu(NULL); file_menu = IupMenu( item_new, item_open, item_save, item_saveas, item_revert, IupSeparator(), item_pagesetup, item_print, IupSeparator(), IupSubmenu("Recent &Files", recent_menu), IupSeparator(), item_exit, NULL); edit_menu = IupMenu( item_copy, item_paste, NULL); view_menu = IupMenu( item_zoomin, item_zoomout, item_actualsize, item_zoomgrid, IupSeparator(), item_background, IupSeparator(), item_toolbar, item_toolbox, item_statusbar, NULL); image_menu = IupMenu( IupSetCallbacks(IupItem("&Resize...", NULL), "ACTION", item_resize_action_cb, NULL), IupSetCallbacks(IupItem("&Mirror", NULL), "ACTION", item_mirror_action_cb, NULL), IupSetCallbacks(IupItem("&Flip", NULL), "ACTION", item_flip_action_cb, NULL), IupSetCallbacks(IupItem("&Rotate 180º", NULL), "ACTION", item_rotate180_action_cb, NULL), IupSetCallbacks(IupItem("&Rotate +90º (clock-wise)", NULL), "ACTION", item_rotate90cw_action_cb, NULL), IupSetCallbacks(IupItem("&Rotate -90º (counter-clock)", NULL), "ACTION", item_rotate90ccw_action_cb, NULL), IupSeparator(), IupSetCallbacks(IupItem("&Negative", NULL), "ACTION", item_negative_action_cb, NULL), IupSetCallbacks(IupItem("&Brightness and Contrast...", NULL), "ACTION", item_brightcont_action_cb, NULL), NULL); help_menu = IupMenu( item_help, item_about, NULL); IupSetCallback(file_menu, "OPEN_CB", (Icallback)file_menu_open_cb); IupSetCallback(edit_menu, "OPEN_CB", (Icallback)edit_menu_open_cb); sub_menu_file = IupSubmenu("&File", file_menu); sub_menu_edit = IupSubmenu("&Edit", edit_menu); sub_menu_view = IupSubmenu("&View", view_menu); sub_menu_image = IupSubmenu("&Image", image_menu); sub_menu_help = IupSubmenu("&Help", help_menu); menu = IupMenu( sub_menu_file, sub_menu_edit, sub_menu_view, sub_menu_image, sub_menu_help, NULL); /* Initialize variables from the configuration file */ IupConfigRecentInit(config, recent_menu, config_recent_cb, 10); if (!IupConfigGetVariableIntDef(config, "Canvas", "ZoomGrid", 1)) IupSetAttribute(item_zoomgrid, "VALUE", "OFF"); if (!IupConfigGetVariableIntDef(config, "MainWindow", "Toolbar", 1)) IupSetAttribute(item_toolbar, "VALUE", "OFF"); if (!IupConfigGetVariableIntDef(config, "MainWindow", "Toolbox", 1)) IupSetAttribute(item_toolbox, "VALUE", "OFF"); if (!IupConfigGetVariableIntDef(config, "MainWindow", "Statusbar", 1)) IupSetAttribute(item_statusbar, "VALUE", "OFF"); return menu; } static Ihandle* create_toolbar(Ihandle *config) { Ihandle *toolbar; Ihandle *btn_copy, *btn_paste, *btn_new, *btn_open, *btn_save, *btn_zoomgrid; IupSetHandle("PaintZoomGrid", load_image_PaintZoomGrid()); btn_new = IupButton(NULL, NULL); IupSetAttribute(btn_new, "IMAGE", "IUP_FileNew"); IupSetAttribute(btn_new, "FLAT", "Yes"); IupSetCallback(btn_new, "ACTION", (Icallback)item_new_action_cb); IupSetAttribute(btn_new, "TIP", "New (Ctrl+N)"); IupSetAttribute(btn_new, "CANFOCUS", "No"); btn_open = IupButton(NULL, NULL); IupSetAttribute(btn_open, "IMAGE", "IUP_FileOpen"); IupSetAttribute(btn_open, "FLAT", "Yes"); IupSetCallback(btn_open, "ACTION", (Icallback)item_open_action_cb); IupSetAttribute(btn_open, "TIP", "Open (Ctrl+O)"); IupSetAttribute(btn_open, "CANFOCUS", "No"); btn_save = IupButton(NULL, NULL); IupSetAttribute(btn_save, "IMAGE", "IUP_FileSave"); IupSetAttribute(btn_save, "FLAT", "Yes"); IupSetCallback(btn_save, "ACTION", (Icallback)item_save_action_cb); IupSetAttribute(btn_save, "TIP", "Save (Ctrl+S)"); IupSetAttribute(btn_save, "CANFOCUS", "No"); btn_copy = IupButton(NULL, NULL); IupSetAttribute(btn_copy, "IMAGE", "IUP_EditCopy"); IupSetAttribute(btn_copy, "FLAT", "Yes"); IupSetCallback(btn_copy, "ACTION", (Icallback)item_copy_action_cb); IupSetAttribute(btn_copy, "TIP", "Copy (Ctrl+C)"); IupSetAttribute(btn_copy, "CANFOCUS", "No"); btn_paste = IupButton(NULL, NULL); IupSetAttribute(btn_paste, "IMAGE", "IUP_EditPaste"); IupSetAttribute(btn_paste, "FLAT", "Yes"); IupSetCallback(btn_paste, "ACTION", (Icallback)item_paste_action_cb); IupSetAttribute(btn_paste, "TIP", "Paste (Ctrl+V)"); IupSetAttribute(btn_paste, "CANFOCUS", "No"); btn_zoomgrid = IupButton(NULL, NULL); IupSetAttribute(btn_zoomgrid, "IMAGE", "PaintZoomGrid"); IupSetAttribute(btn_zoomgrid, "FLAT", "Yes"); IupSetCallback(btn_zoomgrid, "ACTION", (Icallback)item_zoomgrid_action_cb); IupSetAttribute(btn_zoomgrid, "TIP", "Zoom Grid"); IupSetAttribute(btn_paste, "CANFOCUS", "No"); toolbar = IupHbox( btn_new, btn_open, btn_save, IupSetAttributes(IupLabel(NULL), "SEPARATOR=VERTICAL"), btn_copy, btn_paste, IupSetAttributes(IupLabel(NULL), "SEPARATOR=VERTICAL"), btn_zoomgrid, NULL); IupSetAttribute(toolbar, "MARGIN", "5x5"); IupSetAttribute(toolbar, "GAP", "2"); IupSetAttribute(toolbar, "NAME", "TOOLBAR"); /* Initialize variables from the configuration file */ if (!IupConfigGetVariableIntDef(config, "MainWindow", "Toolbar", 1)) { IupSetAttribute(toolbar, "FLOATING", "YES"); IupSetAttribute(toolbar, "VISIBLE", "NO"); } return toolbar; } static void create_toolbox(Ihandle* parent_dlg, Ihandle *config) { Ihandle *toolbox, *gbox, *vbox; Ihandle* canvas = IupGetDialogChild(parent_dlg, "CANVAS"); IupSetHandle("PaintPointer", load_image_Pointer()); IupSetHandle("PaintColorPicker", load_image_PaintColorPicker()); IupSetHandle("PaintPencil", load_image_PaintPencil()); IupSetHandle("PaintLine", load_image_PaintLine()); IupSetHandle("PaintEllipse", load_image_PaintEllipse()); IupSetHandle("PaintRect", load_image_PaintRect()); IupSetHandle("PaintOval", load_image_PaintOval()); IupSetHandle("PaintBox", load_image_PaintBox()); IupSetHandle("PaintFill", load_image_PaintFill()); IupSetHandle("PaintText", load_image_PaintText()); gbox = IupGridBox( IupSetCallbacks(IupSetAttributes(IupToggle(NULL, NULL), "TOOLINDEX=0, IMAGE=PaintPointer, VALUE=ON, FLAT=Yes, TIP=\"Pointer\""), "ACTION", (Icallback)tool_action_cb, NULL), IupSetCallbacks(IupSetAttributes(IupToggle(NULL, NULL), "TOOLINDEX=1, IMAGE=PaintColorPicker, FLAT=Yes, TIP=\"Color Picker\""), "ACTION", (Icallback)tool_action_cb, NULL), IupSetCallbacks(IupSetAttributes(IupToggle(NULL, NULL), "TOOLINDEX=2, IMAGE=PaintPencil, FLAT=Yes, TIP=\"Pencil\""), "ACTION", (Icallback)tool_action_cb, NULL), IupSetCallbacks(IupSetAttributes(IupToggle(NULL, NULL), "TOOLINDEX=3, IMAGE=PaintLine, FLAT=Yes, TIP=\"Line\""), "ACTION", (Icallback)tool_action_cb, NULL), IupSetCallbacks(IupSetAttributes(IupToggle(NULL, NULL), "TOOLINDEX=4, IMAGE=PaintRect, FLAT=Yes, TIP=\"Hollow Rectangle\""), "ACTION", (Icallback)tool_action_cb, NULL), IupSetCallbacks(IupSetAttributes(IupToggle(NULL, NULL), "TOOLINDEX=5, IMAGE=PaintBox, FLAT=Yes, TIP=\"Box (Filled Rectangle)\""), "ACTION", (Icallback)tool_action_cb, NULL), IupSetCallbacks(IupSetAttributes(IupToggle(NULL, NULL), "TOOLINDEX=6, IMAGE=PaintEllipse, FLAT=Yes, TIP=\"Hollow Ellipse\""), "ACTION", (Icallback)tool_action_cb, NULL), IupSetCallbacks(IupSetAttributes(IupToggle(NULL, NULL), "TOOLINDEX=7, IMAGE=PaintOval, FLAT=Yes, TIP=\"Oval (Filled Ellipse)\""), "ACTION", (Icallback)tool_action_cb, NULL), IupSetCallbacks(IupSetAttributes(IupToggle(NULL, NULL), "TOOLINDEX=8, IMAGE=PaintText, FLAT=Yes, TIP=\"Text\""), "ACTION", (Icallback)tool_action_cb, NULL), IupSetCallbacks(IupSetAttributes(IupToggle(NULL, NULL), "TOOLINDEX=9, IMAGE=PaintFill, FLAT=Yes, TIP=\"Fill Color\""), "ACTION", (Icallback)tool_action_cb, NULL), NULL); IupSetAttribute(gbox, "GAPCOL", "2"); IupSetAttribute(gbox, "GAPLIN", "2"); IupSetAttribute(gbox, "MARGIN", "5x10"); IupSetAttribute(gbox, "NUMDIV", "2"); vbox = IupVbox( IupRadio(gbox), IupFrame(IupSetAttributes(IupVbox( IupSetAttributes(IupLabel("Color:"), "EXPAND=HORIZONTAL"), IupSetCallbacks(IupSetAttributes(IupButton(NULL, NULL), "NAME=COLOR, BGCOLOR=\"0 0 0\", RASTERSIZE=28x21"), "ACTION", toolcolor_action_cb, NULL), IupSetAttributes(IupLabel("Width:"), "EXPAND=HORIZONTAL"), IupSetCallbacks(IupSetAttributes(IupText(NULL), "SPIN=Yes, SPINMIN=1, RASTERSIZE=48x"), "VALUECHANGED_CB", toolwidth_valuechanged_cb, NULL), IupSetAttributes(IupLabel("Style:"), "EXPAND=HORIZONTAL"), IupSetCallbacks(IupSetAttributes(IupList(NULL), "DROPDOWN=Yes, VALUE=1, 1=\"____\", 2=\"----\", 3=\"....\", 4=\"-.-.\", 5=\"-..-..\""), "VALUECHANGED_CB", toolstyle_valuechanged_cb, NULL), IupSetAttributes(IupLabel("Tol.: 50%"), "EXPAND=HORIZONTAL, NAME=FILLTOLLABEL"), IupSetCallbacks(IupSetAttributes(IupVal(NULL), "NAME=FILLTOL, RASTERSIZE=60x30, VALUE=50, MAX=100"), "VALUECHANGED_CB", toolfilltol_valuechanged_cb, NULL), IupSetAttributes(IupLabel("Font:"), "EXPAND=HORIZONTAL"), IupSetCallbacks(IupSetAttributes(IupButton("F", NULL), "NAME=FONT, RASTERSIZE=21x21, FONT=\"Times, Bold Italic 11\""), "ACTION", toolfont_action_cb, NULL), NULL), "MARGIN=3x2, GAP=2, ALIGNMENT=ACENTER")), NULL); IupSetAttribute(vbox, "NMARGIN", "2x2"); IupSetAttribute(vbox, "ALIGNMENT", "ACENTER"); toolbox = IupDialog(vbox); IupSetAttribute(toolbox, "DIALOGFRAME", "Yes"); IupSetAttribute(toolbox, "TITLE", "Tools"); IupSetAttribute(toolbox, "FONTSIZE", "8"); IupSetAttribute(toolbox, "TOOLBOX", "Yes"); IupSetCallback(toolbox, "CLOSE_CB", (Icallback)toolbox_close_cb); IupSetAttributeHandle(toolbox, "PARENTDIALOG", parent_dlg); IupSetAttribute(toolbox, "TOOLCOLOR", "0 0 0 255"); IupSetAttribute(toolbox, "TOOLWIDTH", "1"); IupSetAttribute(toolbox, "TOOLSTYLE", "1"); IupSetAttribute(toolbox, "TOOLFILLTOL", "50"); IupSetStrAttribute(toolbox, "TOOLFONT", IupGetAttribute(parent_dlg, "FONT")); IupSetAttribute(toolbox, "CONFIG", (char*)config); IupSetAttribute(toolbox, "CANVAS", (char*)canvas); IupSetAttribute(parent_dlg, "TOOLBOX", (char*)toolbox); /* Initialize variables from the configuration file */ if (IupConfigGetVariableIntDef(config, "MainWindow", "Toolbox", 1)) { /* configure the very first time to be aligned with the main window */ if (!IupConfigGetVariableStr(config, "Toolbox", "X")) { int x = IupGetInt(canvas, "X"); int y = IupGetInt(canvas, "Y"); IupConfigSetVariableInt(config, "Toolbox", "X", x); IupConfigSetVariableInt(config, "Toolbox", "Y", y); } IupConfigDialogShow(config, toolbox, "Toolbox"); } } static Ihandle* create_statusbar(Ihandle *config) { Ihandle *statusbar; statusbar = IupHbox( IupSetAttributes(IupLabel("(0, 0) = 0 0 0"), "EXPAND=HORIZONTAL, PADDING=10x5, NAME=STATUSLABEL"), IupSetAttributes(IupLabel(NULL), "SEPARATOR=VERTICAL"), IupSetAttributes(IupLabel("0 x 0"), "SIZE=70x, PADDING=10x5, NAME=SIZELABEL, ALIGNMENT=ACENTER"), IupSetAttributes(IupLabel(NULL), "SEPARATOR=VERTICAL"), IupSetAttributes(IupLabel("100%"), "SIZE=30x, PADDING=10x5, NAME=ZOOMLABEL, ALIGNMENT=ARIGHT"), IupSetCallbacks(IupSetAttributes(IupButton(NULL, NULL), "IMAGE=IUP_ZoomOut, FLAT=Yes, TIP=\"Zoom Out (Ctrl+-)\""), "ACTION", zoomout_action_cb, NULL), IupSetCallbacks(IupSetAttributes(IupVal(NULL), "VALUE=0, MIN=-6, MAX=6, RASTERSIZE=150x25, NAME=ZOOMVAL"), "VALUECHANGED_CB", zoom_valuechanged_cb, NULL), IupSetCallbacks(IupSetAttributes(IupButton(NULL, NULL), "IMAGE=IUP_ZoomIn, FLAT=Yes, TIP=\"Zoom In (Ctrl++)\""), "ACTION", zoomin_action_cb, NULL), IupSetCallbacks(IupSetAttributes(IupButton(NULL, NULL), "IMAGE=IUP_ZoomActualSize, FLAT=Yes, TIP=\"Actual Size (Ctrl+0)\""), "ACTION", actualsize_action_cb, NULL), NULL); IupSetAttribute(statusbar, "NAME", "STATUSBAR"); IupSetAttribute(statusbar, "ALIGNMENT", "ACENTER"); /* Initialize variables from the configuration file */ if (!IupConfigGetVariableIntDef(config, "MainWindow", "Statusbar", 1)) { IupSetAttribute(statusbar, "FLOATING", "YES"); IupSetAttribute(statusbar, "VISIBLE", "NO"); } return statusbar; } static Ihandle* create_main_dialog(Ihandle *config) { Ihandle *dlg, *vbox, *canvas; #ifdef USE_OPENGL canvas = IupGLCanvas(NULL); IupSetAttribute(canvas, "BUFFER", "DOUBLE"); #else canvas = IupCanvas(NULL); #endif IupSetAttribute(canvas, "NAME", "CANVAS"); IupSetAttribute(canvas, "SCROLLBAR", "Yes"); IupSetAttribute(canvas, "DIRTY", "NO"); /* custom attribute */ IupSetCallback(canvas, "ACTION", (Icallback)canvas_action_cb); IupSetCallback(canvas, "DROPFILES_CB", (Icallback)dropfiles_cb); IupSetCallback(canvas, "MAP_CB", (Icallback)canvas_map_cb); IupSetCallback(canvas, "UNMAP_CB", (Icallback)canvas_unmap_cb); IupSetCallback(canvas, "WHEEL_CB", (Icallback)canvas_wheel_cb); IupSetCallback(canvas, "RESIZE_CB", (Icallback)canvas_resize_cb); IupSetCallback(canvas, "MOTION_CB", (Icallback)canvas_motion_cb); IupSetCallback(canvas, "BUTTON_CB", (Icallback)canvas_button_cb); vbox = IupVbox( create_toolbar(config), canvas, create_statusbar(config), NULL); dlg = IupDialog(vbox); IupSetAttributeHandle(dlg, "MENU", create_main_menu(config)); IupSetAttribute(dlg, "SIZE", "HALFxHALF"); IupSetCallback(dlg, "CLOSE_CB", (Icallback)item_exit_action_cb); IupSetCallback(dlg, "DROPFILES_CB", (Icallback)dropfiles_cb); IupSetCallback(dlg, "MOVE_CB", (Icallback)main_dlg_move_cb); IupSetCallback(dlg, "K_cN", (Icallback)item_new_action_cb); IupSetCallback(dlg, "K_cO", (Icallback)item_open_action_cb); IupSetCallback(dlg, "K_cS", (Icallback)item_save_action_cb); IupSetCallback(dlg, "K_cV", (Icallback)item_paste_action_cb); IupSetCallback(dlg, "K_cC", (Icallback)item_copy_action_cb); IupSetCallback(dlg, "K_cP", (Icallback)item_print_action_cb); IupSetCallback(dlg, "K_cMinus", (Icallback)zoomout_action_cb); IupSetCallback(dlg, "K_cPlus", (Icallback)zoomin_action_cb); IupSetCallback(dlg, "K_cEqual", (Icallback)zoomin_action_cb); IupSetCallback(dlg, "K_c0", (Icallback)actualsize_action_cb); /* parent for pre-defined dialogs in closed functions (IupMessage and IupAlarm) */ IupSetAttributeHandle(NULL, "PARENTDIALOG", dlg); IupSetAttribute(dlg, "CONFIG", (char*)config); return dlg; } int main(int argc, char **argv) { Ihandle *dlg, *config; IupOpen(&argc, &argv); IupImageLibOpen(); #ifdef USE_OPENGL IupGLCanvasOpen(); #endif #ifdef USE_CONTEXTPLUS cdInitContextPlus(); #endif config = IupConfig(); IupSetAttribute(config, "APP_NAME", "simple_paint"); IupConfigLoad(config); dlg = create_main_dialog(config); /* show the dialog at the last position, with the last size */ IupConfigDialogShow(config, dlg, "MainWindow"); /* create and show the toolbox */ create_toolbox(dlg, config); /* open a file from the command line (allow file association in Windows) */ if (argc > 1 && argv[1]) { const char* filename = argv[1]; open_file(dlg, filename); } /* initialize the current file, if not already loaded */ check_new_file(dlg); IupMainLoop(); IupClose(); return EXIT_SUCCESS; } /* Possible Enhancements: - Save last used toolbox options in configuration file? - Hide/show toolbox options according to selected tool - Capture image from Camera using IM - Undo/Redo - Secondary color for drawing of shapes with both outline and filled at the same time - Alpha for colors - Area Selection */