diff --git a/demos/graph/grdevice.c b/demos/graph/grdevice.c index 3d2eb287b..ba367dde0 100644 --- a/demos/graph/grdevice.c +++ b/demos/graph/grdevice.c @@ -1,6 +1,7 @@ #include "grobjs.h" #include "grdevice.h" #include +#include grDeviceChain gr_device_chain[ GR_MAX_DEVICES ]; int gr_num_devices = 0; diff --git a/demos/graph/grfont.c b/demos/graph/grfont.c index 8b9df372c..b96715e49 100644 --- a/demos/graph/grfont.c +++ b/demos/graph/grfont.c @@ -1,4 +1,5 @@ #include "grfont.h" +#include /* font characters */ @@ -329,11 +330,14 @@ { if (string) { + grColor color; + + color.value = 127; grWriteCellString( gr_text_bitmap, gr_margin_right + (gr_cursor_x << 3), gr_margin_top + (gr_cursor_y << 3), string, - (grColor)127L ); + color ); gr_cursor_x += strlen(string); } diff --git a/demos/graph/grinit.c b/demos/graph/grinit.c index 223710689..ebbcf0e27 100644 --- a/demos/graph/grinit.c +++ b/demos/graph/grinit.c @@ -13,6 +13,9 @@ #include "gros2pm.h" #endif +#ifdef DEVICE_WIN32 +#include "grwin32.h" +#endif /********************************************************************** diff --git a/demos/graph/grobjs.c b/demos/graph/grobjs.c index 7ebdb270a..8a34dfd0b 100644 --- a/demos/graph/grobjs.c +++ b/demos/graph/grobjs.c @@ -1,6 +1,6 @@ #include "grobjs.h" #include - +#include int grError = 0; diff --git a/demos/graph/gros2pm.c b/demos/graph/os2/gros2pm.c similarity index 70% rename from demos/graph/gros2pm.c rename to demos/graph/os2/gros2pm.c index e7a63ce72..e23436520 100644 --- a/demos/graph/gros2pm.c +++ b/demos/graph/os2/gros2pm.c @@ -1,5 +1,5 @@ #include "gros2pm.h" - +#include "grdevice.h" #define INCL_DOS #define INCL_WIN @@ -10,13 +10,26 @@ #include #include #include +#include + +#define DEBUGxxx +#ifdef DEBUG +#define LOG(x) LogMessage##x +#else +#define LOG(x) /* rien */ +#endif - static void Panic( const char* message ) +#ifdef DEBUG + static void LogMessage( const char* fmt, ... ) { - fprintf( stderr, "%s", message ); - exit(1); + va_list ap; + + va_start( ap, fmt ); + vfprintf( stderr, fmt, ap ); + va_end( ap ); } +#endif typedef struct Translator { @@ -58,15 +71,10 @@ #define MAX_PIXEL_MODES 32 - static int num_pixel_modes = 0; - static grPixelMode pixel_modes[ MAX_PIXEL_MODES ]; - static int pixel_depth[ MAX_PIXEL_MODES ]; - static HAB gr_anchor; /* device anchor block */ typedef POINTL PMBlitPoints[4]; - typedef struct grPMSurface_ { grSurface root; @@ -107,6 +115,12 @@ } grPMSurface; + /* we use a static variable to pass a pointer to the PM Surface */ + /* to the client window. This is a bit ugly, but it makes things */ + /* a lot more simple.. */ + static grPMSurface* the_surface; + + static int window_created = 0; static @@ -161,6 +175,8 @@ static void done_surface( grPMSurface* surface ) { + LOG(( "Os2PM: done_surface(%08lx)\n", (long)surface )); + if ( surface->frame_window ) WinDestroyWindow( surface->frame_window ); @@ -174,20 +190,6 @@ - static - void add_pixel_mode( grPixelMode pixel_mode, - int depth ) - { - if ( num_pixel_modes >= MAX_PIXEL_MODES ) - Panic( "X11.Too many pixel modes\n" ); - - pixel_modes[ num_pixel_modes ] = pixel_mode; - pixel_depth[ num_pixel_modes ] = depth; - - num_pixel_modes++; - } - - #define LOCK(x) DosRequestMutexSem( x, SEM_INDEFINITE_WAIT ); #define UNLOCK(x) DosReleaseMutexSem( x ) @@ -196,14 +198,14 @@ const int pixel_mode_bit_count[] = { 0, - 1, - 4, - 8, /* pal8 */ - 8, /* gray */ - 15, - 16, - 24, - 32 + 1, /* mono */ + 4, /* pal4 */ + 8, /* pal8 */ + 8, /* grays */ + 15, /* rgb15 */ + 16, /* rgb16 */ + 24, /* rgb24 */ + 32 /* rgb32 */ }; @@ -222,7 +224,7 @@ * surfaces : * * - hold, for each surface, its own bitmap buffer where the - * rest of MiGS writes directly. + * rest of the graph library writes directly. * * - create a PM bitmap object with the same dimensions (and * possibly format). @@ -264,208 +266,31 @@ - - - - - - - - - static - void convert_gray_to_pal8( grPMSurface* surface, - int x, - int y, - int w, - int h ) - { - grBitmap* target = &surface->image; - grBitmap* source = &surface->root.bitmap; - byte* write = (byte*)target->buffer + y*target->pitch + x; - byte* read = (byte*)source->buffer + y*source->pitch + x; - long* palette = surface->shades; - - while (h > 0) - { - byte* _write = write; - byte* _read = read; - byte* limit = _write + w; - - for ( ; _write < limit; _write++, _read++ ) - *_write = (byte) palette[ *_read ]; - - write += target->pitch; - read += source->pitch; - h--; - } - } - - - static - void convert_gray_to_16( grPMSurface* surface, - int x, - int y, - int w, - int h ) - { - grBitmap* target = &surface->image; - grBitmap* source = &surface->root.bitmap; - byte* write = (byte*)target->buffer + y*target->pitch + 2*x; - byte* read = (byte*)source->buffer + y*source->pitch + x; - long* palette = surface->shades; - - while (h > 0) - { - byte* _write = write; - byte* _read = read; - byte* limit = _write + 2*w; - - for ( ; _write < limit; _write += 2, _read++ ) - *(short*)_write = (short)palette[ *_read ]; - - write += target->pitch; - read += source->pitch; - h--; - } - } - - - static - void convert_gray_to_24( grPMSurface* surface, - int x, - int y, - int w, - int h ) - { - grBitmap* target = &surface->image; - grBitmap* source = &surface->root.bitmap; - byte* write = (byte*)target->buffer + y*target->pitch + 3*x; - byte* read = (byte*)source->buffer + y*source->pitch + x; - - while (h > 0) - { - byte* _write = write; - byte* _read = read; - byte* limit = _write + 3*w; - - for ( ; _write < limit; _write += 3, _read++ ) - { - byte color = *_read; - - _write[0] = - _write[1] = - _write[2] = color; - } - - write += target->pitch; - read += source->pitch; - h--; - } - } - - - static - void convert_gray_to_32( grPMSurface* surface, - int x, - int y, - int w, - int h ) - { - grBitmap* target = &surface->image; - grBitmap* source = &surface->root.bitmap; - byte* write = (byte*)target->buffer + y*target->pitch + 4*x; - byte* read = (byte*)source->buffer + y*source->pitch + x; - - while (h > 0) - { - byte* _write = write; - byte* _read = read; - byte* limit = _write + 4*w; - - for ( ; _write < limit; _write += 4, _read++ ) - { - byte color = *_read; - - _write[0] = - _write[1] = - _write[2] = - _write[3] = color; - } - - write += target->pitch; - read += source->pitch; - h--; - } - } - - static - void convert_rectangle( grPMSurface* surface, + void refresh_rectangle( grPMSurface* surface, int x, int y, int w, int h ) { - int z; - - /* first of all, clip to the surface's area */ - if ( x >= surface->image.width || - x+w <= 0 || - y >= surface->image.rows || - y+h <= 0 ) - return; - - if ( x < 0 ) - { - w += x; - x = 0; - } - - z = (x + w) - surface->image.width; - if (z > 0) - w -= z; - - z = (y + h) - surface->image.rows; - if (z > 0) - h -= z; - - /* convert the rectangle to the target depth for gray surfaces */ - if (surface->root.bitmap.mode == gr_pixel_mode_gray) - { - switch (surface->image.mode) - { - case gr_pixel_mode_pal8 : - convert_gray_to_pal8( surface, x, y, w, h ); - break; - - case gr_pixel_mode_rgb555: - case gr_pixel_mode_rgb565: - convert_gray_to_16 ( surface, x, y, w, h ); - break; - - case gr_pixel_mode_rgb24: - convert_gray_to_24 ( surface, x, y, w, h ); - break; - - case gr_pixel_mode_rgb32: - convert_gray_to_32 ( surface, x, y, w, h ); - break; - - default: - ; - } - } - } + LOG(( "Os2PM: refresh_rectangle( %08lx, %d, %d, %d, %d )\n", + (long)surface, x, y, w, h )); + (void)x; + (void)y; + (void)w; + (void)h; - static - void refresh_rectangle( grPMSurface* surface, - int x, - int y, - int w, - int h ) - { + /* convert_rectangle( surface, x, y, w, h ); + */ + DosRequestMutexSem( surface->image_lock, SEM_INDEFINITE_WAIT ); + GpiSetBitmapBits( surface->image_ps, + 0, + surface->root.bitmap.rows, + surface->root.bitmap.buffer, + surface->bitmap_header ); + DosReleaseMutexSem( surface->image_lock ); WinInvalidateRect( surface->client_window, NULL, FALSE ); WinUpdateWindow( surface->frame_window ); @@ -476,7 +301,20 @@ void set_title( grPMSurface* surface, const char* title ) { - WinSetWindowText( surface->title_window, (PSZ)title ); + ULONG rc; + +#if 1 + LOG(( "Os2PM: set_title( %08lx == %08lx, %s )\n", + (long)surface, surface->client_window, title )); +#endif + LOG(( " -- frame = %08lx\n", + (long)surface->frame_window )); + + LOG(( " -- client parent = %08lx\n", + (long)WinQueryWindow( surface->client_window, QW_PARENT ) )); + + rc = WinSetWindowText( surface->client_window, (PSZ)title ); + LOG(( " -- returned rc = %ld\n",rc )); } @@ -501,22 +339,38 @@ static - int init_surface( grPMSurface* surface, - grBitmap* bitmap ) + grPMSurface* init_surface( grPMSurface* surface, + grBitmap* bitmap ) { PBITMAPINFO2 bit; SIZEL sizl = { 0, 0 }; LONG palette[256]; + LOG(( "Os2PM: init_surface( %08lx, %08lx )\n", + (long)surface, (long)bitmap )); + + LOG(( " -- input bitmap =\n" )); + LOG(( " -- mode = %d\n", bitmap->mode )); + LOG(( " -- grays = %d\n", bitmap->grays )); + LOG(( " -- width = %d\n", bitmap->width )); + LOG(( " -- height = %d\n", bitmap->rows )); + /* create the bitmap - under OS/2, we support all modes as PM */ /* handles all conversions automatically.. */ - if ( grNewBitmap( surface->root.bitmap.mode, - surface->root.bitmap.grays, - surface->root.bitmap.width, - surface->root.bitmap.rows, + if ( grNewBitmap( bitmap->mode, + bitmap->grays, + bitmap->width, + bitmap->rows, bitmap ) ) - return grError; + return 0; + LOG(( " -- output bitmap =\n" )); + LOG(( " -- mode = %d\n", bitmap->mode )); + LOG(( " -- grays = %d\n", bitmap->grays )); + LOG(( " -- width = %d\n", bitmap->width )); + LOG(( " -- height = %d\n", bitmap->rows )); + + bitmap->pitch = -bitmap->pitch; surface->root.bitmap = *bitmap; /* create the image and event lock */ @@ -544,15 +398,41 @@ bit->cy = surface->root.bitmap.rows; bit->cPlanes = 1; - bit->argbColor[0].bBlue = 0; + bit->argbColor[0].bBlue = 255; bit->argbColor[0].bGreen = 0; bit->argbColor[0].bRed = 0; - bit->argbColor[1].bBlue = 255; + bit->argbColor[1].bBlue = 0; bit->argbColor[1].bGreen = 255; - bit->argbColor[1].bRed = 255; + bit->argbColor[1].bRed = 0; + + bit->cBitCount = (bitmap->mode == gr_pixel_mode_gray ? 8 : 1 ); - bit->cBitCount = pixel_mode_bit_count[ surface->root.bitmap.mode ]; + if (bitmap->mode == gr_pixel_mode_gray) + { + RGB2* color = bit->argbColor; + int x, count; + + count = bitmap->grays; + for ( x = 0; x < count; x++, color++ ) + { + color->bBlue = + color->bGreen = + color->bRed = (((count-x)*255)/count); + } + } + else + { + RGB2* color = bit->argbColor; + + color[0].bBlue = + color[0].bGreen = + color[0].bRed = 0; + + color[1].bBlue = + color[1].bGreen = + color[1].bRed = 255; + } surface->os2_bitmap = GpiCreateBitmap( surface->image_ps, (PBITMAPINFOHEADER2)bit, @@ -563,6 +443,7 @@ bit->cbFix = sizeof( BITMAPINFOHEADER2 ); GpiQueryBitmapInfoHeader( surface->os2_bitmap, (PBITMAPINFOHEADER2)bit ); + surface->bitmap_header = bit; /* for gr_pixel_mode_gray, create a gray-levels logical palette */ if ( bitmap->mode == gr_pixel_mode_gray ) @@ -592,6 +473,8 @@ surface->blit_points[1].y = surface->root.bitmap.rows; surface->blit_points[3] = surface->blit_points[1]; + window_created = 0; + /* Finally, create the event handling thread for the surface's window */ DosCreateThread( &surface->message_thread, (PFNTHREAD) RunPMWindow, @@ -599,13 +482,16 @@ 0UL, 32920 ); + /* wait for the window creation */ + for ( ; window_created == 0; ) + surface->root.done = (grDoneSurfaceFunc) done_surface; surface->root.refresh_rect = (grRefreshRectFunc) refresh_rectangle; surface->root.set_title = (grSetTitleFunc) set_title; surface->root.listen_event = (grListenEventFunc) listen_event; - - convert_rectangle( surface, 0, 0, bitmap->width, bitmap->rows ); - return 0; + + /* convert_rectangle( surface, 0, 0, bitmap->width, bitmap->rows ); */ + return surface; } @@ -625,6 +511,13 @@ static HMQ queue; QMSG message; + /* store the current surface pointer in "the_surface". It is a static */ + /* variable that is only used to retrieve the pointer in the client */ + /* window procedure the first time is is called.. */ + the_surface = surface; + + LOG(( "Os2PM: RunPMWindow( %08lx )\n", (long)surface )); + /* create an anchor to allow this thread to use PM */ surface->anchor = WinInitialize(0); if (!surface->anchor) @@ -656,12 +549,13 @@ class_flags = FCF_TITLEBAR | FCF_MINBUTTON | FCF_DLGBORDER | FCF_TASKLIST | FCF_SYSMENU; + LOG(( "Os2PM: RunPMWindow: Creating window\n" )); surface->frame_window = WinCreateStdWindow( HWND_DESKTOP, WS_VISIBLE, &class_flags, (PSZ) class_name, - (PSZ) "FreeType PM Graphics", + (PSZ) "FreeType Viewer - press F1 for help", WS_VISIBLE, 0, 0, &surface->client_window ); @@ -674,13 +568,17 @@ /* find the title window handle */ surface->title_window = WinWindowFromID( surface->frame_window, FID_TITLEBAR ); + LOG (( "Os2PM: RunPMWIndow: Creation succeeded\n" )); + LOG (( " -- frame = %08lx\n", surface->frame_window )); + LOG (( " -- client = %08lx\n", surface->client_window )); /* set Window size and position */ WinSetWindowPos( surface->frame_window, 0L, (SHORT) 60, + (SHORT) WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN ) - - surface->root.bitmap.rows + 100, + (surface->root.bitmap.rows + 100), (SHORT) WinQuerySysValue( HWND_DESKTOP, SV_CYDLGFRAME )*2 + surface->root.bitmap.width, @@ -691,12 +589,18 @@ SWP_SIZE | SWP_MOVE ); +#if 0 /* save the handle to the current surface within the window words */ - WinSetWindowPtr( surface->frame_window,QWL_USER, surface ); + WinSetWindowPtr( surface->client_window,QWL_USER, surface ); +#endif + + window_created = 1; /* run the message queue till the end */ while ( WinGetMsg( surface->anchor, &message, (HWND)NULL, 0, 0 ) ) + { WinDispatchMsg( surface->anchor, &message ); + } /* clean-up */ WinDestroyWindow( surface->frame_window ); @@ -728,8 +632,14 @@ grPMSurface* surface; - /* get the handle to the window's surface */ + /* get the handle to the window's surface -- note that this */ + /* value will be null when the window is created */ surface = (grPMSurface*)WinQueryWindowPtr( handle, QWL_USER ); + if (!surface) + { + surface = the_surface; + WinSetWindowPtr( handle, QWL_USER, surface ); + } switch( mess ) { @@ -751,9 +661,9 @@ &sizl, PU_PELS | GPIT_MICRO | GPIA_ASSOC | GPIF_DEFAULT ); - /* take the input focus */ WinFocusChange( HWND_DESKTOP, handle, 0L ); + LOG(( "screen_dc and screen_ps have been created\n" )); break; case WM_MINMAXFRAME: @@ -783,6 +693,10 @@ DosReleaseMutexSem( surface->image_lock ); break; + case WM_HELP: /* this really is a F1 Keypress !! */ + surface->event.key = grKeyF1; + goto Do_Key_Event; + case WM_CHAR: if ( CHARMSG( &mess )->fs & KC_KEYUP ) break; @@ -822,61 +736,6 @@ - - - -#if 0 - static - grKey KeySymTogrKey( key ) - { - grKey k; - int count = sizeof(key_translators)/sizeof(key_translators[0]); - Translator* trans = key_translators; - Translator* limit = trans + count; - - k = grKeyNone; - - while ( trans < limit ) - { - if ( trans->xkey == key ) - { - k = trans->grkey; - break; - } - trans++; - } - - return k; - } - - - - static - void listen_event( grPMSurface* surface, - int event_mask, - grEvent* grevent ) - { - grKey grkey; - - /* XXXX : For now, ignore the event mask, and only exit when */ - /* a key is pressed.. */ - (void)event_mask; - - - /* Now, translate the keypress to a grKey */ - /* If this wasn't part of the simple translated keys, simply get the charcode */ - /* from the character buffer */ - grkey = grKEY(key_buffer[key_cursor++]); - - Set_Key: - grevent->type = gr_key_down; - grevent->key = grkey; - } - -#endif - - - grDevice gr_os2pm_device = { sizeof( grPMSurface ), diff --git a/demos/graph/gpm_os2.def b/demos/graph/os2/gros2pm.def similarity index 100% rename from demos/graph/gpm_os2.def rename to demos/graph/os2/gros2pm.def diff --git a/demos/graph/gros2pm.h b/demos/graph/os2/gros2pm.h similarity index 100% rename from demos/graph/gros2pm.h rename to demos/graph/os2/gros2pm.h diff --git a/demos/graph/os2/rules.mk b/demos/graph/os2/rules.mk new file mode 100644 index 000000000..ffbf0158a --- /dev/null +++ b/demos/graph/os2/rules.mk @@ -0,0 +1,32 @@ +#************************************************************************** +#* +#* OS/2 specific rules file, used to compile the OS/2 graphics driver +#* to the graphics subsystem +#* +#************************************************************************** + +ifeq ($(PLATFORM),os2) + +GR_OS2 := $(GRAPH_)os2 +GR_OS2_ := $(GR_OS2)$(SEP) + +# the GRAPH_LINK is expanded each time an executable is linked with the +# graphics library. +# +GRAPH_LINK += $(GR_OS2_)gros2pm.def + +# Add the OS/2 driver object file to the graphics library "graph.a" +# +GRAPH_OBJS += $(OBJ_)gros2pm.$O + +DEVICES += OS2_PM +DEVICE_INCLUDES += $(GR_OS2) + +# the rule used to compile the graphics driver +# +$(OBJ_)gros2pm.$O: $(GR_OS2_)gros2pm.c $(GR_OS2_)gros2pm.h + $(CC) $(CFLAGS) $(GRAPH_INCLUDES:%=$I%) $I$(GR_OS2) $T$@ $< + +endif + + diff --git a/demos/graph/rules.mk b/demos/graph/rules.mk index 0a190ed3b..f03462566 100644 --- a/demos/graph/rules.mk +++ b/demos/graph/rules.mk @@ -45,11 +45,11 @@ # # -GRAPH_INCLUDES := graph -GRAPH_LIB := $(OBJ_)graph.a +GRAPH_INCLUDES := $(TOP2_)graph +GRAPH_LIB := $(OBJ_)graph.$A GRAPH_LINK := $(GRAPH_LIB) -GRAPH_ := graph$(SEP) +GRAPH_ := $(TOP2_)graph$(SEP) GRAPH_H := $(GRAPH_)graph.h \ $(GRAPH_)grtypes.h \ @@ -65,10 +65,15 @@ GRAPH_OBJS := $(OBJ_)grblit.$O \ $(OBJ_)grinit.$O +# Default value for COMPILE_GRAPH_LIB +# this value can be modified by the system-specific graphics drivers.. +# +COMPILE_GRAPH_LIB = ar -r $@ $(GRAPH_OBJS) + # Add the rules used to detect and compile graphics driver depending # on the current platform.. # -include $(wildcard config/*/rules.mk) +include $(wildcard $(GRAPH_)/*/rules.mk) ######################################################################### # @@ -80,7 +85,7 @@ include $(wildcard config/*/rules.mk) # # $(GRAPH_LIB): $(GRAPH_OBJS) - ar -r $@ $(GRAPH_OBJS) + $(COMPILE_GRAPH_LIB) # pattern rule for normal sources diff --git a/demos/graph/win32/grwin32.c b/demos/graph/win32/grwin32.c new file mode 100644 index 000000000..9fbf0ad62 --- /dev/null +++ b/demos/graph/win32/grwin32.c @@ -0,0 +1,504 @@ +/******************************************************************* + * + * grwin32.c graphics driver for Win32 platform. 0.1 + * + * This is the driver for displaying inside a window under Win32, + * used by the graphics utility of the FreeType test suite. + * + * Written by Antoine Leca. + * Copyright 1999-2000 by Antoine Leca, David Turner + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * Borrowing liberally from the other FreeType drivers. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + ******************************************************************/ + +#include +#include +#include + +#define WIN32_LEAN_AND_MEAN +#include + +#include "grwin32.h" +#include "grdevice.h" + + +/* logging facility */ +#include + +#define DEBUGxxx + +#ifdef DEBUG +#define LOG(x) LogMessage##x +#else +#define LOG(x) /* rien */ +#endif + +#ifdef DEBUG + static void LogMessage( const char* fmt, ... ) + { + va_list ap; + + va_start( ap, fmt ); + vfprintf( stderr, fmt, ap ); + va_end( ap ); + } +#endif +/*-------------------*/ + +/* Size of the window. */ +#define WIN_WIDTH 640u +#define WIN_HEIGHT 450u + +/* These values can be changed, but WIN_WIDTH should remain for now a */ +/* multiple of 32 to avoid padding issues. */ + + typedef struct _Translator + { + ULONG winkey; + grKey grkey; + + } Translator; + + static + Translator key_translators[] = + { + { VK_BACK, grKeyBackSpace }, + { VK_TAB, grKeyTab }, + { VK_RETURN, grKeyReturn }, + { VK_ESCAPE, grKeyEsc }, + { VK_HOME, grKeyHome }, + { VK_LEFT, grKeyLeft }, + { VK_UP, grKeyUp }, + { VK_RIGHT, grKeyRight }, + { VK_DOWN, grKeyDown }, + /* + { VK_PAGEUP, grKeyPageUp }, + { VK_PAGEDOWN, grKeyPageDown }, + */ + { VK_END, grKeyEnd }, + { VK_F1, grKeyF1 }, + { VK_F2, grKeyF2 }, + { VK_F3, grKeyF3 }, + { VK_F4, grKeyF4 }, + { VK_F5, grKeyF5 }, + { VK_F6, grKeyF6 }, + { VK_F7, grKeyF7 }, + { VK_F8, grKeyF8 }, + { VK_F9, grKeyF9 }, + { VK_F10, grKeyF10 }, + { VK_F11, grKeyF11 }, + { VK_F12, grKeyF12 } + }; + + /* This is a minimalist driver, it is only able to display */ + /* a _single_ window. Moreover, only monochrome and gray */ + /* bitmaps are supported.. */ + + /* handle of the window. */ + static HWND hwndGraphic; + + static int window_width, window_height; + + /* the following variables are used to set the window title lazily */ + static int title_set = 1; + static const char* the_title; + + /* bitmap information */ + static LPBITMAPINFO pbmi; + static HBITMAP hbm; + + /* local event to pass on */ + static grEvent ourevent; + static int eventToProcess = 0; + +/* destroys the surface*/ +static +void done_surface( grSurface* surface ) +{ + /* The graphical window has perhaps already destroyed itself */ + if ( hwndGraphic ) + { + DestroyWindow ( hwndGraphic ); + PostMessage( hwndGraphic, WM_QUIT, 0, 0 ); + } + grDoneBitmap( &surface->bitmap ); + if ( pbmi ) free ( pbmi ); +} + + static + const int pixel_mode_bit_count[] = + { + 0, + 1, /* mono */ + 4, /* pal4 */ + 8, /* pal8 */ + 8, /* grays */ + 15, /* rgb15 */ + 16, /* rgb16 */ + 24, /* rgb24 */ + 32 /* rgb32 */ + }; + + static + void refresh_rectangle( grSurface* surface, + int x, + int y, + int w, + int h ) + { + HDC hDC; + int row_bytes; + + LOG(( "Win32: refresh_rectangle( %08lx, %d, %d, %d, %d )\n", + (long)surface, x, y, w, h )); + (void)x; + (void)y; + (void)w; + (void)h; + + row_bytes = surface->bitmap.pitch; + if (row_bytes < 0) row_bytes = -row_bytes; + + if ( row_bytes*8 != pbmi->bmiHeader.biWidth * pbmi->bmiHeader.biBitCount ) + pbmi->bmiHeader.biWidth = row_bytes * 8 / pbmi->bmiHeader.biBitCount; + + hDC = GetDC ( hwndGraphic ); + SetDIBits ( hDC, hbm, + 0, + surface->bitmap.rows, + surface->bitmap.buffer, + pbmi, + DIB_RGB_COLORS ); + + ReleaseDC ( hwndGraphic, hDC ); + + ShowWindow( hwndGraphic, SW_SHOW ); + InvalidateRect ( hwndGraphic, NULL, FALSE ); + UpdateWindow ( hwndGraphic ); + } + + static + void set_title( grSurface* surface, const char* title ) + { + (void)surface; + + /* the title will be set on the next listen_event, just */ + /* record it there.. */ + the_title = title; + title_set = 0; + } + + static + void listen_event( grSurface* surface, + int event_mask, + grEvent* grevent ) + { + MSG msg; + + (void)surface; + (void)event_mask; + + if ( hwndGraphic && !title_set ) + { + SetWindowText( hwndGraphic, the_title ); + title_set = 1; + } + + do + { + while ( PeekMessage( &msg, 0, 0, 0, PM_REMOVE ) ) + { + TranslateMessage( &msg ); + DispatchMessage( &msg ); + } + if (!eventToProcess) + WaitMessage(); + } + while (!eventToProcess); + + *grevent = ourevent; + } + +/* + * set graphics mode + * and create the window class and the message handling. + */ + +/* Declarations of the Windows-specific functions that are below. */ +static BOOL RegisterTheClass ( void ); +static BOOL CreateTheWindow ( int width, int height ); + +static +grSurface* init_surface( grSurface* surface, + grBitmap* bitmap ) +{ + static RGBQUAD black = { 0, 0, 0, 0 }; + static RGBQUAD white = { 0xFF, 0xFF, 0xFF, 0 }; + + if( ! RegisterTheClass() ) return 0; /* if already running, fails. */ + + /* find some memory for the bitmap header */ + if ( (pbmi = malloc ( sizeof ( BITMAPINFO ) + sizeof ( RGBQUAD ) * 256 ) ) + /* 256 should really be 2 if not grayscale */ + == NULL ) + /* lack of memory; fails the process */ + return 0; + + LOG(( "Win32: init_surface( %08lx, %08lx )\n", + (long)surface, (long)bitmap )); + + LOG(( " -- input bitmap =\n" )); + LOG(( " -- mode = %d\n", bitmap->mode )); + LOG(( " -- grays = %d\n", bitmap->grays )); + LOG(( " -- width = %d\n", bitmap->width )); + LOG(( " -- height = %d\n", bitmap->rows )); + + /* create the bitmap - under Win32, we support all modes as the GDI */ + /* handles all conversions automatically.. */ + if ( grNewBitmap( bitmap->mode, + bitmap->grays, + bitmap->width, + bitmap->rows, + bitmap ) ) + return 0; + + LOG(( " -- output bitmap =\n" )); + LOG(( " -- mode = %d\n", bitmap->mode )); + LOG(( " -- grays = %d\n", bitmap->grays )); + LOG(( " -- width = %d\n", bitmap->width )); + LOG(( " -- height = %d\n", bitmap->rows )); + + bitmap->pitch = -bitmap->pitch; + surface->bitmap = *bitmap; + + /* initialize the header to appropriate values */ + memset( pbmi, 0, sizeof ( BITMAPINFO ) + sizeof ( RGBQUAD ) * 256 ); + + switch ( bitmap->mode ) + { + case gr_pixel_mode_mono: + pbmi->bmiHeader.biBitCount = 1; + pbmi->bmiColors[0] = white; + pbmi->bmiColors[1] = black; + break; + + case gr_pixel_mode_gray: + pbmi->bmiHeader.biBitCount = 8; + pbmi->bmiHeader.biClrUsed = bitmap->grays; + { + int count = bitmap->grays; + int x; + RGBQUAD* color = pbmi->bmiColors; + + for ( x = 0; x < count; x++, color++ ) + { + color->rgbRed = + color->rgbGreen = + color->rgbBlue = (((count-x)*255)/count); + color->rgbReserved = 0; + } + } + break; + + default: + free ( pbmi ); + return 0; /* Unknown mode */ + } + + pbmi->bmiHeader.biSize = sizeof ( BITMAPINFOHEADER ); + pbmi->bmiHeader.biWidth = bitmap->width; + pbmi->bmiHeader.biHeight = bitmap->rows; + pbmi->bmiHeader.biPlanes = 1; + + if( ! CreateTheWindow( bitmap->width, bitmap->rows ) ) + { + free ( pbmi ); + return 0; + } + + surface->done = (grDoneSurfaceFunc) done_surface; + surface->refresh_rect = (grRefreshRectFunc) refresh_rectangle; + surface->set_title = (grSetTitleFunc) set_title; + surface->listen_event = (grListenEventFunc) listen_event; + + return surface; +} + + +/* ---- Windows-specific stuff ------------------------------------------- */ + +LRESULT CALLBACK Message_Process( HWND, UINT, WPARAM, LPARAM ); + +static +BOOL RegisterTheClass ( void ) + { + WNDCLASS ourClass = { + /* UINT style */ 0, + /* WNDPROC lpfnWndProc */ Message_Process, + /* int cbClsExtra */ 0, + /* int cbWndExtra */ 0, + /* HANDLE hInstance */ 0, + /* HICON hIcon */ 0, + /* HCURSOR hCursor */ 0, + /* HBRUSH hbrBackground*/ 0, + /* LPCTSTR lpszMenuName */ NULL, + /* LPCTSTR lpszClassName*/ "FreeTypeTestGraphicDriver" + }; + + ourClass.hInstance = GetModuleHandle( NULL ); + ourClass.hIcon = LoadIcon(0, IDI_APPLICATION); + ourClass.hCursor = LoadCursor(0, IDC_ARROW); + ourClass.hbrBackground= GetStockObject(BLACK_BRUSH); + + return RegisterClass(&ourClass) != 0; /* return False if it fails. */ + } + +static +BOOL CreateTheWindow ( int width, int height ) + { + window_width = width; + window_height = height; + + if ( ! (hwndGraphic = CreateWindow( + /* LPCSTR lpszClassName; */ "FreeTypeTestGraphicDriver", + /* LPCSTR lpszWindowName; */ "FreeType Test Graphic Driver", + /* DWORD dwStyle; */ WS_OVERLAPPED | WS_SYSMENU, + /* int x; */ CW_USEDEFAULT, + /* int y; */ CW_USEDEFAULT, + /* int nWidth; */ width + 2*GetSystemMetrics(SM_CXBORDER), + /* int nHeight; */ height+ GetSystemMetrics(SM_CYBORDER) + + GetSystemMetrics(SM_CYCAPTION), + /* HWND hwndParent; */ HWND_DESKTOP, + /* HMENU hmenu; */ 0, + /* HINSTANCE hinst; */ GetModuleHandle( NULL ), + /* void FAR* lpvParam; */ NULL)) + ) + /* creation failed... */ + return 0; + + return 1; + } + + /* Message processing for our Windows class */ +LRESULT CALLBACK Message_Process( HWND handle, UINT mess, + WPARAM wParam, LPARAM lParam ) + { + + switch( mess ) + { + case WM_DESTROY: + /* warn the main thread to quit if it didn't know */ + ourevent.type = gr_event_key; + ourevent.key = grKeyEsc; + eventToProcess = 1; + hwndGraphic = 0; + PostQuitMessage ( 0 ); + DeleteObject ( hbm ); + break; + + case WM_CREATE: + { + HDC hDC; + + hDC = GetDC ( handle ); + hbm = CreateDIBitmap ( + /* HDC hdc; handle of device context */ hDC, + /* BITMAPINFOHEADER FAR* lpbmih; addr.of header*/ &pbmi->bmiHeader, + /* DWORD dwInit; CBM_INIT to initialize bitmap */ 0, + /* const void FAR* lpvBits; address of values */ NULL, + /* BITMAPINFO FAR* lpbmi; addr.of bitmap data */ pbmi, + /* UINT fnColorUse; RGB or palette indices */ DIB_RGB_COLORS); + ReleaseDC ( handle, hDC ); + break; + } + + case WM_PAINT: + { + HDC hDC, memDC; + HANDLE oldbm; + PAINTSTRUCT ps; + + hDC = BeginPaint ( handle, &ps ); + memDC = CreateCompatibleDC(hDC); + oldbm = SelectObject(memDC, hbm); + BitBlt ( hDC, 0, 0, window_width, window_height, memDC, 0, 0, SRCCOPY); + ReleaseDC ( handle, hDC ); + SelectObject ( memDC, oldbm ); + DeleteObject ( memDC ); + EndPaint ( handle, &ps ); + } + + case WM_KEYDOWN: + switch ( wParam ) + { + case VK_ESCAPE: + ourevent.type = gr_event_key; + ourevent.key = grKeyEsc; + eventToProcess = 1; + break; + + default: + /* lookup list of translated keys */ + { + int count = sizeof( key_translators )/sizeof( key_translators[0] ); + Translator* trans = key_translators; + Translator* limit = trans + count; + for ( ; trans < limit; trans++ ) + if ( wParam == trans->winkey ) + { + ourevent.key = trans->grkey; + goto Do_Key_Event; + } + } + } + + case WM_CHAR: + { + ourevent.key = wParam; + + Do_Key_Event: + ourevent.type = gr_event_key; + eventToProcess = 1; + } + break; + + default: + return DefWindowProc( handle, mess, wParam, lParam ); + } + + return 0; + } + + static int init_device( void ) + { + return 0; + } + + static void done_device( void ) + { + } + + grDevice gr_win32_device = + { + sizeof( grSurface ), + "win32", + + init_device, + done_device, + + (grDeviceInitSurfaceFunc) init_surface, + + 0, + 0 + }; + + +/* End */ diff --git a/demos/graph/win32/grwin32.h b/demos/graph/win32/grwin32.h new file mode 100644 index 000000000..028d1a993 --- /dev/null +++ b/demos/graph/win32/grwin32.h @@ -0,0 +1,23 @@ +#ifndef GRWIN32_H +#define GRWIN32_H + +#include "grobjs.h" + + extern + grDevice gr_win32_device; + +#ifdef GR_INIT_BUILD + static + grDeviceChain gr_win32_device_chain = + { + "win32", + &gr_win32_device, + GR_INIT_DEVICE_CHAIN + }; + +#undef GR_INIT_DEVICE_CHAIN +#define GR_INIT_DEVICE_CHAIN &gr_win32_device_chain + +#endif /* GR_INIT_BUILD */ + +#endif /* GRWIN32_H */ diff --git a/demos/graph/win32/rules.mk b/demos/graph/win32/rules.mk new file mode 100644 index 000000000..20c202443 --- /dev/null +++ b/demos/graph/win32/rules.mk @@ -0,0 +1,49 @@ +#************************************************************************** +#* +#* Win32 specific rules file, used to compile the Win32 graphics driver +#* to the graphics subsystem +#* +#************************************************************************** + +ifeq ($(PLATFORM),win32) + +GR_WIN32 := $(GRAPH_)win32 +GR_WIN32_ := $(GR_WIN32)$(SEP) + +# Add the Win32 driver object file to the graphics library "graph.a" +# +GRAPH_OBJS += $(OBJ_)grwin32.$O + +DEVICES += WIN32 +DEVICE_INCLUDES += $(GR_WIN32) + +# the rule used to compile the graphics driver +# +$(OBJ_)grwin32.$O: $(GR_WIN32_)grwin32.c $(GR_WIN32_)grwin32.h + $(CC) $(CFLAGS) $(GRAPH_INCLUDES:%=$I%) $I$(GR_WIN32) $T$@ $< + +# Now update COMPILE_GRAPH_LIB according to the compiler used on Win32 +# +ifeq ($(CC),gcc) # test for GCC +LINK = $(CC) $T$@ $< $(FTLIB) +COMMON_LINK = $(LINK) $(COMMON_OBJ) +GRAPH_LINK = $(COMMON_LINK) $(GRAPH_LIB) -luser32 -lgdi32 +endif + +ifeq ($(CC),cl) # test for Visual C++ +COMPILE_GRAPH_LIB = lib /nologo /out:$(GRAPH_LIB) $(GRAPH_OBJS) +LINK = cl /nologo /MD -o $@ $< $(FTLIB) +COMMON_LINK = $(LINK) $(COMMON_OBJ) +GRAPH_LINK = $(COMMON_LINK) $(GRAPH_LIB) user32.lib gdi32.lib +endif + +ifeq ($(CC),lcc) # test for LCC-Win32 +COMPILE_GRAPH_LIB = lcclib /out:$(subst /,\\,$(GRAPH_LIB)) $(subst /,\\,$(GRAPH_OBJS)) +GRAPH_LINK = $(subst /,\\,$(GRAPH_LIB)) user32.lib gdi32.lib +LINK_ROOT = lcclnk -o $(subst /,\\,$@) $(subst /,\\,$<) +LINK = $(LINK_ROOT) $(subst /,\\,$(FTLIB)) +COMMON_LINK = $(LINK_ROOT) $(subst /,\\,$(COMMON_OBJ)) $(subst /,\\,$(FTLIB)) +GRAPH_LINK = $(LINK_ROOT) $(subst /,\\,$(COMMON_OBJ)) $(subst /,\\,$(GRAPH_LIB)) $(subst /,\\,$(FTLIB)) +endif +endif + diff --git a/demos/graph/grx11.c b/demos/graph/x11/grx11.c similarity index 100% rename from demos/graph/grx11.c rename to demos/graph/x11/grx11.c diff --git a/demos/graph/grx11.h b/demos/graph/x11/grx11.h similarity index 100% rename from demos/graph/grx11.h rename to demos/graph/x11/grx11.h diff --git a/demos/graph/x11/rules.mk b/demos/graph/x11/rules.mk new file mode 100644 index 000000000..a6e185f84 --- /dev/null +++ b/demos/graph/x11/rules.mk @@ -0,0 +1,81 @@ +#************************************************************************** +#* +#* X11-specific rules files, used to compile the X11 graphics driver +#* when supported by the current platform +#* +#************************************************************************** + +######################################################################### +# +# Try to detect an X11 setup. +# +# We simply try to detect a `X11R6/bin', `X11R5/bin' or `X11/bin' in +# the current path. +# +ifneq ($(findstring X11R6$(SEP)bin,$(PATH)),) +xversion := X11R6 +else + +ifneq ($(findstring X11R5$(SEP)bin,$(PATH)),) +xversion := X11R5 +else + +ifneq ($(findstring X11$(SEP)bin,$(PATH)),) +xversion := X11 +endif +endif +endif + +ifdef xversion +X11_PATH := $(subst ;, ,$(PATH)) $(subst :, ,$(PATH)) +X11_PATH := $(filter %$(xversion)$(SEP)bin,$(X11_PATH)) +X11_PATH := $(X11_PATH:%$(SEP)bin=%) +endif + +########################################################################## +# +# Update some variables to compile the X11 graphics module. Note that +# X11 is available on Unix, or on OS/2. However, it only compiles with +# gcc on the latter platform, which is why it is safe to use the flags +# `-L' and `-l' +# +ifneq ($(X11_PATH),) + +X11_INCLUDE := $(X11_PATH:%=%$(SEP)include) +X11_LIB := $(X11_PATH:%=%$(SEP)lib) + +# the GRAPH_LINK variable is expanded each time an executable is linked against +# the graphics library.. +# +GRAPH_LINK += $(X11_LIB:%=-L%) -lX11 + +# Solaris needs a -lsocket in GRAPH_LINK .. +# +UNAME := $(shell uname) +ifneq ($(findstring $(UNAME),SunOS Solaris),) +GRAPH_LINK += -lsocket +endif + + +# add the X11 driver object file to the graphics library +# +GRAPH_OBJS += $(OBJ_)grx11.$O + + + +GR_X11 := $(GRAPH_)x11 +GR_X11_ := $(GR_X11)$(SEP) + +DEVICES += X11 +DEVICE_INCLUDES += $(GR_X11) + +# the rule used to compile the X11 driver +# +$(OBJ_)grx11.$O: $(GR_X11_)grx11.c $(GR_X11_)grx11.h + $(CC) $(CFLAGS) $(GRAPH_INCLUDES:%=$I%) $I$(GR_X11) \ + $(X11_INCLUDE:%=$I%) $T$@ $< +endif + + + +