diff --git a/contrib/sdk/samples/freetype/txview/Makefile b/contrib/sdk/samples/freetype/txview/Makefile index 22f474f6b9..a80db2dc66 100644 --- a/contrib/sdk/samples/freetype/txview/Makefile +++ b/contrib/sdk/samples/freetype/txview/Makefile @@ -1,29 +1,49 @@ + CC = kos32-gcc LD = kos32-ld +AR = kos32-ar SDK_DIR:= $(abspath ../../..) +CONTRIB_DIR:= $(abspath ../../../..) -LDFLAGS = -static -S -nostdlib -T $(SDK_DIR)/sources/newlib/app.lds -Map txview.map --image-base 0 +LDFLAGS = -static --subsystem native -Tapp-dynamic.lds -Map txview.map --image-base 0 -CFLAGS = -c -fno-ident -O2 -fomit-frame-pointer -U__WIN32__ -U_Win32 -U_WIN32 -U__MINGW32__ -UWIN32 +CFLAGS = -c -O2 -msse2 -fno-ident -U__WIN32__ -U_Win32 -U_WIN32 -U__MINGW32__ -UWIN32 -INCLUDES= -I $(SDK_DIR)/sources/newlib/libc/include -I $(SDK_DIR)/sources/freetype/include -LIBPATH:= -L $(SDK_DIR)/lib -L /home/autobuild/tools/win32/mingw32/lib +INCLUDES= -I./winlib -I./pxdraw -I $(SDK_DIR)/sources/newlib/libc/include -I $(SDK_DIR)/sources/freetype/include +INCLUDES+= -I $(CONTRIB_DIR)/toolchain/binutils/bfd -I $(CONTRIB_DIR)/toolchain/binutils/include +LIBPATH:= -L./ -L $(SDK_DIR)/lib + +LIB_SRCS= \ + pxdraw/context.c \ + pxdraw/dutils.c \ + pxdraw/region.c \ + winlib/button.c \ + winlib/winlib.c \ + $(NULL) SOURCES = main.c \ - fontlib.c \ - tview.c + fontlib.c \ + tview.c \ + $(NULL) +LIB_OBJS = $(patsubst %.c, %.o, $(LIB_SRCS)) OBJECTS = $(patsubst %.c, %.o, $(SOURCES)) default: txview -txview: $(OBJECTS) Makefile - $(LD) $(LDFLAGS) $(LIBPATH) -o txview $(OBJECTS) -lfreetype.dll -lpixlib.dll -lgcc -lc.dll -lapp - objcopy txview -O binary +libwin.a: $(LIB_OBJS) Makefile + $(AR) crs $@ $(LIB_OBJS) +txview: $(OBJECTS) libwin.a Makefile + $(LD) $(LDFLAGS) $(LIBPATH) -o txview.dll $(OBJECTS) -lfreetype.dll -lpixlib3 -lwin -lgcc -lc.dll +# objdump -d txview.dll > txview.lst + objcopy txview.dll txview -O binary + +clean: + /bin/rm -rf *.o txview %.o : %.c Makefile $(SOURCES) $(CC) $(CFLAGS) $(INCLUDES) -o $@ $< diff --git a/contrib/sdk/samples/freetype/txview/fontlib.c b/contrib/sdk/samples/freetype/txview/fontlib.c index 6192698ce7..c50146c860 100644 --- a/contrib/sdk/samples/freetype/txview/fontlib.c +++ b/contrib/sdk/samples/freetype/txview/fontlib.c @@ -6,19 +6,12 @@ #include #include FT_FREETYPE_H #include FT_GLYPH_H -#include - -typedef struct -{ - int l; - int t; - int r; - int b; -}rect_t; +#include typedef struct { FT_Face face; + int fontsize; int height; int base; @@ -27,6 +20,9 @@ typedef struct }font_t; static FT_Face def_face; +static FT_Face sym_face; + +font_t *sym_font; typedef unsigned int color_t; @@ -34,63 +30,37 @@ unsigned int ansi2utf32(unsigned char ch); font_t *create_font(FT_Face face, int size); -void my_draw_bitmap(bitmap_t *win, FT_Bitmap *bitmap, int dstx, int dsty, int col) +void draw_glyph(ctx_t *ctx, void *buffer, int pitch, rect_t *rc, color_t color); + +unsigned int ansi2utf32(unsigned char ch) { - uint8_t *dst; - uint8_t *src, *tmpsrc; + if(ch < 0x80) + return ch; - uint32_t *tmpdst; - int i, j; + if(ch < 0xB0) + return 0x410-0x80 + ch; - dst = win->data + dsty * win->pitch + dstx*4; - src = bitmap->buffer; + if(ch < 0xE0) + return 0; -// printf("buffer %x width %d rows %d\n", -// bitmap->buffer, bitmap->width, bitmap->rows); + if(ch < 0xF0) + return 0x440-0xE0 + ch; + if(ch == 0xF0) + return 0x401; + else if(ch==0xF1) + return 0x451; + else return 0; +} - for( i = 0; i < bitmap->rows; i++ ) - { - tmpdst = (uint32_t*)dst; - tmpsrc = src; - - dst+= win->pitch; - src+= bitmap->pitch; - - for( j = 0; j < bitmap->width; j++) - { - int a = *tmpsrc++; - int sr, sg, sb; - int dr, dg, db; - - if( a != 0) a++; - - db = *tmpdst & 0xFF; - dg = (*tmpdst >> 8) & 0xFF; - dr = (*tmpdst >> 16) & 0xFF; - - sb = col & 0xFF; - sg = (col >> 8) & 0xFF; - sr = (col >> 16) &0xFF; - - db = (a*sb + db*(256-a))/256; - dg = (a*sg + dg*(256-a))/256; - dr = (a*sr + dr*(256-a))/256; - - *tmpdst++ = 0xFF000000|(dr<<16)|(dg<<8)|db; - }; - } -}; - - -int draw_text_ext(bitmap_t *winbitmap, font_t *font, char *text, int len, rect_t *rc, int color) +int draw_text_ext(ctx_t *ctx, font_t *font, char *text, int len, rect_t *rc, color_t color) { FT_UInt glyph_index; FT_Bool use_kerning = 0; FT_BitmapGlyph glyph; FT_UInt previous; - int x, y, w; + int x, y, xend; int col, ncol; unsigned char ch; int err = 0; @@ -100,9 +70,8 @@ int draw_text_ext(bitmap_t *winbitmap, font_t *font, char *text, int len, rect_t col = 0; x = rc->l << 6; - y = rc->b; - - w = (rc->r - rc->l) << 6; + xend = rc->r << 6; + y = rc->t + font->base; while( len-- ) { @@ -113,7 +82,7 @@ int draw_text_ext(bitmap_t *winbitmap, font_t *font, char *text, int len, rect_t if(ch == '\t') { - ncol = (col+4) & ~3; + ncol = (col+3) & ~4; if( col < ncol) { glyph_index = FT_Get_Char_Index( font->face, ansi2utf32(' ') ); @@ -127,7 +96,7 @@ int draw_text_ext(bitmap_t *winbitmap, font_t *font, char *text, int len, rect_t x += delta.x ; } - if( x + (font->glyph[ch]->advance.x >> 10) > w) + if( x + (font->glyph[ch]->advance.x >> 10) >= xend) break; x += font->glyph[ch]->advance.x >> 10; @@ -147,15 +116,30 @@ int draw_text_ext(bitmap_t *winbitmap, font_t *font, char *text, int len, rect_t x += delta.x ; } - if( x + (font->glyph[ch]->advance.x >> 10) > w) +// if( x + (font->glyph[ch]->advance.x >> 10) >= xend) +// break; + + if( x >= xend) break; glyph = (FT_BitmapGlyph)font->glyph[ch]; - my_draw_bitmap(winbitmap, &glyph->bitmap, (x >> 6) + glyph->left, - y - glyph->top, color); + if(glyph != NULL) + { + rect_t rc_dst; - x += font->glyph[ch]->advance.x >> 10; + rc_dst.l = (x >> 6) + glyph->left; + rc_dst.t = y - glyph->top; + rc_dst.r = rc_dst.l + glyph->bitmap.width; + if(rc_dst.r > (xend >> 6)) + rc_dst.r = xend >> 6; + rc_dst.b = rc_dst.t + glyph->bitmap.rows; + +// printf("char: %c ", ch); + px_draw_glyph(ctx, glyph->bitmap.buffer, glyph->bitmap.pitch, &rc_dst, color); + + x += font->glyph[ch]->advance.x >> 10; + }; previous = glyph_index; }; @@ -180,7 +164,6 @@ int init_fontlib() // err = FT_New_Face( library, "/kolibrios/Fonts/lucon.ttf", 0, &face ); err = FT_New_Face( library, "/kolibrios/Fonts/DroidSansMono.ttf", 0, &face ); - if ( err == FT_Err_Unknown_File_Format ) { printf("font format is unsupported\n"); @@ -191,37 +174,33 @@ int init_fontlib() { printf("font file could not be read or broken\n"); goto done; - } def_face = face; + err = FT_New_Face( library, "/kolibrios/Fonts/Symbols.ttf", 0, &face ); + if ( err == FT_Err_Unknown_File_Format ) + { + printf("font format is unsupported\n"); + goto done; + + } + else if ( err ) + { + printf("font file could not be read or broken\n"); + goto done; + } + + sym_face = face; + + sym_font = create_font(sym_face, 14); + done: return err; }; -unsigned int ansi2utf32(unsigned char ch) -{ - if(ch < 0x80) - return ch; - - if(ch < 0xB0) - return 0x410-0x80 + ch; - - if(ch < 0xE0) - return 0; - - if(ch < 0xF0) - return 0x440-0xE0 + ch; - - if(ch == 0xF0) - return 0x401; - else if(ch==0xF1) - return 0x451; - else return 0; -} font_t *create_font(FT_Face xface, int size) @@ -236,7 +215,7 @@ font_t *create_font(FT_Face xface, int size) memset(font, 0, sizeof(*font)); font->face = (xface == NULL) ? def_face : xface; - font->height = size+1; + font->height = size; err = FT_Set_Pixel_Sizes( font->face, 0, size ); @@ -276,3 +255,9 @@ font_t *create_font(FT_Face xface, int size) return font; } + +int get_font_height(font_t *font) +{ + return font->height; +} + diff --git a/contrib/sdk/samples/freetype/txview/main.c b/contrib/sdk/samples/freetype/txview/main.c index 57f5a274cd..ffc1b036ee 100644 --- a/contrib/sdk/samples/freetype/txview/main.c +++ b/contrib/sdk/samples/freetype/txview/main.c @@ -1,181 +1,187 @@ -#include -#include -#include -#include FT_FREETYPE_H -#include FT_GLYPH_H -#include -#include - -typedef struct -{ - int l; - int t; - int r; - int b; -}rect_t; - -typedef struct -{ - FT_Face face; - int height; - int base; - - FT_Glyph glyph[256]; - -}font_t; - -typedef struct -{ - bitmap_t bitmap; - font_t *font; - - char *text; - char **line; - int lines; - int txlines; - int startline; - int endline; - int w; - int h; -}tview_t; - -int init_tview(tview_t *txv, int width, int height, char *text, int size); -void txv_set_size(tview_t *txv, int txw, int txh); -void txv_set_font_size(tview_t *txv, int size); - -int txv_scroll_up(tview_t *txv); -int txv_scroll_down(tview_t *txv); - -void* init_fontlib(); -int draw_text_ext(bitmap_t *winbitmap, FT_Face face, char *text, int len, rect_t *rc, int color); - -void draw_window(void) -{ - BeginDraw(); - DrawWindow(0,0,0,0,NULL,0,0x73); - EndDraw(); -} - -tview_t txv; - -int main(int argc, char *argv[]) -{ - ufile_t uf; - oskey_t key; - int clw = 640; - int clh = 480; - - __asm__ __volatile__( - "int $0x40" - ::"a"(40), "b"(0xc0000027)); - - if(argc < 2) - uf = load_file("/RD/1/EXAMPLE.ASM"); - else uf = load_file(argv[1]); - - if(uf.data == NULL || - uf.size == 0) - return 0; - - init_pixlib(0); - init_fontlib(); - - init_tview(&txv, clw, clh, uf.data, uf.size); - - BeginDraw(); - DrawWindow(10, 40, clw+TYPE_3_BORDER_WIDTH*2, - clh+TYPE_3_BORDER_WIDTH+get_skin_height(), "Text example", 0x000000, 0x73); - blit_bitmap(&txv.bitmap, TYPE_3_BORDER_WIDTH, get_skin_height(), txv.w, txv.h, 0, 0); - - EndDraw(); - - for (;;) - { - uint32_t wheels; - int buttons; - pos_t pos; - - switch (get_os_event()) - { - case 1: - { - char proc_info[1024]; - int winx, winy, winw, winh; - int txw, txh; - - get_proc_info(proc_info); - - winx = *(uint32_t*)(proc_info+34); - winy = *(uint32_t*)(proc_info+38); - winw = *(uint32_t*)(proc_info+42)+1; - winh = *(uint32_t*)(proc_info+46)+1; - - txw = winw - TYPE_3_BORDER_WIDTH*2; - txh = winh - TYPE_3_BORDER_WIDTH - get_skin_height(); - - if( (txw != clw) || - (txh != clh) ) - { - txv_set_size(&txv, txw, txh); - clw = txw; - clh = txh; - }; - - draw_window(); - blit_bitmap(&txv.bitmap, TYPE_3_BORDER_WIDTH, get_skin_height(), txv.w, txv.h, 0, 0); - break; - } - case 2: - key = get_key(); - printf("key %d\n", key.code); - switch(key.code) - { - case 27: - return; - - case 45: - txv_set_font_size(&txv, txv.font->height-3); - blit_bitmap(&txv.bitmap, TYPE_3_BORDER_WIDTH, get_skin_height(), txv.w, txv.h, 0, 0); - break; - - case 61: - txv_set_font_size(&txv, txv.font->height+1); - blit_bitmap(&txv.bitmap, TYPE_3_BORDER_WIDTH, get_skin_height(), txv.w, txv.h, 0, 0); - break; - case 177: - if( txv_scroll_up(&txv) ) - blit_bitmap(&txv.bitmap, TYPE_3_BORDER_WIDTH, get_skin_height(), txv.w, txv.h, 0, 0); - break; - - case 178: - if( txv_scroll_down(&txv) ) - blit_bitmap(&txv.bitmap, TYPE_3_BORDER_WIDTH, get_skin_height(), txv.w, txv.h, 0, 0); - break; - } - break; - - case 3: - // button pressed; we have only one button, close - return; - - case 6: -// pos = get_mouse_pos(); -// buttons = get_mouse_buttons(); - wheels = get_mouse_wheels(); - - if( wheels & 0xFFFF) - { - int r; - - if((short)wheels > 0) - r = txv_scroll_up(&txv); - else - r = txv_scroll_down(&txv); - - if( r ) - blit_bitmap(&txv.bitmap, TYPE_3_BORDER_WIDTH, get_skin_height(), txv.w, txv.h, 0, 0); - } - } - } - return 0; -} + +#include +#include +#include +#include FT_FREETYPE_H +#include FT_GLYPH_H +#include + +#include "winlib.h" + + +typedef struct tview *tview_t; + +tview_t *create_tview(ctx_t *ctx, int width, int height); +void txv_get_margins(const tview_t *txv, rect_t *margins); +void txv_set_margins(tview_t *txv, const rect_t *margins); +void txv_set_size(tview_t *txv, int txw, int txh); +void txv_set_font_size(tview_t *txv, int size); +int txv_get_font_size(tview_t *txv); +void txv_set_text(tview_t *txv, char *text, int size); +int txv_scroll_up(tview_t *txv); +int txv_scroll_down(tview_t *txv); +int txv_page_up(tview_t *txv); +int txv_page_down(tview_t *txv); + +typedef struct +{ + volatile int lock; + unsigned int handle; +}mutex_t; + + +void* init_fontlib(); + +void draw_window(void) +{ + BeginDraw(); + DrawWindow(0,0,0,0,NULL,0,0x73); + EndDraw(); +} + +tview_t *txv; + + + +int main(int argc, char *argv[]) +{ + ufile_t uf; + oskey_t key; + ctx_t *ctx; + rect_t margins = {4,2,20,0}; + + int clw = 640; + int clh = 480; + + + __asm__ __volatile__( + "int $0x40" + ::"a"(40), "b"(0xc0000027)); + + if(argc < 2) + uf = load_file("/RD/1/EXAMPLE.ASM"); + else uf = load_file(argv[1]); + + if(uf.data == NULL || + uf.size == 0) + return 0; + + ctx = create_context(TYPE_3_BORDER_WIDTH, get_skin_height(), clw, clh); + + init_fontlib(); + + txv = create_tview(ctx, clw, clh); + txv_set_margins(txv, &margins); + txv_set_text(txv, uf.data, uf.size); + + BeginDraw(); + DrawWindow(10, 40, clw+TYPE_3_BORDER_WIDTH*2, + clh+TYPE_3_BORDER_WIDTH+get_skin_height(), "Text example", 0x000000, 0x73); + show_context(ctx); + EndDraw(); + + for (;;) + { + uint32_t wheels; + int buttons; + pos_t pos; + + switch (get_os_event()) + { + case 1: + { + char proc_info[1024]; + int winx, winy, winw, winh; + int txw, txh; + char state; + + draw_window(); + + get_proc_info(proc_info); + state = *(char*)(proc_info+70); + if(state & (WIN_STATE_MINIMIZED|WIN_STATE_ROLLED)) + continue; + + winx = *(uint32_t*)(proc_info+34); + winy = *(uint32_t*)(proc_info+38); + winw = *(uint32_t*)(proc_info+42)+1; + winh = *(uint32_t*)(proc_info+46)+1; + + txw = winw - TYPE_3_BORDER_WIDTH*2; + txh = winh - TYPE_3_BORDER_WIDTH - get_skin_height(); + + if( (txw != clw) || + (txh != clh) ) + { + resize_context(ctx, txw, txh); + txv_set_size(txv, txw, txh); + clw = txw; + clh = txh; + }; + + show_context(ctx); + break; + } + case 2: + key = get_key(); +// printf("key %d\n", key.code); + switch(key.code) + { + case 27: + return 0; + + case 45: + txv_set_font_size(txv, txv_get_font_size(txv) - 2); + show_context(ctx); + break; + + case 61: + txv_set_font_size(txv, txv_get_font_size(txv) + 2); + show_context(ctx); + break; + + case 177: + if( txv_scroll_down(txv) ) + show_context(ctx); + break; + + case 178: + if( txv_scroll_up(txv) ) + show_context(ctx); + break; + case 183: + if( txv_page_down(txv) ) + show_context(ctx); + break; + case 184: + if( txv_page_up(txv) ) + show_context(ctx); + break; + } + break; + + case 3: + // button pressed; we have only one button, close + return 0; + + case 6: +// pos = get_mouse_pos(); +// buttons = get_mouse_buttons(); + wheels = get_mouse_wheels(); + + if( wheels & 0xFFFF) + { + int r = 0; + + if((short)wheels > 0) + r = txv_scroll_down(txv); + else if((short)wheels < 0) + r = txv_scroll_up(txv); + + if( r ) + show_context(ctx); + } + } + } + return 0; +} diff --git a/contrib/sdk/samples/freetype/txview/pxdraw/context.c b/contrib/sdk/samples/freetype/txview/pxdraw/context.c new file mode 100644 index 0000000000..2cc0f46dc7 --- /dev/null +++ b/contrib/sdk/samples/freetype/txview/pxdraw/context.c @@ -0,0 +1,339 @@ +#include +#include +#include "pxdraw.h" +#include "internal.h" + +ctx_t* create_context(int x, int y, int width, int height) +{ + ctx_t *ctx; + + ctx = malloc(sizeof(ctx_t)); + if (ctx == NULL) + goto err_0; + + ctx->pitch = ALIGN(width * sizeof(color_t), 16); + ctx->size = ALIGN(ctx->pitch * height, 4096); + + ctx->buffer = user_alloc(ctx->size+4096); + if (ctx->buffer == NULL) + goto err_1; + + ctx->x = x; + ctx->y = y; + ctx->width = width; + ctx->height = height; + + ctx->rc.l = 0; + ctx->rc.t = 0; + ctx->rc.r = width; + ctx->rc.b = height; + + ctx->rcu.l = 0; + ctx->rcu.t = 0; + ctx->rcu.r = ctx->width; + ctx->rcu.b = ctx->height; + ctx->dirty = 1; + + __builtin_cpu_init (); + if (__builtin_cpu_supports ("sse2")) + ctx->px_rect_simd = px_rect_xmm; + else if (__builtin_cpu_supports ("mmx")) + ctx->px_rect_simd = px_rect_mmx; + else + ctx->px_rect_simd = px_rect_alu; + + if (__builtin_cpu_supports ("sse2")) + ctx->px_glyph = px_glyph_sse; + else + ctx->px_glyph = px_glyph_alu; + + return ctx; + +err_1: + free(ctx); +err_0: + return NULL; +}; + +int resize_context(ctx_t *ctx, int width, int height) +{ + int size; + int pitch; + + pitch = ALIGN(width * sizeof(color_t), 16); + size = ALIGN(pitch * height, 4096); + + if (size > ctx->size) + { + ctx->buffer = user_realloc(ctx->buffer, size); /* grow buffer */ + if (ctx->buffer == NULL) + return -1; + + ctx->size = size; + } + else if (size < ctx->size) + user_unmap(ctx->buffer, size, ctx->size - size); /* unmap unused pages */ + + ctx->width = width; + ctx->height = height; + ctx->pitch = pitch; + + ctx->rc.l = 0; + ctx->rc.t = 0; + ctx->rc.r = width; + ctx->rc.b = height; + + ctx->rcu.l = ctx->rcu.t = 0; + ctx->rcu.r = ctx->rcu.b = 0; + + return 0; +}; + +void clear_context(ctx_t *ctx, color_t color) +{ + size_t size; + + size = ctx->pitch * ctx->height; + + if (size >= 1024) + ctx->px_rect_simd(ctx->buffer, ctx->pitch, ctx->width, ctx->height, color); + else + px_rect_alu(ctx->buffer, ctx->pitch, ctx->width, ctx->height, color); + + ctx->rcu.l = 0; + ctx->rcu.t = 0; + ctx->rcu.r = ctx->width; + ctx->rcu.b = ctx->height; + ctx->dirty = 1; +}; + +void show_context(ctx_t *ctx) +{ + struct blit_call bc; + int ret; + + bc.dstx = ctx->x; + bc.dsty = ctx->y; + bc.w = ctx->width; + bc.h = ctx->height; + bc.srcx = 0; + bc.srcy = 0; + bc.srcw = ctx->width; + bc.srch = ctx->height; + bc.stride = ctx->pitch; + bc.bitmap = ctx->buffer; + + __asm__ __volatile__( + "int $0x40":"=a"(ret):"a"(73), "b"(0x00), + "c"(&bc):"memory"); + + ctx->dirty = 0; +}; + +void scroll_context(ctx_t *ctx, int dst_y, int src_y, int rows) +{ + char *dst; + char *src; + + dst = ctx->buffer + dst_y * ctx->pitch; + src = ctx->buffer + src_y * ctx->pitch; + + __builtin_memmove(dst, src, rows * ctx->pitch); + ctx->dirty = 1; +} + +static int clip_rect(const rect_t *clip, rect_t *rc) +{ + if (rc->l > rc->r) + return 1; + if (rc->t > rc->b) + return 1; + + if (rc->l < clip->l) + rc->l = clip->l; + else if (rc->l >= clip->r) + return 1; + + if (rc->t < clip->t) + rc->t = clip->t; + else if (rc->t >= clip->b) + return 1; + + if (rc->r < clip->l) + return 1; + else if (rc->r > clip->r) + rc->r = clip->r; + + if (rc->b < clip->t) + return 1; + else if (rc->b > clip->b) + rc->b = clip->b; + + if ((rc->l == rc->r) || + (rc->t == rc->b)) + return 1; + return 0; +} + +int px_hline(ctx_t*ctx, int x, int y, int width, color_t color) +{ + char *dst_addr; + + int xr = x + width; + + if(y < ctx->rc.t) + return 0; + else if(y >= ctx->rc.b) + return 0; + + if(x < ctx->rc.l) + x = ctx->rc.l; + else if(x >= ctx->rc.r) + return 0; + + if(xr <= ctx->rc.l) + return 0; + else if(xr > ctx->rc.r) + xr = ctx->rc.r; + + dst_addr = ctx->buffer; + dst_addr+= ctx->pitch * y + x * sizeof(color_t); + + __asm__ __volatile__ + (" cld; rep stosl\n\t" + :: "D" (dst_addr),"c" (xr-x), "a" (color) + : "flags"); +}; + +void px_vline(ctx_t*ctx, int x, int y, int height, color_t color) +{ + char *dst_addr; + + int yb = y + height; + + if(x < ctx->rc.l) + return; + else if(x >= ctx->rc.r) + return; + + if(y < ctx->rc.t) + y = ctx->rc.t; + else if(y >= ctx->rc.b) + return; + + if(yb <= ctx->rc.t) + return; + else if(yb > ctx->rc.b) + yb = ctx->rc.b; + + dst_addr = ctx->buffer; + dst_addr+= ctx->pitch * y + x * sizeof(color_t); + + while(y < yb) + { + color_t *t = (color_t*)dst_addr; + *t = color; + y++; + dst_addr+= ctx->pitch; + }; +}; + +static int do_fill_rect(ctx_t *ctx, rect_t *rc, color_t color) +{ + if (!clip_rect(&ctx->rc, rc)) + { + int w, h; + char *dst_addr; + + w = rc->r - rc->l; + h = rc->b - rc->t; + + dst_addr = ctx->buffer; + dst_addr += ctx->pitch * rc->t + rc->l * sizeof(color_t); + if (w * h >= 256) + ctx->px_rect_simd(dst_addr, ctx->pitch, w, h, color); + else + px_rect_alu(dst_addr, ctx->pitch, w, h, color); + return 1; + }; + return 0; +}; + +void px_fill_rect(ctx_t *ctx, const rect_t *src, color_t color) +{ + rect_t rc = *src; + int update; + + update = do_fill_rect(ctx, &rc, color); + + if(update) + { + if (rc.l < ctx->rcu.l) + ctx->rcu.l = rc.l; + if (rc.t < ctx->rcu.t) + ctx->rcu.t = rc.t; + if (rc.r > ctx->rcu.r) + ctx->rcu.r = rc.r; + if (rc.b > ctx->rcu.b) + ctx->rcu.b = rc.b; + ctx->dirty = 1; + }; +} + +void px_fill_region(ctx_t *ctx, const rgn_t *rgn, color_t color) +{ + int update = 0; + + for (int i = 0; i < rgn->num_rects; i++) + { + rect_t rc = rgn->rects[i]; + update |= do_fill_rect(ctx, &rc, color); + } + + if (update) + { + if (rgn->extents.l < ctx->rcu.l) + ctx->rcu.l = rgn->extents.l; + if (rgn->extents.t < ctx->rcu.t) + ctx->rcu.t = rgn->extents.t; + if (rgn->extents.r > ctx->rcu.r) + ctx->rcu.r = rgn->extents.r; + if (rgn->extents.b > ctx->rcu.b) + ctx->rcu.b = rgn->extents.b; + ctx->dirty = 1; + }; +} + +void px_draw_glyph(ctx_t *ctx, const void *buffer, int pitch, const rect_t *rc, color_t color) +{ + rect_t rc_dst = *rc; + int srcx, srcy; + + if (!clip_rect(&ctx->rc, &rc_dst)) + { + int width; + int height; + unsigned char *dst = ctx->buffer; + const unsigned char *src = buffer; + + width = rc_dst.r - rc_dst.l; + height = rc_dst.b - rc_dst.t; + + srcx = rc_dst.l - rc->l; + srcy = rc_dst.t - rc->t; + dst += ctx->pitch * rc_dst.t + rc_dst.l * sizeof(color_t); + src += pitch * srcy + srcx; + ctx->px_glyph(dst, ctx->pitch, src, pitch, width, height, color); + + if (rc_dst.l < ctx->rcu.l) + ctx->rcu.l = rc_dst.l; + if (rc_dst.t < ctx->rcu.t) + ctx->rcu.t = rc_dst.t; + if (rc_dst.r > ctx->rcu.r) + ctx->rcu.r = rc_dst.r; + if (rc_dst.b > ctx->rcu.b) + ctx->rcu.b = rc_dst.b; + + ctx->dirty = 1; + }; +}; diff --git a/contrib/sdk/samples/freetype/txview/pxdraw/dutils.c b/contrib/sdk/samples/freetype/txview/pxdraw/dutils.c new file mode 100644 index 0000000000..1cd687f230 --- /dev/null +++ b/contrib/sdk/samples/freetype/txview/pxdraw/dutils.c @@ -0,0 +1,226 @@ +#include +#include +#include + +typedef unsigned int color_t; + +void px_rect_alu(void *dst_addr, int pitch, int w, int h, color_t src_color) +{ + while (h--) + { + char *tmp = dst_addr; + dst_addr = tmp + pitch; + __asm__ __volatile__( + "cld; rep stosl\n\t" + :: "D"(tmp), "a"(src_color), "c"(w) + : "flags"); + }; +}; + +void px_rect_mmx(void *dst_addr, int pitch, int w, int h, color_t src_color) +{ + register __m64 color; + + color = _mm_cvtsi32_si64(src_color); + color = _mm_unpacklo_pi32(color, color); + + while (h--) + { + char *tmp = dst_addr; + char *end = tmp + w * sizeof(color_t); + dst_addr = tmp + pitch; + + int t = (int)tmp; + if (t & 4) + { + *(color_t*)tmp = src_color; + tmp += 4; + }; + + while (tmp + 64 <= end) + { + __m64 *_tmp = (__m64*)tmp; + _tmp[0] = color; + _tmp[1] = color; + _tmp[2] = color; + _tmp[3] = color; + _tmp[4] = color; + _tmp[5] = color; + _tmp[6] = color; + _tmp[7] = color; + tmp += 64; + }; + if (tmp + 32 <= end) + { + __m64 *_tmp = (__m64*)tmp; + _tmp[0] = color; + _tmp[1] = color; + _tmp[2] = color; + _tmp[3] = color; + tmp += 32; + }; + if (tmp + 16 <= end) + { + __m64 *_tmp = (__m64*)tmp; + _tmp[0] = color; + _tmp[1] = color; + tmp += 16; + }; + if (tmp + 8 <= end) + { + __m64 *_tmp = (__m64*)tmp; + _tmp[0] = color; + tmp += 8; + }; + if (tmp < end) + *(color_t*)tmp = src_color; + }; + _mm_empty(); +}; + +void px_rect_xmm(void *dst_addr, int pitch, int w, int h, color_t dst_color) +{ + __m128i color; + + color = _mm_set_epi32(dst_color, dst_color, dst_color, dst_color); + + while (h--) + { + char *tmp = dst_addr; + char *end = tmp + w * sizeof(color_t); + dst_addr = tmp + pitch; + + if ((int)tmp & 4) + { + *(color_t*)tmp = dst_color; + tmp += 4; + }; + if ((int)tmp & 8) + { + __m128i *_tmp = (__m128i*)tmp; + _mm_storel_epi64(_tmp, color); + tmp += 8; + }; + + while (tmp + 128 <= end) + { + __m128i *_tmp = (__m128i*)tmp; + _mm_store_si128(&_tmp[0], color); + _mm_store_si128(&_tmp[1], color); + _mm_store_si128(&_tmp[2], color); + _mm_store_si128(&_tmp[3], color); + _mm_store_si128(&_tmp[4], color); + _mm_store_si128(&_tmp[5], color); + _mm_store_si128(&_tmp[6], color); + _mm_store_si128(&_tmp[7], color); + tmp += 128; + }; + if (tmp + 64 <= end) + { + __m128i *_tmp = (__m128i*)tmp; + _mm_store_si128(&_tmp[0], color); + _mm_store_si128(&_tmp[1], color); + _mm_store_si128(&_tmp[2], color); + _mm_store_si128(&_tmp[3], color); + tmp += 64; + }; + if (tmp + 32 <= end) + { + __m128i *_tmp = (__m128i*)tmp; + _mm_store_si128(&_tmp[0], color); + _mm_store_si128(&_tmp[1], color); + tmp += 32; + }; + if (tmp + 16 <= end) + { + __m128i *_tmp = (__m128i*)tmp; + _mm_store_si128(&_tmp[0], color); + tmp += 16; + }; + if (tmp + 8 <= end) + { + __m128i *_tmp = (__m128i*)tmp; + _mm_storel_epi64(_tmp, color); + tmp += 8; + }; + if (tmp < end) + *(color_t*)tmp = dst_color; + }; +} + +void px_glyph_alu(void *dst_addr, int dst_pitch,const void *src_addr, int src_pitch, + int width, int height, color_t src_color) +{ + while (height-- > 0) + { + int w = width; + const unsigned char *src = src_addr; + color_t *dst = dst_addr; + + dst_addr = (char*)dst + dst_pitch; + src_addr = src + src_pitch; + + while (w-- > 0) + { + unsigned char a = *src++; + color_t dst_color = *(color_t*)dst; + unsigned int rb = dst_color & 0xff00ff; + unsigned int g = dst_color & 0x00ff00; + + rb += ((src_color & 0xff00ff) - rb) * a >> 8; + g += ((src_color & 0x00ff00) - g) * a >> 8; + + *dst++ = (src_color & 0xFF000000) | (rb & 0xff00ff) | (g & 0xff00); + }; + } +} + +__m64 m_4x0080 = { 0x00800080, 0x00800080 }; +__m64 m_4x0101 = { 0x01010101, 0x01010101 }; +__m64 m_4x00FF = { 0x00FF00FF, 0x00FF00FF }; +__m64 m_zero = { 0 }; + +void px_glyph_sse(void *dst_addr, int dst_pitch, const void *src_addr, int src_pitch, + int width, int height, color_t src_color) +{ + static __m64 m_4x0080 = { 0x00800080, 0x00800080 }; + static __m64 m_4x0101 = { 0x01010101, 0x01010101 }; + static __m64 m_4x00FF = { 0x00FF00FF, 0x00FF00FF }; + static __m64 m_zero = { 0 }; + + __m64 color; + + color = _mm_cvtsi32_si64(src_color); + color = _m_punpcklbw(color, m_zero); + while (height-- > 0) + { + int w = width; + const unsigned char *tmpsrc = src_addr; + color_t *tmpdst = dst_addr; + + dst_addr = (char*)tmpdst + dst_pitch; + src_addr = tmpsrc + src_pitch; + + while (w-- > 0) + { + __m64 m_alpha, m_1_minus_alpha; + __m64 src_alpha, dst_color; + + unsigned int alpha = *tmpsrc++; + m_alpha = _mm_cvtsi32_si64((alpha << 16) | alpha); + dst_color = _mm_cvtsi32_si64(*(int*)tmpdst); + + m_alpha = _mm_unpacklo_pi32(m_alpha, m_alpha); + m_1_minus_alpha = _m_psubb(m_4x00FF, m_alpha); + dst_color = _m_punpcklbw(dst_color, m_zero); + src_alpha = _m_pmullw(color, m_alpha); + dst_color = _m_pmullw(dst_color, m_1_minus_alpha); + dst_color = _m_paddw(src_alpha, dst_color); + dst_color = _m_paddw(dst_color, m_4x0080); + dst_color = _mm_mulhi_pu16(dst_color, m_4x0101); + dst_color = _mm_packs_pu16(dst_color, dst_color); + *tmpdst++ = _mm_cvtsi64_si32(dst_color); + }; + } + _mm_empty(); +}; diff --git a/contrib/sdk/samples/freetype/txview/pxdraw/internal.h b/contrib/sdk/samples/freetype/txview/pxdraw/internal.h new file mode 100644 index 0000000000..e4b35efcb6 --- /dev/null +++ b/contrib/sdk/samples/freetype/txview/pxdraw/internal.h @@ -0,0 +1,31 @@ + +#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask)) +#define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1) + +struct context +{ + int x; + int y; + int width; + int height; + rect_t rc; + rect_t rcu; + void *buffer; + size_t pitch; + size_t size; + int dirty; + void (*px_rect_simd)(void *dst_addr, int pitch, int w, int h, color_t dst_color); + void (*px_glyph)(void *dst_addr, int dst_pitch, const void *src_addr, int src_pitch, + int width, int height, color_t src_color); +}; + + +void px_rect_alu(void *dst_addr, int pitch, int w, int h, color_t src_color); +void px_rect_mmx(void *dst_addr, int pitch, int w, int h, color_t src_color); +void px_rect_xmm(void *dst_addr, int pitch, int w, int h, color_t dst_color); +void px_glyph_alu(void *dst_addr, int dst_pitch,const void *src_addr, + int src_pitch, int width, int height, color_t src_color); + +void px_glyph_sse(void *dst_addr, int dst_pitch, const void *src_addr, + int src_pitch, int width, int height, color_t src_color); + diff --git a/contrib/sdk/samples/freetype/txview/pxdraw/pxdraw.h b/contrib/sdk/samples/freetype/txview/pxdraw/pxdraw.h new file mode 100644 index 0000000000..68b6a874eb --- /dev/null +++ b/contrib/sdk/samples/freetype/txview/pxdraw/pxdraw.h @@ -0,0 +1,46 @@ +#ifndef __PXDRAW_H__ +#define __PXDRAW_H__ + +#include + +#if defined __cplusplus +extern "C" { +#endif + +typedef unsigned int color_t; +typedef struct context ctx_t; + +typedef struct +{ + int l; + int t; + int r; + int b; +}rect_t; + +typedef struct +{ + int num_rects; + rect_t *rects; + rect_t extents; +}rgn_t; + +rgn_t* create_round_rect_rgn(int left, int top, int right, int bottom, + int ellipse_width, int ellipse_height); +void destroy_region(rgn_t *rgn); + +ctx_t* create_context(int x, int y, int width, int height); +int resize_context(ctx_t *ctx, int width, int height); +void clear_context(ctx_t *ctx, color_t color); +void show_context(ctx_t *ctx); +void scroll_context(ctx_t *ctx, int dst_y, int src_y, int rows); + +int px_hline(ctx_t*ctx, int x, int y, int width, color_t color); +void px_vline(ctx_t*ctx, int x, int y, int height, color_t color); +void px_fill_rect(ctx_t *ctx, const rect_t *src, color_t color); +void px_draw_glyph(ctx_t *ctx, const void *buffer, int pitch, const rect_t *rc, color_t color); + +#if defined __cplusplus +} +#endif +#endif /* __PXDRAW_H__ */ diff --git a/contrib/sdk/samples/freetype/txview/pxdraw/region.c b/contrib/sdk/samples/freetype/txview/pxdraw/region.c new file mode 100644 index 0000000000..059f7616d9 --- /dev/null +++ b/contrib/sdk/samples/freetype/txview/pxdraw/region.c @@ -0,0 +1,93 @@ +#include +#include "pxdraw.h" + +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#define min(a,b) (((a) < (b)) ? (a) : (b)) + +rgn_t* create_round_rect_rgn(int left, int top, int right, int bottom, + int ellipse_width, int ellipse_height) +{ + rgn_t *obj; + rect_t *rects; + int a, b, i, x, y; + int64_t asq, bsq, dx, dy, err; + + right--; + bottom--; + + ellipse_width = min(right - left, abs(ellipse_width)); + ellipse_height = min(bottom - top, abs(ellipse_height)); + + obj = malloc(sizeof(rgn_t)); + if (obj == NULL) + return NULL; + + obj->num_rects = ellipse_height; + obj->extents.l = left; + obj->extents.t = top; + obj->extents.r = right; + obj->extents.b = bottom; + + obj->rects = rects = malloc(obj->num_rects * sizeof(rect_t)); + if (rects == NULL) + { + free(obj); + return NULL; + }; + + /* based on an algorithm by Alois Zingl */ + + a = ellipse_width - 1; + b = ellipse_height - 1; + asq = (int64_t)8 * a * a; + bsq = (int64_t)8 * b * b; + dx = (int64_t)4 * b * b * (1 - a); + dy = (int64_t)4 * a * a * (1 + (b % 2)); + err = dx + dy + a * a * (b % 2); + + x = 0; + y = ellipse_height / 2; + + rects[y].l = left; + rects[y].r = right; + + while (x <= ellipse_width / 2) + { + int64_t e2 = 2 * err; + if (e2 >= dx) + { + x++; + err += dx += bsq; + } + if (e2 <= dy) + { + y++; + err += dy += asq; + rects[y].l = left + x; + rects[y].r = right - x; + } + } + + for (i = 0; i < ellipse_height / 2; i++) + { + rects[i].l = rects[b - i].l; + rects[i].r = rects[b - i].r; + rects[i].t = top + i; + rects[i].b = rects[i].t + 1; + } + for (; i < ellipse_height; i++) + { + rects[i].t = bottom - ellipse_height + i; + rects[i].b = rects[i].t + 1; + } + rects[ellipse_height / 2].t = top + ellipse_height / 2; /* extend to top of rectangle */ + + return obj; +}; + +void destroy_region(rgn_t *rgn) +{ + free(rgn->rects); + free(rgn); +}; + diff --git a/contrib/sdk/samples/freetype/txview/tview.c b/contrib/sdk/samples/freetype/txview/tview.c index 241b516825..bfa65f5af4 100644 --- a/contrib/sdk/samples/freetype/txview/tview.c +++ b/contrib/sdk/samples/freetype/txview/tview.c @@ -4,7 +4,6 @@ #include FT_FREETYPE_H #include FT_GLYPH_H #include "winlib.h" -#include "draw2.h" int init_fontlib(); font_t *create_font(FT_Face face, int size); @@ -87,7 +86,12 @@ static void txv_redraw(tview_t *txv) rect_t rc; int i; - draw_rect(txv->ctx, 0, 0, txv->w, txv->h, 0xFFFFFFFF); + rc.l = 0; + rc.t = 0; + rc.r = txv->w; + rc.b = txv->h; + + px_fill_rect(txv->ctx, &rc, 0xFFFFFFFF); rc.l = txv->margins.l; rc.t = txv->margins.t; @@ -162,14 +166,14 @@ int txv_scroll_down(tview_t *txv) dst = txv->margins.t; src = dst + txv->line_height; rows = txv->line_height * (txv->pagesize-1); - scroll_ctx(txv->ctx, dst, src, rows ); + scroll_context(txv->ctx, dst, src, rows ); rc.l = txv->margins.l; rc.t = txv->margins.t + rows; rc.r = txv->w - txv->margins.r; rc.b = rc.t + txv->line_height; - draw_rect(txv->ctx, rc.l, rc.t, rc.r - rc.l, txv->line_height, 0xFFFFFFFF); + px_fill_rect(txv->ctx, &rc, 0xFFFFFFFF); draw_text_ext(txv->ctx, txv->font, txv->line[txv->endline], txv->line[txv->endline+1]-txv->line[txv->endline], &rc, 0xFF000000); @@ -181,7 +185,7 @@ int txv_scroll_down(tview_t *txv) { rc.t+= txv->line_height; rc.b+= txv->line_height; - draw_rect(txv->ctx, rc.l, rc.t, rc.r - rc.l, txv->line_height, 0xFFFFFFFF); + px_fill_rect(txv->ctx, &rc, 0xFFFFFFFF); draw_text_ext(txv->ctx, txv->font, txv->line[txv->endline], txv->line[txv->endline+1]-txv->line[txv->endline], &rc, 0xFF000000); } @@ -202,14 +206,14 @@ int txv_scroll_up(tview_t *txv) src = txv->margins.t; dst = src + txv->line_height; - scroll_ctx(txv->ctx, dst, src, rows); + scroll_context(txv->ctx, dst, src, rows); rc.l = txv->margins.l; rc.t = txv->margins.t; rc.r = txv->w - txv->margins.r; rc.b = rc.t + txv->line_height; - draw_rect(txv->ctx, rc.l, rc.t, rc.r - rc.l, txv->line_height, 0xFFFFFFFF); + px_fill_rect(txv->ctx, &rc, 0xFFFFFFFF); txv->startline--; txv->endline--; diff --git a/contrib/sdk/samples/freetype/txview/winlib/button.c b/contrib/sdk/samples/freetype/txview/winlib/button.c new file mode 100644 index 0000000000..1a63a68264 --- /dev/null +++ b/contrib/sdk/samples/freetype/txview/winlib/button.c @@ -0,0 +1,158 @@ +#include +#include +#include "winlib.h" + +typedef struct +{ + ctrl_t ctrl; + + uint32_t state; + + char *caption; + int capt_len; +}button_t; + +static void button_on_draw(button_t *btn) +{ + color_t color = 0xFFD7D7D7; + char t = (char)btn->ctrl.id; + rect_t rc, rci; + + if(btn->ctrl.style & 1) + { + send_message(btn->ctrl.parent, MSG_OWNERDRAW, btn, 0); + return; + } + + if(btn->state & bPressed) + color = 0xFFB0B0B0; + else if(btn->state & bHighlight) + color = 0xFFE7E7E7; + + rc = rci = btn->ctrl.rc; + rci.l++; + rci.t++; + + px_hline(btn->ctrl.ctx, rc.l, rc.t, btn->ctrl.w, 0xFF646464); + px_fill_rect(btn->ctrl.ctx, &rci, color); + px_hline(btn->ctrl.ctx, rc.l, rc.b-1, btn->ctrl.w, 0xFF646464); + px_vline(btn->ctrl.ctx, rc.l, rc.t+1, btn->ctrl.h-2, 0xFF646464); + px_vline(btn->ctrl.ctx, rc.r-1, rc.t+1, btn->ctrl.h-2, 0xFF646464); + + rc.l+= 4; + rc.t+= 6; + + draw_text_ext(btn->ctrl.ctx, btn->ctrl.font, btn->caption, btn->capt_len, &rc, 0xFF000000); +}; + +static void button_on_mouseenter(button_t *btn) +{ + btn->state|= bHighlight; + send_message(&btn->ctrl, MSG_DRAW, 0, 0); +} + +static void button_on_mouseleave(button_t *btn) +{ + if( (ctrl_t*)btn != mouse_capture) { + btn->state &= ~bHighlight; + send_message(&btn->ctrl, MSG_DRAW, 0, 0); + }; +} + +static void button_on_lbuttondown(button_t *btn, int x, int y) +{ + capture_mouse((ctrl_t*)btn); + btn->state|= bPressed; + send_message(&btn->ctrl, MSG_DRAW, 0, 0); +}; + +static void button_on_lbuttonup(button_t *btn, int x, int y) +{ + int action; + + action = (btn->state & bPressed) ? MSG_COMMAND : 0; + + release_mouse(); + + if( pt_in_rect( &btn->ctrl.rc, x, y) ) + btn->state = bHighlight; + else + btn->state = 0; + + send_message(&btn->ctrl, MSG_DRAW, 0, 0); + + if(action) + send_message(btn->ctrl.parent,MSG_COMMAND,btn->ctrl.id,(int)btn); +}; + +static void button_on_mousemove(button_t *btn, int x, int y) +{ + int old_state; + + if( !(btn->state & bHighlight)) + { + btn->state|= bHighlight; + send_message(&btn->ctrl, MSG_DRAW, 0, 0); + }; + + if( (ctrl_t*)btn != mouse_capture) + return; + + old_state = btn->state; + + if( pt_in_rect(&btn->ctrl.rc, x, y) ) + btn->state |= bPressed; + else + btn->state &= ~bPressed; + + if( old_state ^ btn->state) + send_message(&btn->ctrl, MSG_DRAW, 0, 0); +} + +int button_proc(ctrl_t *ctrl, uint32_t msg, uint32_t arg1, uint32_t arg2) +{ + button_t *btn = (button_t*)ctrl; + + switch( msg ) + { + HANDLE_MSG(btn, MSG_DRAW, button_on_draw); + HANDLE_MSG(btn, MSG_MOUSEENTER, button_on_mouseenter); + HANDLE_MSG(btn, MSG_MOUSELEAVE, button_on_mouseleave); + HANDLE_MSG(btn, MSG_LBTNDOWN, button_on_lbuttondown); + HANDLE_MSG(btn, MSG_LBTNDBLCLK, button_on_lbuttondown); + HANDLE_MSG(btn, MSG_LBTNUP, button_on_lbuttonup); + HANDLE_MSG(btn, MSG_MOUSEMOVE, button_on_mousemove); + } + return 0; +}; + +ctrl_t *create_button(char *caption, uint32_t style, int id, int x, int y, + int w, int h, ctrl_t *parent) +{ + button_t *btn; + int len; + + if( !parent ) + return NULL; + + btn = create_control(sizeof(button_t), id, x, y, w, h, parent); + btn->ctrl.style = style; + btn->ctrl.handler = button_proc; + btn->state = 0; + btn->caption = caption; + + if( !caption ) + btn->capt_len = 0; + else + { + len = strlen(caption); + btn->capt_len = len; + if( len ) + btn->caption = strdup(caption); + else + btn->caption = NULL; + } + + return &btn->ctrl; +}; + diff --git a/contrib/sdk/samples/freetype/txview/winlib/control.h b/contrib/sdk/samples/freetype/txview/winlib/control.h new file mode 100644 index 0000000000..b9199065c7 --- /dev/null +++ b/contrib/sdk/samples/freetype/txview/winlib/control.h @@ -0,0 +1,109 @@ +#ifndef __CONTROL_H__ +#define __CONTROL_H_ + +#include +#include +#include "link.h" + +typedef struct font font_t; + +typedef struct control ctrl_t; + +typedef int (handler_t)(ctrl_t*, uint32_t, uint32_t, uint32_t); + +struct control +{ + link_t link; + link_t child; + + handler_t *handler; + ctrl_t *parent; + + ctx_t *ctx; + font_t *font; + uint32_t id; + uint32_t style; + + rect_t rc; + int w; + int h; +}; + +void *create_control(size_t size, int id, int x, int y, + int w, int h, ctrl_t *parent); + +#define bPressed 2 +#define bHighlight 1 + + +ctrl_t *create_button(char *caption, uint32_t style, int id, int x, int y, + int w, int h, ctrl_t *parent); + +typedef struct +{ + ctrl_t ctrl; + + uint32_t state; + + int pix_range; + int min_range; + int max_range; + int page_size; + int thumb_pos; + + rect_t tl_rect; + rect_t br_rect; + + ctrl_t *btn_up; + ctrl_t *btn_down; + ctrl_t *thumb; +}scroller_t; + + +#define MSG_SYS_PAINT 0x001 +#define MSG_SYS_KEY 0x002 +#define MSG_SYS_BUTTON 0x003 +#define MSG_SYS_MOUSE 0x006 + +#define MSG_LBTNDOWN 0x010 +#define MSG_LBTNUP 0x011 +#define MSG_RBTNDOWN 0x012 +#define MSG_RBTNUP 0x013 +#define MSG_MBTNDOWN 0x014 +#define MSG_MBTNUP 0x015 +#define MSG_WHEELDOWN 0x016 +#define MSG_WHEELUP 0x017 + +#define MSG_LBTNDBLCLK 0x018 + +#define MSG_MOUSEMOVE 0x019 +#define MSG_MOUSEENTER 0x01A +#define MSG_MOUSELEAVE 0x01B + +#define MSG_CREATE 0x020 +#define MSG_SIZE 0x021 +#define MSG_DRAW 0x022 +#define MSG_OWNERDRAW 0x023 +#define MSG_POSCHANGING 0x024 +#define MSG_POSCHANGE 0x025 + +#define MSG_COMMAND 0x030 + +static inline int pt_in_rect(rect_t *rc, int x, int y) +{ + if( (x >= rc->l) && (x < rc->r) && + (y >= rc->t) && (y < rc->b) ) + return 1; + return 0; +}; + + +#define send_message( ctrl, msg, arg1, arg2) \ + (ctrl)->handler( (ctrl_t*)(ctrl), \ + (uint32_t)(msg), (uint32_t)(arg1), (uint32_t)(arg2)) + +#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask)) +#define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1) + + +#endif /* __CONTROL_H_ */ diff --git a/contrib/sdk/samples/freetype/txview/winlib/link.h b/contrib/sdk/samples/freetype/txview/winlib/link.h new file mode 100644 index 0000000000..9162095657 --- /dev/null +++ b/contrib/sdk/samples/freetype/txview/winlib/link.h @@ -0,0 +1,64 @@ +#ifndef __LINK_H__ +#define __LINK_H__ + +typedef struct link +{ + struct link *prev; + struct link *next; +}link_t; + +#define LIST_INITIALIZE(name) \ + link_t name = { .prev = &name, .next = &name } + +#define list_get_instance(link, type, member) \ + ((type *)(((u8_t *)(link)) - ((u8_t *)&(((type *)NULL)->member)))) + +static inline void link_initialize(link_t *link) +{ + link->prev = NULL; + link->next = NULL; +} + +static inline void list_initialize(link_t *head) +{ + head->prev = head; + head->next = head; +} + +static inline void list_append(link_t *link, link_t *head) +{ + link->prev = head->prev; + link->next = head; + head->prev->next = link; + head->prev = link; +} + +static inline void list_remove(link_t *link) +{ + link->next->prev = link->prev; + link->prev->next = link->next; + link_initialize(link); +} + +static inline int list_empty(link_t *head) +{ + return head->next == head ? 1 : 0; +} + +static inline void list_prepend(link_t *link, link_t *head) +{ + link->next = head->next; + link->prev = head; + head->next->prev = link; + head->next = link; +} + +static inline void list_insert(link_t *new, link_t *old) +{ + new->prev = old->prev; + new->next = old; + new->prev->next = new; + old->prev = new; +} + +#endif /* __LINK_H__ */ diff --git a/contrib/sdk/samples/freetype/txview/winlib/winlib.c b/contrib/sdk/samples/freetype/txview/winlib/winlib.c new file mode 100644 index 0000000000..152a2c5d7a --- /dev/null +++ b/contrib/sdk/samples/freetype/txview/winlib/winlib.c @@ -0,0 +1,615 @@ +#include +#include +#include "winlib.h" + +#define ID_SCROLLER_UP 0x30 +#define ID_SCROLLER_DOWN 0x31 +#define ID_SCROLLER_THUMB 0x32 + +typedef int v2si __attribute__ ((vector_size (8))); + +font_t *create_font(void *face, int size); + +static pos_t old_pos; +ctrl_t *mouse_capture = NULL; + + + +void show_window(window_t *win) +{ + BeginDraw(); + DrawWindow(0,0,0,0,NULL,0,0x73); + if( (win->win_state != MINIMIZED) && + (win->win_state != ROLLED) ) + show_context(win->ctx); + EndDraw(); +} + +window_t *create_window(char *caption, int style, int x, int y, + int w, int h, handler_t handler) +{ + char proc_info[1024]; + window_t *win; + + if(handler==NULL) + return NULL; + + win = malloc(sizeof(*win)); + if(win == NULL) + return NULL; + + BeginDraw(); + DrawWindow(x, y, w+TYPE_3_BORDER_WIDTH*2, + h+TYPE_3_BORDER_WIDTH+get_skin_height(), caption, 0x000000, 0x73); + EndDraw(); + + GetProcInfo(proc_info); + + x = *(uint32_t*)(proc_info+34); + y = *(uint32_t*)(proc_info+38); + w = *(uint32_t*)(proc_info+42)+1; + h = *(uint32_t*)(proc_info+46)+1; + + win->handler = handler; + + list_initialize(&win->link); + list_initialize(&win->child); + + win->rc.l = x; + win->rc.t = y; + win->rc.r = x + w; + win->rc.b = y + h; + + win->w = w; + win->h = h; + + win->client.l = TYPE_3_BORDER_WIDTH; + win->client.t = get_skin_height(); + win->client.r = w - TYPE_3_BORDER_WIDTH; + win->client.b = h - TYPE_3_BORDER_WIDTH; + win->clw = win->client.r - win->client.l; + win->clh = win->client.b - win->client.t; + + win->caption_txt = caption; + win->style = style; + + win->child_over = NULL; + win->child_focus = NULL; + + win->ctx = create_context(win->client.l, win->client.t, win->clw, win->clh); + clear_context(win->ctx, 0xFFFFFFFF); + + win->font = create_font(NULL, 14); + + send_message((ctrl_t*)win, MSG_CREATE, 0, 0); + send_message((ctrl_t*)win, MSG_DRAW, 0, 0); + + ctrl_t *child; + + child = (ctrl_t*)win->child.next; + + while( &child->link != &win->child) + { + send_message(child, MSG_DRAW, 0, 0); + child = (ctrl_t*)child->link.next; + }; + + show_window(win); + + return win; +}; + + +void handle_sys_paint(window_t *win) +{ + char proc_info[1024]; + int winx, winy, winw, winh; + uint8_t state; + + GetProcInfo(proc_info); + + winx = *(uint32_t*)(proc_info+34); + winy = *(uint32_t*)(proc_info+38); + winw = *(uint32_t*)(proc_info+42)+1; + winh = *(uint32_t*)(proc_info+46)+1; + + state = *(uint8_t*)(proc_info+70); + + if(state & 2) + { + win->win_state = MINIMIZED; + return; + } + else if(state & 4) + { + win->win_state = ROLLED; + show_window(win); + return; + }; + + if(state & 1) + state = MAXIMIZED; + else + state = NORMAL; + + if( (win->w != winw) || + (win->h != winh) ) + { + ctrl_t *child; + + win->client.l = TYPE_3_BORDER_WIDTH; + win->client.t = get_skin_height(); + win->client.r = winw - TYPE_3_BORDER_WIDTH; + win->client.b = winh - TYPE_3_BORDER_WIDTH; + win->clw = win->client.r - win->client.l; + win->clh = win->client.b - win->client.t; + + resize_context(win->ctx, win->clw, win->clh); + + clear_context(win->ctx, 0xFFFFFFFF); + + send_message((ctrl_t*)win, MSG_SIZE, 0, 0); + send_message((ctrl_t*)win, MSG_DRAW, 0, 0); + + child = (ctrl_t*)win->child.next; + + while( &child->link != &win->child) + { + send_message(child, MSG_DRAW, 0, 0); + child = (ctrl_t*)child->link.next; + }; + } + + win->rc.l = winx; + win->rc.t = winy; + win->rc.r = winx + winw; + win->rc.b = winy + winh; + win->w = winw; + win->h = winh; + win->win_state = state; + + show_window(win); +}; + + +ctrl_t *get_child(ctrl_t *ctrl, int x, int y) +{ + ctrl_t *child = NULL; + + ctrl_t *tmp = (ctrl_t*)ctrl->child.next; + + while( &tmp->link != &ctrl->child ) + { + if(pt_in_rect(&tmp->rc, x, y)) + { + child = get_child(tmp, x, y); + return child == NULL ? tmp : child; + }; + tmp = (ctrl_t*)tmp->link.next; + }; + return child; +}; + + +int send_mouse_message(window_t *win, uint32_t msg) +{ + ctrl_t *child; + + if(mouse_capture) + return send_message(mouse_capture, msg, 0, old_pos.val); + + child = get_child((ctrl_t*)win, old_pos.x, old_pos.y); + + if(msg == MSG_MOUSEMOVE) + { + if( win->child_over ) + { + if(child == win->child_over) + send_message(child, MSG_MOUSEMOVE, 0, old_pos.val); + else + send_message(win->child_over, MSG_MOUSELEAVE, 0, old_pos.val); + } + else if( child ) + send_message(child, MSG_MOUSEENTER, 0, old_pos.val); + + win->child_over = child; + }; + + if( child ) + return send_message(child, msg, 0, old_pos.val); + + if(pt_in_rect(&win->client, old_pos.x, old_pos.y)) + return send_message((ctrl_t*)win, msg, 0, old_pos.val); + +}; + +#define DBG(x) + +static void handle_sys_mouse(window_t *win) +{ + static uint32_t mouse_click_time; + static int mouse_action; + static int old_buttons; + int buttons; + uint32_t wheels; + uint32_t click_time; + int action; + + pos_t pos; + + mouse_action = 0; + pos = get_mouse_pos(POS_WINDOW); + + if(pos.val != old_pos.val) + { + mouse_action = 0x80000000; + old_pos = pos; + }; +// printf("pos x%d y%d\n", pos.x, pos.y); + + buttons = get_mouse_buttons(); + wheels = get_mouse_wheels(); + +// if( wheels & 0xFFFF){ +// wheels = (short)wheels>0 ? MSG_WHEELDOWN : MSG_WHEELUP; +// send_mouse_message(win, wheels); +// } + + if((action = (buttons ^ old_buttons))!=0) + { + mouse_action|= action<<3; + mouse_action|= buttons & ~old_buttons; + } + old_buttons = buttons; + + if(mouse_action & 0x80000000) { + DBG("mouse move \n\r"); + send_mouse_message(win, MSG_MOUSEMOVE); + }; + + if(mouse_action & 0x09) + { + if((mouse_action & 0x09)==0x09) + { +// printf("left button down x= %d y= %d\n\r", old_x.x, old_x.y); + click_time = get_tick_count(); + if(click_time < mouse_click_time+35) { + mouse_click_time = click_time; + send_mouse_message(win,MSG_LBTNDBLCLK); + } + else { + mouse_click_time = click_time; + send_mouse_message(win,MSG_LBTNDOWN); + }; + } + else { +// printf("left button up \n\r"); + send_mouse_message(win,MSG_LBTNUP); + } + }; + + if(mouse_action & 0x12) + { + if((mouse_action & 0x12)==0x12) { + DBG("right button down \n\r"); + send_mouse_message(win,MSG_RBTNDOWN); + } + else { + DBG("right button up \n\r"); + send_mouse_message(win,MSG_RBTNUP); + }; + }; + if(mouse_action & 0x24) + { + if((mouse_action & 0x24)==0x24){ + DBG("middle button down \n\r"); + send_mouse_message(win,MSG_MBTNDOWN); + } + else { + DBG("middle button up \n\r"); + send_mouse_message(win,MSG_MBTNUP); + }; + }; +}; + + +int handle_system_events(window_t *win) +{ + oskey_t key; + + for (;;) + { + switch (get_os_event()) + { + case MSG_SYS_PAINT: + handle_sys_paint(win); + break; + + case MSG_SYS_KEY: + key = get_key(); + printf("key %d\n", key.code); + break; + + case MSG_SYS_BUTTON: + // button pressed; we have only one button, close + return 0; + + case MSG_SYS_MOUSE: + handle_sys_mouse(win); + break; + }; + + if( (win->win_state != MINIMIZED) && + (win->win_state != ROLLED) ) + show_context(win->ctx); + } + + return 0; +} + +void *create_control(size_t size, int id, int x, int y, + int w, int h, ctrl_t *parent) +{ + + ctrl_t *ctrl; + + if( !parent ) + return NULL; + + ctrl = (ctrl_t*)malloc(size); + + link_initialize(&ctrl->link); + list_initialize(&ctrl->child); + + ctrl->parent = parent; + + ctrl->ctx = parent->ctx; + ctrl->font = parent->font; + ctrl->id = id; + + ctrl->rc.l = x; + ctrl->rc.t = y ; + + ctrl->rc.r = x + w; + ctrl->rc.b = y + h; + + ctrl->w = w; + ctrl->h = h; + + list_append(&ctrl->link, &parent->child); + + return ctrl; +}; + + +int move_ctrl(ctrl_t *ctrl, int x, int y, int w, int h) +{ + rect_t rc; + rc.l = x; + rc.t = y; + rc.r = w; + rc.b = h; + + send_message(ctrl, MSG_POSCHANGING, 0, &rc); + + ctrl->rc.l = rc.l; + ctrl->rc.t = rc.t; + ctrl->rc.r = rc.l + rc.r; + ctrl->rc.b = rc.t + rc.b; + ctrl->w = rc.r; + ctrl->h = rc.b; + + send_message(ctrl, MSG_POSCHANGE, 0, &rc); + + return 1; +}; + + + +/* + * + * + * + * + * + * + * + * +*/ + +int def_ctrl_proc(ctrl_t *ctrl, uint32_t msg, uint32_t arg1, uint32_t arg2) +{ + switch( msg ) + { + + }; + + return 0; +} + +/* + * + * + * + * + * + * + * + * +*/ + + +static void scroller_on_draw(scroller_t *scrl) +{ + if(scrl->btn_up) + send_message((ctrl_t*)scrl->btn_up, MSG_DRAW, 0, 0); + + if(scrl->btn_down) + send_message((ctrl_t*)scrl->btn_down, MSG_DRAW, 0, 0); + + if(scrl->thumb) + send_message((ctrl_t*)scrl->thumb, MSG_DRAW, 0, 0); + + if(scrl->tl_rect.t != scrl->tl_rect.b) + px_fill_rect(scrl->ctrl.ctx, &scrl->tl_rect, 0xFFE1D8D0); + + if(scrl->br_rect.t != scrl->br_rect.b) + px_fill_rect(scrl->ctrl.ctx, &scrl->br_rect, 0xFFE1D8D0); +} + +static void scroller_on_ownerdraw(scroller_t *scrl, ctrl_t *child) +{ +typedef struct +{ + ctrl_t ctrl; + + uint32_t state; + + char *caption; + int capt_len; +}button_t; + + button_t *btn; + color_t color = 0xFFD7D7D7; + char t = (char)child->id; + rect_t rc; + + switch(child->id) + { + case ID_SCROLLER_UP: + case ID_SCROLLER_DOWN: + btn = (button_t*)child; + if(btn->state & bPressed) + color = 0xFFB0B0B0; + else if(btn->state & bHighlight) + color = 0xFFE7E7E7; + + rc = btn->ctrl.rc; + px_fill_rect(btn->ctrl.ctx, &rc, color); + rc.l+= 3; + rc.t+= 5; + draw_text_ext(btn->ctrl.ctx, sym_font, &t, 1, &rc, 0xFF000000); + break; + + case ID_SCROLLER_THUMB: + btn = (button_t*)child; + color = 0xFFB0B0B0; + if(btn->state & bPressed) + color = 0xFF707070; + else if(btn->state & bHighlight) + color = 0xFF909090; + + rc = btn->ctrl.rc; + px_fill_rect(btn->ctrl.ctx, &rc, color); + } +}; + +static void scroller_update_layout(scroller_t *scrl) +{ + +// th_size = scrl->pix_range*scrl->page_size/ +// (scrl->max_range-scrl->min_range); + +// if(th_size > scrl->pix_range) +// th_size = scrl->pix_range; + + scrl->tl_rect.l = scrl->ctrl.rc.l; + scrl->br_rect.l = scrl->ctrl.rc.l; + + scrl->tl_rect.r = scrl->ctrl.rc.r; + scrl->br_rect.r = scrl->ctrl.rc.r; + + scrl->tl_rect.t = scrl->btn_up->rc.b; + scrl->tl_rect.b = scrl->thumb->rc.t; + + scrl->br_rect.t = scrl->thumb->rc.b; + scrl->br_rect.b = scrl->btn_down->rc.t; + + scrl->pix_range = scrl->ctrl.h - 40 - 20; +}; + +static void scroller_on_poschange(scroller_t *scrl, rect_t *pos) +{ + move_ctrl(scrl->btn_up, pos->l, pos->t, pos->r, pos->r); + move_ctrl(scrl->btn_down, pos->l, pos->t+pos->b-pos->r, pos->r, pos->r); + move_ctrl(scrl->thumb, pos->l, pos->t+pos->r, pos->r, pos->r); + + scroller_update_layout(scrl); + scroller_on_draw(scrl); +}; + +static void scroller_on_command(scroller_t *ctrl, int id, ctrl_t *child, int notify) +{ + scroller_t *scrl = (scroller_t*)ctrl; + int thumb_pos = scrl->thumb_pos; + + switch(id) + { + case ID_SCROLLER_UP: + if(scrl->thumb_pos > scrl->min_range) + scrl->thumb_pos--; + printf("scroll up\n"); + break; + case ID_SCROLLER_DOWN: + if(scrl->thumb_pos < scrl->max_range) + scrl->thumb_pos++; + printf("scroll down\n"); + break; + }; + + if(thumb_pos != scrl->thumb_pos) + { + rect_t rc = scrl->thumb->rc; + int offset = scrl->pix_range*scrl->thumb_pos; + offset /= scrl->max_range - scrl->min_range; + rc.t = scrl->ctrl.rc.t + scrl->btn_up->h + offset; + rc.r = scrl->thumb->w; + rc.b = scrl->thumb->h; + move_ctrl(scrl->thumb, rc.l, rc.t, rc.r, rc.b); + scroller_update_layout(scrl); + scroller_on_draw(scrl); + } +} + +int scroller_proc(ctrl_t *ctrl, uint32_t msg, uint32_t arg1, uint32_t arg2) +{ + scroller_t *scrl = (scroller_t*)ctrl; + + switch( msg ) + { + HANDLE_MSG(scrl, MSG_DRAW, scroller_on_draw); + HANDLE_MSG(scrl, MSG_COMMAND, scroller_on_command); + HANDLE_MSG(scrl, MSG_OWNERDRAW, scroller_on_ownerdraw); + HANDLE_MSG(scrl, MSG_POSCHANGE, scroller_on_poschange); + }; + + return 0; +}; + + +scroller_t *create_scroller(uint32_t style, int id, int x, int y, + int w, int h, ctrl_t *parent) +{ + scroller_t *scrl; + + if( !parent ) + return NULL; + + scrl = create_control(sizeof(scroller_t), id, x, y, w, h, parent); + scrl->ctrl.handler = scroller_proc; + + scrl->min_range = 0; + scrl->max_range = 100; + scrl->thumb_pos = 0; + scrl->page_size = 1; + + scrl->btn_up = create_button(NULL, 1, ID_SCROLLER_UP, x, y, w, w, (ctrl_t*)scrl); + scrl->btn_down = create_button(NULL, 1, ID_SCROLLER_DOWN, x, y+h-w, w, w, (ctrl_t*)scrl); + scrl->thumb = create_button(NULL, 1, ID_SCROLLER_THUMB, x, w, w, w, (ctrl_t*)scrl); + + scroller_update_layout(scrl); + + return scrl; +}; + + diff --git a/contrib/sdk/samples/freetype/txview/winlib/winlib.h b/contrib/sdk/samples/freetype/txview/winlib/winlib.h new file mode 100644 index 0000000000..6c001aade9 --- /dev/null +++ b/contrib/sdk/samples/freetype/txview/winlib/winlib.h @@ -0,0 +1,124 @@ +#ifndef __WINLIB_H__ +#define __WINLIB_H__ + +#include +#include +#include "control.h" + +enum win_state{ + NORMAL, MINIMIZED, ROLLED, MAXIMIZED, FULLSCREEN +}; + + +typedef struct +{ + link_t link; + link_t child; + + handler_t *handler; + ctrl_t *parent; + + ctx_t *ctx; + font_t *font; + + uint32_t id; + uint32_t style; + + rect_t rc; + int w; + int h; + + rect_t saved; + rect_t client; + int clw; + int clh; + + char *caption_txt; + ctrl_t *child_over; + ctrl_t *child_focus; + + enum win_state win_state; + enum win_state saved_state; + +}window_t; + + +#define HANDLE_MSG(ctrl, message, fn) \ + case (message): return HANDLE_##message((ctrl), (arg1), (arg2), (fn)) + +/* void ctrl_on_draw(ctrl_t *ctrl) */ +#define HANDLE_MSG_DRAW(ctrl, arg1, arg2, fn) \ + ((fn)(ctrl),0) + +/* void ctrl_on_ownerdraw(ctrl_t *ctrl, ctrl_t *child) */ +#define HANDLE_MSG_OWNERDRAW(ctrl, arg1, arg2, fn) \ + ((fn)((ctrl),((ctrl_t*)arg1)),0) + +/* void ctrl_on_poschanging(ctrl_t *ctrl, rect_t *pos) */ +#define HANDLE_MSG_POSCHANGING(ctrl, arg1, arg2, fn) \ + ((fn)((ctrl),((rect_t*)arg2)),0) + +/* void ctrl_on_poschange(ctrl_t *ctrl, rect_t *pos) */ +#define HANDLE_MSG_POSCHANGE(ctrl, arg1, arg2, fn) \ + ((fn)((ctrl),((rect_t*)arg2)),0) + +/* void ctrl_on_mouseenter(ctrl_t *ctrl) */ +#define HANDLE_MSG_MOUSEENTER(ctrl, arg1, arg2, fn) \ + ((fn)(ctrl),0) + +/* void ctrl_on_mouseleave(ctrl_t *ctrl) */ +#define HANDLE_MSG_MOUSELEAVE(ctrl, arg1, arg2, fn) \ + ((fn)(ctrl),0) + +/* void ctrl_on_lbuttondown(ctrl_t *ctrl, int x, int y) */ +#define HANDLE_MSG_LBTNDOWN(ctrl, arg1, arg2, fn) \ + ((fn)((ctrl), ((pos_t)arg2).x, ((pos_t)arg2).y), 0L) + +#define HANDLE_MSG_LBTNDBLCLK(ctrl, arg1, arg2, fn) \ + ((fn)((ctrl), ((pos_t)arg2).x, ((pos_t)arg2).y), 0L) + +/* void ctrl_on_lbuttonup(ctrl_t *ctrl, int x, int y) */ +#define HANDLE_MSG_LBTNUP(ctrl, arg1, arg2, fn) \ + ((fn)((ctrl), ((pos_t)arg2).x, ((pos_t)arg2).y), 0L) + +/* void ctrl_on_mousemove(ctrl_t *ctrl, int x, int y) */ +#define HANDLE_MSG_MOUSEMOVE(ctrl, arg1, arg2, fn) \ + ((fn)((ctrl), ((pos_t)arg2).x, ((pos_t)arg2).y), 0L) + +/* void ctrl_on_command(ctrl_t *ctrl, int id, ctrl_t *child, int notify) */ +#define HANDLE_MSG_COMMAND(ctrl,arg1,arg2,fn) \ + ((fn)((ctrl),(int)(arg1 & 0xFFFF),(ctrl_t*)(arg2),(int)(arg1>>16)),0) + +window_t *create_window(char *caption, int style, int x, int y, + int w, int h, handler_t handler); +int handle_system_events(window_t *win); +void show_window(window_t *win); + +extern ctrl_t *mouse_capture; + +static inline ctrl_t *capture_mouse(ctrl_t *newm) +{ + ctrl_t *old = mouse_capture; + + mouse_capture = newm; + + __asm__ __volatile__( + "int $0x40" + ::"a"(40), "b"(0x80000027)); + + return old; +} + +static void release_mouse(void) +{ + mouse_capture = NULL; + __asm__ __volatile__( + "int $0x40" + ::"a"(40), "b"(0xC0000027)); +} + +extern font_t *sym_font; + +int draw_text_ext(ctx_t *ctx, font_t *font, char *text, int len, rect_t *rc, color_t color); + +#endif /* __WINLIB_H__ */