From c3a2920bab79e0a41b45c74b883367437ab1dd6d Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 27 Feb 2011 18:44:54 +0800 Subject: [PATCH] axwin2 - Working on GUI, implemented image loading - Also fixed URI/URL handling code (needs correctness though) --- Usermode/Applications/axwin2_src/Makefile | 4 + Usermode/Applications/axwin2_src/WM/Makefile | 9 ++ .../Applications/axwin2_src/WM/decorator.c | 9 ++ Usermode/Applications/axwin2_src/WM/image.c | 111 +++++++++++++++--- .../Applications/axwin2_src/WM/interface.c | 10 +- Usermode/Applications/axwin2_src/WM/video.c | 8 +- Usermode/Applications/axwin2_src/WM/wm.c | 4 +- Usermode/Applications/axwin2_src/WM/wm.h | 2 +- Usermode/Libraries/libimage_sif.so_src/main.c | 39 ++++-- Usermode/Libraries/liburi.so_src/main.c | 31 ++++- Usermode/include/axwin/axwin.h | 4 + Usermode/include/image.h | 24 ++++ Usermode/include/uri.h | 2 + 13 files changed, 219 insertions(+), 38 deletions(-) create mode 100644 Usermode/Applications/axwin2_src/Makefile create mode 100644 Usermode/include/image.h diff --git a/Usermode/Applications/axwin2_src/Makefile b/Usermode/Applications/axwin2_src/Makefile new file mode 100644 index 00000000..e47c829d --- /dev/null +++ b/Usermode/Applications/axwin2_src/Makefile @@ -0,0 +1,4 @@ + +%: + $(MAKE) -C WM/ $@ + $(MAKE) -C Shell_src/ $@ diff --git a/Usermode/Applications/axwin2_src/WM/Makefile b/Usermode/Applications/axwin2_src/WM/Makefile index 154d2cfa..d740d1c1 100644 --- a/Usermode/Applications/axwin2_src/WM/Makefile +++ b/Usermode/Applications/axwin2_src/WM/Makefile @@ -10,4 +10,13 @@ OBJ := main.o helpers.o commandline.o video.o video_text.o OBJ += messages.o interface.o wm.o decorator.o OBJ += image.o +LDFLAGS += -limage_sif -luri + -include ../../Makefile.tpl + +all: resources/LogoSmall.sif.res.h + +%.res.h: % Makefile + echo "#define RESOURCE_$(notdir $<) \\"| sed -e 's/\./_/g' > $@ + base64 $< | sed -e 's/.*/"&"\\/' >> $@ + echo "" >> $@ diff --git a/Usermode/Applications/axwin2_src/WM/decorator.c b/Usermode/Applications/axwin2_src/WM/decorator.c index c224d6fc..9eb6a62f 100644 --- a/Usermode/Applications/axwin2_src/WM/decorator.c +++ b/Usermode/Applications/axwin2_src/WM/decorator.c @@ -7,6 +7,8 @@ #include "common.h" #include "wm.h" +#define BORDER_EVERYTHING 1 + #define BOX_BGCOLOUR 0xC0C0C0 #define BOX_BORDER 0xA0A0A0 #define BUTTON_BGCOLOUR 0xD0D0D0 @@ -22,6 +24,13 @@ void Decorator_RenderWidget(tElement *Element) Element->CachedW, Element->CachedH ); + #if BORDER_EVERYTHING + Video_DrawRect(Element->CachedX, Element->CachedY, + Element->CachedW, Element->CachedH, + 0 + ); + #endif + switch(Element->Type) { case ELETYPE_NONE: diff --git a/Usermode/Applications/axwin2_src/WM/image.c b/Usermode/Applications/axwin2_src/WM/image.c index eab1d0ee..1d7d343d 100644 --- a/Usermode/Applications/axwin2_src/WM/image.c +++ b/Usermode/Applications/axwin2_src/WM/image.c @@ -12,40 +12,119 @@ // === IMPORTS === extern tImage *Image_SIF_Parse(void *Buffer, size_t Size); +// === PROTOTYPES === + int UnBase64(uint8_t *Dest, char *Src, int BufSize); + // === CODE === /** * \brief Open an image from a URI */ tImage *Image_Load(const char *URI) { - #if 0 tURI *uri; int filesize; void *buf; tImage *img; - void *fp; uri = URI_Parse(URI); - - fp = URI_Open(URI_MODE_READ, uri); - if(!fp) return NULL; - free(uri); - - filesize = URI_GetSize(fp); - buf = malloc( filesize ); - if(!buf) { - URI_Close(fp); + if( !uri ) { + _SysDebug("Image_Load: Unable parse as URI '%s'\n", URI); return NULL; } - URI_Read(fp, filesize, buf); - URI_Close(fp); + if( strcmp(uri->Proto, "file") == 0 ) + { + FILE *fp; + fp = fopen(uri->Path, "rb"); + if(!fp) { + _SysDebug("Image_Load: Unable to open '%s'\n", uri->Path); + free(uri); + return NULL; + } + + fseek(fp, 0, SEEK_END); + filesize = ftell(fp); + buf = malloc( filesize ); + if(!buf) { + _SysDebug("Image_Load: malloc() failed!\n"); + fclose(fp); + free(uri); + return NULL; + } + + fread(buf, filesize, 1, buf); + fclose(fp); + } + else if( strcmp(uri->Proto, "base64") == 0 ) + { + // 4 bytes of base64 = 3 bytes of binary (base 256) + filesize = strlen( uri->Path ) * 3 / 4; + buf = malloc(filesize); + if(!buf) { + _SysDebug("Image_Load: malloc() failed!\n"); + free(uri); + return NULL; + } + + filesize = UnBase64(buf, uri->Path, filesize); + } + else + { + _SysDebug("Image_Load: Unknow protocol '%s'\n", uri->Proto); + free(uri); + return NULL; + } img = Image_SIF_Parse(buf, filesize); free(buf); + free(uri); + if( !img ) { + _SysDebug("Image_Load: Unable to parse SIF from '%s'\n", URI); + return NULL; + } return img; - #else - return NULL; - #endif +} + +/** + * \brief Decode a Base64 value + */ +int UnBase64(uint8_t *Dest, char *Src, int BufSize) +{ + uint32_t val; + int i, j; + char *start_src = Src; + + for( i = 0; i+2 < BufSize; i += 3 ) + { + val = 0; + for( j = 0; j < 4; j++, Src ++ ) { + if('A' <= *Src && *Src <= 'Z') + val |= (*Src - 'A') << ((3-j)*6); + else if('a' <= *Src && *Src <= 'z') + val |= (*Src - 'a' + 26) << ((3-j)*6); + else if('0' <= *Src && *Src <= '9') + val |= (*Src - '0' + 52) << ((3-j)*6); + else if(*Src == '+') + val |= 62 << ((3-j)*6); + else if(*Src == '/') + val |= 63 << ((3-j)*6); + else if(!*Src) + break; + else if(*Src != '=') + j --; // Ignore invalid characters + } + Dest[i ] = (val >> 16) & 0xFF; + Dest[i+1] = (val >> 8) & 0xFF; + Dest[i+2] = val & 0xFF; + if(j != 4) break; + } + + // Finish things off + if(i < BufSize) + Dest[i] = (val >> 16) & 0xFF; + if(i+1 < BufSize) + Dest[i+1] = (val >> 8) & 0xFF; + + return Src - start_src; } diff --git a/Usermode/Applications/axwin2_src/WM/interface.c b/Usermode/Applications/axwin2_src/WM/interface.c index d4ad424f..630b1f47 100644 --- a/Usermode/Applications/axwin2_src/WM/interface.c +++ b/Usermode/Applications/axwin2_src/WM/interface.c @@ -6,6 +6,7 @@ * > Main Overarching UI */ #include "common.h" +#include "resources/LogoSmall.sif.res.h" // === GLOBALS == int giInterface_Width = 0; @@ -17,6 +18,7 @@ tElement *gpInterface_MainArea; tElement *gpInterface_HeaderBar; tElement *gpInterface_TabBar; tElement *gpInterface_TabContent; +const char csLogoSmall[] = "base64:///"RESOURCE_LogoSmall_sif; // === CODE === /** @@ -41,9 +43,11 @@ void Interface_Init(void) btn = WM_CreateElement(gpInterface_Sidebar, ELETYPE_BUTTON, ELEFLAG_NOSTRETCH, "SystemMenu"); WM_SetSize(btn, giInterface_Width-4); // TODO: Once image loading is implemented, switch to a logo - #if 0 - text = WM_CreateElement(btn, ELETYPE_IMAGE, ELEFLAG_SCALE); - WM_SetText(text, "asset://LogoSmall.sif"); + #if 1 + //text = WM_CreateElement(btn, ELETYPE_IMAGE, ELEFLAG_SCALE); + text = WM_CreateElement(btn, ELETYPE_IMAGE, 0, "MenuLogo"); + //WM_SetText(text, "file:///LogoSmall.sif"); + WM_SetText(text, csLogoSmall); #else text = WM_CreateElement(btn, ELETYPE_TEXT, 0, NULL); WM_SetText(text, "Acess"); diff --git a/Usermode/Applications/axwin2_src/WM/video.c b/Usermode/Applications/axwin2_src/WM/video.c index 7e253606..5c604256 100644 --- a/Usermode/Applications/axwin2_src/WM/video.c +++ b/Usermode/Applications/axwin2_src/WM/video.c @@ -104,7 +104,11 @@ void Video_DrawImage(short X, short Y, short W, short H, tImage *Image) { int x, y; uint8_t *buf = (uint8_t *)(gpScreenBuffer + Y*giScreenWidth + X); - uint8_t *data = Image->Data; + uint8_t *data; + + // Sanity please + if( !Image ) + return ; // Bounds Check if( X >= giScreenWidth ) return ; @@ -118,6 +122,8 @@ void Video_DrawImage(short X, short Y, short W, short H, tImage *Image) if( X + W > giScreenWidth ) W = giScreenWidth - X; if( Y + H > giScreenHeight ) H = giScreenHeight - Y; + // Do the render + data = Image->Data; switch( Image->Format ) { case IMGFMT_BGRA: diff --git a/Usermode/Applications/axwin2_src/WM/wm.c b/Usermode/Applications/axwin2_src/WM/wm.c index ad441b39..f107ae74 100644 --- a/Usermode/Applications/axwin2_src/WM/wm.c +++ b/Usermode/Applications/axwin2_src/WM/wm.c @@ -18,7 +18,7 @@ tElement *WM_CreateElement(tElement *Parent, int Type, int Flags, const char *De void WM_UpdateMinDims(tElement *Element); void WM_SetFlags(tElement *Element, int Flags); void WM_SetSize(tElement *Element, int Size); -void WM_SetText(tElement *Element, char *Text); +void WM_SetText(tElement *Element, const char *Text); void WM_UpdateDimensions(tElement *Element, int Pass); void WM_UpdatePosition(tElement *Element); void WM_RenderWidget(tElement *Element); @@ -100,7 +100,7 @@ void WM_SetSize(tElement *Element, int Size) * \brief Set the text field of an element * \note Used for the image path on ELETYPE_IMAGE */ -void WM_SetText(tElement *Element, char *Text) +void WM_SetText(tElement *Element, const char *Text) { if(!Element) return ; if(Element->Text) free(Element->Text); diff --git a/Usermode/Applications/axwin2_src/WM/wm.h b/Usermode/Applications/axwin2_src/WM/wm.h index 0f5edf2f..cd4ab90c 100644 --- a/Usermode/Applications/axwin2_src/WM/wm.h +++ b/Usermode/Applications/axwin2_src/WM/wm.h @@ -145,6 +145,6 @@ enum eElementTypes extern tElement *WM_CreateElement(tElement *Parent, int Type, int Flags, const char *DebugName); extern void WM_SetFlags(tElement *Element, int Flags); extern void WM_SetSize(tElement *Element, int Size); -extern void WM_SetText(tElement *Element, char *Text); +extern void WM_SetText(tElement *Element, const char *Text); #endif diff --git a/Usermode/Libraries/libimage_sif.so_src/main.c b/Usermode/Libraries/libimage_sif.so_src/main.c index 7b076a3b..4ce0a2d3 100644 --- a/Usermode/Libraries/libimage_sif.so_src/main.c +++ b/Usermode/Libraries/libimage_sif.so_src/main.c @@ -7,6 +7,17 @@ #include //#include +// === STRUCTURES === +struct sHeader +{ + uint16_t Magic; + uint16_t Flags; + uint16_t Width; + uint16_t Height; +}; + +// === CONSTANTS === + // === CODE === int SoMain(void) { @@ -17,8 +28,6 @@ int SoMain(void) */ tImage *Image_SIF_Parse(void *Buffer, size_t Size) { - uint16_t magic; - uint16_t flags; uint16_t w, h; int ofs, i; tImage *ret; @@ -26,25 +35,30 @@ tImage *Image_SIF_Parse(void *Buffer, size_t Size) int fileOfs = 0; int comp, fmt; int sampleSize = 4; + struct sHeader *hdr = Buffer; + + _SysDebug("Image_SIF_Parse: (Buffer=%p, Size=0x%x)", Buffer, Size); // Get magic word and determine byte ordering - magic = *(uint16_t*)Buffer+fileOfs; fileOfs += 2; - if(magic == 0x51F0) + if(hdr->Magic == 0x51F0) // Little Endian bRevOrder = 0; - else if(magic == 0xF051) + else if(hdr->Magic == 0xF051) // Big Endian bRevOrder = 1; else { return NULL; } + _SysDebug(" Image_SIF_Parse: bRevOrder = %i", bRevOrder); + // Read flags - flags = *(uint16_t*)Buffer+fileOfs; fileOfs += 2; - comp = flags & 7; - fmt = (flags >> 3) & 7; + comp = hdr->Flags & 7; + fmt = (hdr->Flags >> 3) & 7; // Read dimensions - w = *(uint16_t*)Buffer+fileOfs; fileOfs += 2; - h = *(uint16_t*)Buffer+fileOfs; fileOfs += 2; + w = hdr->Width; + h = hdr->Height; + + _SysDebug(" Image_SIF_Parse: Dimensions %ix%i", w, h); // Get image format switch(fmt) @@ -58,10 +72,13 @@ tImage *Image_SIF_Parse(void *Buffer, size_t Size) sampleSize = 3; break; default: - free(ret); return NULL; } + _SysDebug(" Image_SIF_Parse: sampleSize = %i, fmt = %i", sampleSize, fmt); + + fileOfs = sizeof(struct sHeader); + // Allocate space ret = calloc(1, sizeof(tImage) + w * h * sampleSize); ret->Width = w; diff --git a/Usermode/Libraries/liburi.so_src/main.c b/Usermode/Libraries/liburi.so_src/main.c index 2d785f3e..57de6f6a 100644 --- a/Usermode/Libraries/liburi.so_src/main.c +++ b/Usermode/Libraries/liburi.so_src/main.c @@ -32,11 +32,12 @@ void URI_Close(tURIFile *File); size_t URI_file_Read(int Handle, size_t Bytes, void *Buffer); size_t URI_file_Write(int Handle, size_t Bytes, void *Buffer); void URI_file_Close(int Handle); +size_t URI_file_GetSize(int Handle); // === CONSTANTS === // Builtin URI protocol handlers tURIHandler caBuiltinHandlers[] = { - {"file", 0, URI_file_Open, URI_file_Close, URI_file_Read, URI_file_Write} + {"file", 0, URI_file_Open, URI_file_Close, URI_file_Read, URI_file_Write, URI_file_GetSize} }; #define NUM_BUILTIN_HANDLERS (sizeof(caBuiltinHandlers)/sizeof(caBuiltinHandlers[0])) @@ -55,7 +56,7 @@ tURI *URI_Parse(const char *String) if(!String) return NULL; protolen = 0; - while( isalpha(*tmp) ) tmp++, protolen++; + while( isalpha(*tmp) || isdigit(*tmp) ) tmp++, protolen++; // true URI if(tmp[0] == ':' && tmp[1] == '/' && tmp[2] == '/') @@ -75,7 +76,7 @@ tURI *URI_Parse(const char *String) if( *tmp == '[' ) { tmp ++; - while( *tmp != ']' ) { + while( *tmp && *tmp != ']' ) { ret->Host[hostlen] = *tmp; tmp ++; hostlen ++; @@ -86,7 +87,7 @@ tURI *URI_Parse(const char *String) // IPv4/DNS else { - while( *tmp != '/' && *tmp != ':' ) + while( *tmp && *tmp != '/' && *tmp != ':' ) { ret->Host[hostlen] = *tmp; tmp ++; @@ -225,6 +226,19 @@ tURIFile *URI_Open(int Mode, tURI *URI) return ret; } +int URI_GetSize(tURIFile *File, size_t *Size) +{ + if( !File || !Size ) return -1; + + if( File->Handler->GetSize ) + { + *Size = File->Handler->GetSize(File->Handle); + return 0; // Success + } + + return 1; // Size not avaliable +} + /** * \brief Read from a URI file */ @@ -322,3 +336,12 @@ void URI_file_Close(int Handle) { close(Handle); } +size_t URI_file_GetSize(int Handle) +{ + uint64_t curpos = tell(Handle); + size_t ret; + seek(Handle, 0, SEEK_END); + ret = tell(Handle); + seek(Handle, curpos, SEEK_SET); + return ret; +} diff --git a/Usermode/include/axwin/axwin.h b/Usermode/include/axwin/axwin.h index cacf1d83..71af36a0 100644 --- a/Usermode/include/axwin/axwin.h +++ b/Usermode/include/axwin/axwin.h @@ -11,6 +11,9 @@ typedef void *tAxWin_Handle; // === Messaging === #include "messages.h" + +extern int AxWin_Register(const char *Name); + extern int AxWin_MessageLoop(); extern int AxWin_SendMessage(tAxWin_Message *Message); extern tAxWin_Message *AxWin_WaitForMessage(void); @@ -33,6 +36,7 @@ typedef int tAxWin_MessageCallback(tAxWin_Message *); /** * \} */ + extern tAxWin_Window *AxWin_CreateWindow( int16_t X, int16_t Y, int16_t W, int16_t H, uint32_t Flags, tAxWin_MessageCallback *Callback); diff --git a/Usermode/include/image.h b/Usermode/include/image.h new file mode 100644 index 00000000..69e1549e --- /dev/null +++ b/Usermode/include/image.h @@ -0,0 +1,24 @@ +/* + */ +#ifndef _IMAGE_H_ +#define _IMAGE_H_ + +// === TYPES === +typedef struct sImage tImage; +struct sImage +{ + short Width; + short Height; + int Format; + uint8_t Data[]; +}; + +// === CONSTANTS === +enum eImageFormats +{ + IMGFMT_BGRA, + IMGFMT_RGB, + NUM_IMGFMTS +}; + +#endif diff --git a/Usermode/include/uri.h b/Usermode/include/uri.h index 92956b05..20b4b4cb 100644 --- a/Usermode/include/uri.h +++ b/Usermode/include/uri.h @@ -33,11 +33,13 @@ struct sURIHandler void (*Close)(int Handle); size_t (*Read)(int Handle, size_t Bytes, void *Buffer); size_t (*Write)(int Handle, size_t Bytes, void *Buffer); + size_t (*GetSize)(int Handle); }; // === FUNCTIONS === extern tURI *URI_Parse(const char *String); extern tURIFile *URI_Open(int Mode, tURI *URI); +extern int URI_GetSize(tURIFile *File, size_t *Size); extern size_t URI_Read(tURIFile *File, size_t Bytes, void *Buffer); extern size_t URI_Write(tURIFile *File, size_t Bytes, void *Buffer); extern void URI_Close(tURIFile *File); -- 2.20.1